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