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