1 /* -*- c-basic-offset: 2 -*- */
2 /*
3 Copyright(C) 2017 Brazil
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License version 2.1 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
17 */
18
19 #include "grn_file_lock.h"
20 #include "grn_ctx.h"
21
22 #include <sys/stat.h>
23
24 #ifdef WIN32
25 # include <io.h>
26 # include <share.h>
27 #else /* WIN32 */
28 # include <sys/types.h>
29 # include <fcntl.h>
30 #endif /* WIN32 */
31
32 #ifdef WIN32
33 # define GRN_FILE_LOCK_IS_INVALID(file_lock) \
34 ((file_lock)->handle == INVALID_HANDLE_VALUE)
35 #else /* WIN32 */
36 # define GRN_FILE_LOCK_IS_INVALID(file_lock) \
37 ((file_lock)->fd == -1)
38 #endif /* WIN32 */
39
40 void
grn_file_lock_init(grn_ctx * ctx,grn_file_lock * file_lock,const char * path)41 grn_file_lock_init(grn_ctx *ctx,
42 grn_file_lock *file_lock,
43 const char *path)
44 {
45 file_lock->path = path;
46 #ifdef WIN32
47 file_lock->handle = INVALID_HANDLE_VALUE;
48 #else /* WIN32 */
49 file_lock->fd = -1;
50 #endif /* WIN32 */
51 }
52
53 grn_bool
grn_file_lock_acquire(grn_ctx * ctx,grn_file_lock * file_lock,int timeout,const char * error_message_tag)54 grn_file_lock_acquire(grn_ctx *ctx,
55 grn_file_lock *file_lock,
56 int timeout,
57 const char *error_message_tag)
58 {
59 int i;
60 int n_lock_tries = timeout;
61
62 if (!file_lock->path) {
63 return GRN_TRUE;
64 }
65
66 for (i = 0; i < n_lock_tries; i++) {
67 #ifdef WIN32
68 file_lock->handle = CreateFile(file_lock->path,
69 GENERIC_READ | GENERIC_WRITE,
70 0,
71 NULL,
72 CREATE_ALWAYS,
73 FILE_ATTRIBUTE_NORMAL,
74 NULL);
75 #else /* WIN32 */
76 file_lock->fd = open(file_lock->path, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
77 #endif
78 if (!GRN_FILE_LOCK_IS_INVALID(file_lock)) {
79 break;
80 }
81 grn_nanosleep(GRN_LOCK_WAIT_TIME_NANOSECOND);
82 }
83
84 if (GRN_FILE_LOCK_IS_INVALID(file_lock)) {
85 ERR(GRN_NO_LOCKS_AVAILABLE,
86 "%s failed to acquire lock: <%s>",
87 error_message_tag, file_lock->path);
88 return GRN_FALSE;
89 } else {
90 return GRN_TRUE;
91 }
92 }
93
94 void
grn_file_lock_release(grn_ctx * ctx,grn_file_lock * file_lock)95 grn_file_lock_release(grn_ctx *ctx, grn_file_lock *file_lock)
96 {
97 if (GRN_FILE_LOCK_IS_INVALID(file_lock)) {
98 return;
99 }
100
101 #ifdef WIN32
102 CloseHandle(file_lock->handle);
103 DeleteFile(file_lock->path);
104
105 file_lock->handle = INVALID_HANDLE_VALUE;
106 #else /* WIN32 */
107 close(file_lock->fd);
108 unlink(file_lock->path);
109
110 file_lock->fd = -1;
111 #endif /* WIN32 */
112 file_lock->path = NULL;
113 }
114
115 void
grn_file_lock_fin(grn_ctx * ctx,grn_file_lock * file_lock)116 grn_file_lock_fin(grn_ctx *ctx, grn_file_lock *file_lock)
117 {
118 if (!GRN_FILE_LOCK_IS_INVALID(file_lock)) {
119 grn_file_lock_release(ctx, file_lock);
120 }
121 }
122