Use busy wait for file locking on NT
[idzebra-moved-to-github.git] / index / lockutil.c
1 /*
2  * Copyright (C) 1994-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: lockutil.c,v $
7  * Revision 1.12.2.1  2002-07-23 12:40:33  adam
8  * Use busy wait for file locking on NT
9  *
10  * Revision 1.12  1999/05/26 07:49:13  adam
11  * C++ compilation.
12  *
13  * Revision 1.11  1999/02/02 14:50:59  adam
14  * Updated WIN32 code specific sections. Changed header.
15  *
16  * Revision 1.10  1997/09/29 09:08:36  adam
17  * Revised locking system to be thread safe for the server.
18  *
19  * Revision 1.9  1997/09/25 14:54:43  adam
20  * WIN32 files lock support.
21  *
22  * Revision 1.8  1997/09/17 12:19:15  adam
23  * Zebra version corresponds to YAZ version 1.4.
24  * Changed Zebra server so that it doesn't depend on global common_resource.
25  *
26  * Revision 1.7  1997/09/09 13:38:08  adam
27  * Partial port to WIN95/NT.
28  *
29  * Revision 1.6  1996/10/29 14:08:14  adam
30  * Uses resource lockDir instead of lockPath.
31  *
32  * Revision 1.5  1996/03/26 16:01:13  adam
33  * New setting lockPath: directory of various lock files.
34  *
35  * Revision 1.4  1995/12/13  08:46:10  adam
36  * Locking uses F_WRLCK and F_RDLCK again!
37  *
38  * Revision 1.3  1995/12/12  16:00:57  adam
39  * System call sync(2) used after update/commit.
40  * Locking (based on fcntl) uses F_EXLCK and F_SHLCK instead of F_WRLCK
41  * and F_RDLCK.
42  *
43  * Revision 1.2  1995/12/11  11:43:29  adam
44  * Locking based on fcntl instead of flock.
45  * Setting commitEnable removed. Command line option -n can be used to
46  * prevent commit if commit setting is defined in the configuration file.
47  *
48  * Revision 1.1  1995/12/07  17:38:47  adam
49  * Work locking mechanisms for concurrent updates/commit.
50  *
51  */
52 #include <stdio.h>
53 #include <assert.h>
54 #include <string.h>
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <sys/types.h>
58 #ifdef WIN32
59 #include <io.h>
60 #include <sys/locking.h>
61 #else
62 #include <unistd.h>
63 #endif
64
65 #include "index.h"
66
67 struct zebra_lock_info {
68     int fd;
69     int excl_flag;
70 };
71
72 ZebraLockHandle zebra_lock_create (const char *name, int excl_flag)
73 {
74     ZebraLockHandle h = (ZebraLockHandle) xmalloc (sizeof(*h));
75     h->excl_flag = excl_flag;
76     h->fd = -1;
77     yaz_log (LOG_DEBUG, "zebra_lock_create %s %d begin", name, excl_flag);
78 #ifdef WIN32
79     if (!h->excl_flag)
80         h->fd = open (name, O_BINARY|O_RDONLY);
81     if (h->fd == -1)
82         h->fd = open (name, ((h->excl_flag > 1) ? O_EXCL : 0)|
83             (O_BINARY|O_CREAT|O_RDWR), 0666);
84 #else
85     h->fd= open (name, ((h->excl_flag > 1) ? O_EXCL : 0)|
86             (O_BINARY|O_CREAT|O_RDWR|O_SYNC), 0666);
87 #endif
88     if (h->fd == -1)
89     {
90         if (h->excl_flag <= 1)
91             logf (LOG_WARN|LOG_ERRNO, "open %s", name);
92         xfree (h);
93         return NULL;
94     }
95     yaz_log (LOG_DEBUG, "zebra_lock_create %s %d end", name, excl_flag);
96     return h;
97 }
98
99 void zebra_lock_destroy (ZebraLockHandle h)
100 {
101     if (!h)
102         return;
103     if (h->fd != -1)
104         close (h->fd);
105     xfree (h);
106 }
107
108 void zebra_lock_prefix (Res res, char *path)
109 {
110     char *lock_dir = res_get_def (res, "lockDir", "");
111
112     strcpy (path, lock_dir);
113     if (*path && path[strlen(path)-1] != '/')
114         strcat (path, "/");
115 }
116
117 #ifndef WIN32
118 static int unixLock (int fd, int type, int cmd)
119 {
120     struct flock area;
121     area.l_type = type;
122     area.l_whence = SEEK_SET;
123     area.l_len = area.l_start = 0L;
124     return fcntl (fd, cmd, &area);
125 }
126 #endif
127
128 int zebra_lock (ZebraLockHandle h)
129 {
130 #ifdef WIN32
131     int m = 10;
132     yaz_log(LOG_DEBUG, "lock begin");
133     while (_locking (h->fd, _LK_NBLCK, 1) != 0)
134     {
135         Sleep(m);
136         if (m > 1000)
137             m = m+100;
138         else
139             m = m * 2;
140     }
141     yaz_log(LOG_DEBUG, "lock end m=%d", m);
142     return 0;
143 #else
144     return unixLock (h->fd, h->excl_flag ? F_WRLCK : F_RDLCK, F_SETLKW);
145 #endif
146 }
147
148 int zebra_lock_nb (ZebraLockHandle h)
149 {
150 #ifdef WIN32
151     yaz_log(LOG_DEBUG, "lock_nb begin");
152     return _locking (h->fd, _LK_NBLCK, 1);
153     yaz_log(LOG_DEBUG, "lock_nb end");
154 #else
155     return unixLock (h->fd, h->excl_flag ? F_WRLCK : F_RDLCK, F_SETLK);
156 #endif
157 }
158
159 int zebra_unlock (ZebraLockHandle h)
160 {
161 #ifdef WIN32
162     return _locking (h->fd, _LK_UNLCK, 1);
163 #else
164     return unixLock (h->fd, F_UNLCK, F_SETLKW);
165 #endif
166 }
167
168 int zebra_lock_fd (ZebraLockHandle h)
169 {
170     return h->fd;
171 }