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
40void
41grn_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
53grn_bool
54grn_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
94void
95grn_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
115void
116grn_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