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