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