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