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