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