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