WIN32 files lock support.
[idzebra-moved-to-github.git] / index / lockidx.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: lockidx.c,v $
7  * Revision 1.12  1997-09-25 14:54:43  adam
8  * WIN32 files lock support.
9  *
10  * Revision 1.11  1997/09/17 12:19:15  adam
11  * Zebra version corresponds to YAZ version 1.4.
12  * Changed Zebra server so that it doesn't depend on global common_resource.
13  *
14  * Revision 1.10  1997/09/09 13:38:07  adam
15  * Partial port to WIN95/NT.
16  *
17  * Revision 1.9  1997/09/04 13:58:04  adam
18  * Added O_BINARY for open calls.
19  *
20  * Revision 1.8  1997/02/12 20:39:46  adam
21  * Implemented options -f <n> that limits the log to the first <n>
22  * records.
23  * Changed some log messages also.
24  *
25  * Revision 1.7  1996/10/29 14:08:13  adam
26  * Uses resource lockDir instead of lockPath.
27  *
28  * Revision 1.6  1996/03/26 16:01:13  adam
29  * New setting lockPath: directory of various lock files.
30  *
31  * Revision 1.5  1995/12/13  08:46:09  adam
32  * Locking uses F_WRLCK and F_RDLCK again!
33  *
34  * Revision 1.4  1995/12/12  16:00:57  adam
35  * System call sync(2) used after update/commit.
36  * Locking (based on fcntl) uses F_EXLCK and F_SHLCK instead of F_WRLCK
37  * and F_RDLCK.
38  *
39  * Revision 1.3  1995/12/11  11:43:29  adam
40  * Locking based on fcntl instead of flock.
41  * Setting commitEnable removed. Command line option -n can be used to
42  * prevent commit if commit setting is defined in the configuration file.
43  *
44  * Revision 1.2  1995/12/08  16:22:54  adam
45  * Work on update while servers are running. Three lock files introduced.
46  * The servers reload their registers when necessary, but they don't
47  * reestablish result sets yet.
48  *
49  * Revision 1.1  1995/12/07  17:38:47  adam
50  * Work locking mechanisms for concurrent updates/commit.
51  *
52  */
53 #include <stdio.h>
54 #include <assert.h>
55 #ifdef WINDOWS
56 #include <io.h>
57 #else
58 #include <unistd.h>
59 #endif
60 #include <fcntl.h>
61 #include <string.h>
62 #include <errno.h>
63
64 #include "index.h"
65
66 static ZebraLockHandle server_lock_main = NULL;
67 static ZebraLockHandle server_lock_cmt = NULL;
68 static ZebraLockHandle server_lock_org = NULL;
69
70 int zebraIndexWait (int commitPhase)
71 {
72     char pathPrefix[1024];
73     char path[1024];
74     ZebraLockHandle h;
75     
76     zebraLockPrefix (common_resource, pathPrefix);
77
78     if (server_lock_cmt)
79         zebra_unlock (server_lock_cmt);
80     else
81     {
82         sprintf (path, "%s%s", pathPrefix, FNAME_COMMIT_LOCK);
83         server_lock_cmt = zebra_lock_create (path, 1);
84         if (!server_lock_cmt)
85         {
86             logf (LOG_WARN|LOG_ERRNO, "cannot create lock %s", path);
87             return -1;
88         }
89     }
90     if (server_lock_org)
91         zebra_unlock (server_lock_org);
92     else
93     {
94         sprintf (path, "%s%s", pathPrefix, FNAME_ORG_LOCK);
95         server_lock_org = zebra_lock_create (path, 1);
96         if (!server_lock_org)
97         {
98             logf (LOG_WARN|LOG_ERRNO, "cannot create lock %s", path);
99             return -1;
100         }
101     }
102     if (commitPhase)
103         h = server_lock_cmt;
104     else
105         h = server_lock_org;
106     if (zebra_lock_nb (h))
107     {
108 #ifndef WINDOWS
109         if (errno != EWOULDBLOCK)
110         {
111             logf (LOG_FATAL|LOG_ERRNO, "flock");
112             exit (1);
113         }
114 #endif
115         if (commitPhase)
116             logf (LOG_LOG, "Waiting for lock cmt");
117         else
118             logf (LOG_LOG, "Waiting for lock org");
119         if (zebra_lock (h) == -1)
120         {
121             logf (LOG_FATAL, "flock");
122             exit (1);
123         }
124     }
125     zebra_unlock (h);
126     return 0;
127 }
128
129
130 void zebraIndexLockMsg (const char *str)
131 {
132     char path[1024];
133     char pathPrefix[1024];
134     int l, r, fd;
135
136     assert (server_lock_main);
137     fd = zebra_lock_fd (server_lock_main);
138     lseek (fd, 0L, SEEK_SET);
139     l = strlen(str);
140     r = write (fd, str, l);
141     if (r != l)
142     {
143         logf (LOG_FATAL|LOG_ERRNO, "write lock file");
144         exit (1);
145     }
146     zebraLockPrefix (common_resource, pathPrefix);
147     sprintf (path, "%s%s", pathPrefix, FNAME_TOUCH_TIME);
148     fd = creat (path, 0666);
149     close (fd);
150 }
151
152 void zebraIndexUnlock (void)
153 {
154     char path[1024];
155     char pathPrefix[1024];
156
157     zebraLockPrefix (common_resource, pathPrefix);
158     sprintf (path, "%s%s", pathPrefix, FNAME_MAIN_LOCK);
159     unlink (path);
160 }
161
162 void zebraIndexLock (BFiles bfs, int commitNow, const char *rval)
163 {
164     char path[1024];
165     char pathPrefix[1024];
166     char buf[256];
167     int r;
168
169     if (server_lock_main)
170         return ;
171     zebraLockPrefix (common_resource, pathPrefix);
172     sprintf (path, "%s%s", pathPrefix, FNAME_MAIN_LOCK);
173     while (1)
174     {
175         server_lock_main = zebra_lock_create (path, 2);
176         if (!server_lock_main)
177         {
178             server_lock_main = zebra_lock_create (path, 1);
179             if (!server_lock_main)
180             {
181                 if (errno == ENOENT)
182                     continue;
183                 logf (LOG_FATAL|LOG_ERRNO, "open %s", path);
184                 exit (1);
185             }
186             if (zebra_lock_nb (server_lock_main) == -1)
187             {
188 #ifdef WINDOWS
189                 logf (LOG_LOG, "waiting for other index process");
190                 zebra_lock (server_lock_main);
191                 zebra_unlock (server_lock_main);
192                 zebra_lock_destroy (server_lock_main);
193                 continue;
194 #else
195                 if (errno == EWOULDBLOCK)
196                 {
197                     logf (LOG_LOG, "waiting for other index process");
198                     zebra_lock (server_lock_main);
199                     zebra_unlock (server_lock_main);
200                     zebra_lock_destroy (server_lock_main);
201                     continue;
202                 }
203                 else
204                 {
205                     logf (LOG_FATAL|LOG_ERRNO, "flock %s", path);
206                     exit (1);
207                 }
208 #endif
209             }
210             else
211             {
212                 int fd = zebra_lock_fd (server_lock_main);
213
214                 logf (LOG_WARN, "unlocked %s", path);
215                 r = read (fd, buf, 256);
216                 if (r == 0)
217                 {
218                     logf (LOG_WARN, "zero length %s", path);
219                     zebra_lock_destroy (server_lock_main);
220                     unlink (path);
221                     continue;
222                 }
223                 else if (r == -1)
224                 {
225                     logf (LOG_FATAL|LOG_ERRNO, "read %s", path);
226                     exit (1);
227                 }
228                 if (*buf == 'r')
229                 {
230                     logf (LOG_WARN, "previous transaction didn't"
231                           " reach commit");
232                     zebra_lock_destroy (server_lock_main);
233                     bf_commitClean (bfs, rval);
234                     unlink (path);
235                     continue;
236                 }
237                 else if (*buf == 'd')
238                 {
239                     logf (LOG_WARN, "commit file wan't deleted after commit");
240                     zebra_lock_destroy (server_lock_main);
241                     bf_commitClean (bfs, rval);
242                     unlink (path);
243                     continue;
244                 }                    
245                 else if (*buf == 'w')
246                 {
247                     logf (LOG_WARN, "your index may be inconsistent");
248                     exit (1);
249                 }
250                 else if (*buf == 'c')
251                 {
252                     if (commitNow)
253                     {
254                         unlink (path);
255                         zebra_lock_destroy (server_lock_main);
256                         continue;
257                     }
258                     logf (LOG_FATAL, "previous transaction didn't"
259                           " finish commit. Commit now!");
260                     exit (1);
261                 }
262                 else 
263                 {
264                     logf (LOG_FATAL, "unknown id 0x%02x in %s", *buf,
265                           path);
266                     exit (1);
267                 }
268             }
269         }
270         else
271             break;
272     }
273     zebra_lock (server_lock_main);
274 }
275