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