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-1301 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 |
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 |
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 |
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 |
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 | |