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