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