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