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