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