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