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