IDZEBRA  2.2.7
tstflock.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 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 
62 static char seq[1000];
63 static char *seqp = 0;
64 
65 #define NUM_THREADS 100
66 
67 #if YAZ_POSIX_THREADS
68 pthread_cond_t sleep_cond = PTHREAD_COND_INITIALIZER;
69 pthread_mutex_t sleep_mutex = PTHREAD_MUTEX_INITIALIZER;
70 #endif
71 
72 int test_fd = 0;
73 
74 static 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 
98 void *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  }
136  zebra_lock_destroy(lh);
137  *pdata = 123;
138  return 0;
139 }
140 
141 #ifdef WIN32
142 DWORD WINAPI ThreadProc(void *p)
143 {
144  run_func(p);
145  return 0;
146 }
147 #endif
148 
149 static 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 
197 static 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 
216 void 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 
242 int 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
void * run_func(void *arg)
Definition: tstflock.c:98
static void small_sleep(void)
Definition: tstflock.c:74