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