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