IDZEBRA 2.2.8
tstflock.c
Go to the documentation of this file.
1/* This file is part of the Zebra server.
2 Copyright (C) Index Data
3
4Zebra is free software; you can redistribute it and/or modify it under
5the terms of the GNU General Public License as published by the Free
6Software Foundation; either version 2, or (at your option) any later
7version.
8
9Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18*/
19
20#if HAVE_CONFIG_H
21#include <config.h>
22#endif
23#include <assert.h>
24#include <stdlib.h>
25#include <yaz/test.h>
26#include <yaz/log.h>
27#if HAVE_SYS_TIME_H
28#include <sys/time.h>
29#endif
30#include <time.h>
31
32#if HAVE_SYS_STAT_H
33#include <sys/stat.h>
34#endif
35#if HAVE_SYS_TYPES_H
36#include <sys/types.h>
37#endif
38#if HAVE_UNISTD_H
39#include <unistd.h>
40#endif
41#if HAVE_SYS_WAIT_H
42#include <sys/wait.h>
43#endif
44
45#include <fcntl.h>
46
47#ifdef WIN32
48#include <io.h>
49#endif
50
51#if YAZ_POSIX_THREADS
52#include <pthread.h>
53#endif
54#ifdef WIN32
55#include <windows.h>
56#include <process.h>
57#endif
58
59#include <idzebra/flock.h>
60#include <string.h>
61
62static char seq[1000];
63static char *seqp = 0;
64
65#define NUM_THREADS 100
66
67#if YAZ_POSIX_THREADS
68pthread_cond_t sleep_cond = PTHREAD_COND_INITIALIZER;
69pthread_mutex_t sleep_mutex = PTHREAD_MUTEX_INITIALIZER;
70#endif
71
72int test_fd = 0;
73
74static void small_sleep(void)
75{
76#ifdef WIN32
77 Sleep(2);
78#else
79#if YAZ_POSIX_THREADS
80 struct timespec abstime;
81 struct timeval now;
82
83 gettimeofday(&now, 0);
84 abstime.tv_sec = now.tv_sec;
85 abstime.tv_nsec = 1000000 + now.tv_usec * 1000;
86 if (abstime.tv_nsec > 1000000000) /* 1s = 1e9 ns */
87 {
88 abstime.tv_nsec -= 1000000000;
89 abstime.tv_sec++;
90 }
91 pthread_mutex_lock(&sleep_mutex);
92 pthread_cond_timedwait(&sleep_cond, &sleep_mutex, &abstime);
93 pthread_mutex_unlock(&sleep_mutex);
94#endif
95#endif
96}
97
98void *run_func(void *arg)
99{
100 int i;
101 int *pdata = (int*) arg;
102 int use_write_lock = *pdata;
103 ZebraLockHandle lh = zebra_lock_create(0, "my.LCK");
104 for (i = 0; i<2; i++)
105 {
106 int write_lock = use_write_lock;
107
108 if (use_write_lock == 2) /* random lock */
109 write_lock = (rand() & 3) == 3 ? 1 : 0;
110
111 if (write_lock)
112 {
113 zebra_lock_w(lh);
114
115 write(test_fd, "L", 1);
116 *seqp++ = 'L';
117 small_sleep();
118 *seqp++ = 'U';
119 write(test_fd, "U", 1);
120
121 zebra_unlock(lh);
122 }
123 else
124 {
125 zebra_lock_r(lh);
126
127 write(test_fd, "l", 1);
128 *seqp++ = 'l';
129 small_sleep();
130 *seqp++ = 'u';
131 write(test_fd, "u", 1);
132
133 zebra_unlock(lh);
134 }
135 }
137 *pdata = 123;
138 return 0;
139}
140
141#ifdef WIN32
142DWORD WINAPI ThreadProc(void *p)
143{
144 run_func(p);
145 return 0;
146}
147#endif
148
149static void tst_thread(int num, int write_flag)
150{
151#ifdef WIN32
152 HANDLE handles[NUM_THREADS];
153 DWORD dwThreadId[NUM_THREADS];
154#endif
155#if YAZ_POSIX_THREADS
156 pthread_t child_thread[NUM_THREADS];
157#endif
158 int i, id[NUM_THREADS];
159
160 seqp = seq;
161 assert (num <= NUM_THREADS);
162 for (i = 0; i < num; i++)
163 {
164 id[i] = write_flag;
165#if YAZ_POSIX_THREADS
166 pthread_create(&child_thread[i], 0 /* attr */, run_func, &id[i]);
167#endif
168#ifdef WIN32
169 if (1)
170 {
171 void *pData = &id[i];
172 handles[i] = CreateThread(
173 NULL, /* default security attributes */
174 0, /* use default stack size */
175 ThreadProc, /* thread function */
176 pData, /* argument to thread function */
177 0, /* use default creation flags */
178 &dwThreadId[i]); /* returns the thread identifier */
179 }
180
181#endif
182 }
183#if YAZ_POSIX_THREADS
184 for (i = 0; i<num; i++)
185 pthread_join(child_thread[i], 0);
186#endif
187#ifdef WIN32
188 WaitForMultipleObjects(num, handles, TRUE, INFINITE);
189#endif
190 for (i = 0; i < num; i++)
191 YAZ_CHECK(id[i] == 123);
192 *seqp++ = '\0';
193 yaz_log(YLOG_LOG, "tst_thread(%d,%d) returns seq=%s",
194 num, write_flag, seq);
195}
196
197static void tst(void)
198{
199 tst_thread(4, 1); /* write locks */
200 if (1)
201 {
202 int i = 0;
203 while (seq[i])
204 {
205 YAZ_CHECK_EQ(seq[i], 'L');
206 YAZ_CHECK_EQ(seq[i+1], 'U');
207 i = i + 2;
208 }
209 }
210
211 tst_thread(6, 0); /* read locks */
212
213 tst_thread(20, 2); /* random locks */
214}
215
216void fork_tst(void)
217{
218#if HAVE_SYS_WAIT_H
219 pid_t pid[2];
220 int i;
221
222 for (i = 0; i<2; i++)
223 {
224 pid[i] = fork();
225 if (!pid[i])
226 {
227 tst();
228 exit(0);
229 }
230 }
231 for (i = 0; i<2; i++)
232 {
233 int status;
234 waitpid(pid[i], &status, 0);
235 YAZ_CHECK(status == 0);
236 }
237#else
238 tst();
239#endif
240}
241
242int main(int argc, char **argv)
243{
244 YAZ_CHECK_INIT(argc, argv);
245 YAZ_CHECK_LOG();
246
247 /* ensure the flock system logs in our test */
248 yaz_log_init_level(yaz_log_mask_str("flock"));
249
251
252 test_fd = open("tstflock.out", (O_BINARY|O_CREAT|O_RDWR), 0666);
253 YAZ_CHECK(test_fd != -1);
254 if (test_fd != -1)
255 {
256 fork_tst();
257 }
258 YAZ_CHECK_TERM;
259}
260
261
262/*
263 * Local variables:
264 * c-basic-offset: 4
265 * c-file-style: "Stroustrup"
266 * indent-tabs-mode: nil
267 * End:
268 * vim: shiftwidth=4 tabstop=8 expandtab
269 */
270
#define O_BINARY
Definition agrep.c:46
ZebraLockHandle zebra_lock_create(const char *dir, const char *file)
Definition flock.c:106
void zebra_flock_init(void)
Definition flock.c:380
int zebra_lock_r(ZebraLockHandle h)
Definition flock.c:277
int zebra_lock_w(ZebraLockHandle h)
Definition flock.c:240
void zebra_lock_destroy(ZebraLockHandle h)
Definition flock.c:177
int zebra_unlock(ZebraLockHandle h)
Definition flock.c:313
static void tst_thread(int num, int write_flag)
Definition tstflock.c:149
int main(int argc, char **argv)
Definition tstflock.c:242
static char seq[1000]
Definition tstflock.c:62
static void tst(void)
Definition tstflock.c:197
void fork_tst(void)
Definition tstflock.c:216
static char * seqp
Definition tstflock.c:63
#define NUM_THREADS
Definition tstflock.c:65
int test_fd
Definition tstflock.c:72
static void small_sleep(void)
Definition tstflock.c:74
void * run_func(void *arg)
Definition tstflock.c:98