Write seq to yaz_log
[idzebra-moved-to-github.git] / util / tstflock.c
1 /*
2  * Copyright (C) 1995-2006, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: tstflock.c,v 1.12 2006-06-30 15:10:29 adam Exp $
6  */
7
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <yaz/test.h>
11 #include <yaz/log.h>
12
13 #if HAVE_SYS_STAT_H
14 #include <sys/stat.h>
15 #endif
16 #if HAVE_SYS_TYPES_H
17 #include <sys/types.h>
18 #endif
19 #if HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 #if HAVE_SYS_WAIT_H
23 #include <sys/wait.h>
24 #endif
25
26 #include <fcntl.h>
27
28 #if YAZ_POSIX_THREADS
29 #include <pthread.h>
30 #endif
31 #ifdef WIN32
32 #include <windows.h>
33 #include <process.h>
34 #endif
35
36 #include <idzebra/flock.h>
37 #include <string.h>
38
39 static char seq[1000];
40 static char *seqp = 0;
41
42 #define NUM_THREADS 100
43
44 int test_fd = 0;
45
46 static void small_sleep()
47 {
48 #ifdef WIN32
49     Sleep(50);
50 #else
51     sleep(1);
52 #endif
53 }
54
55 void *run_func(void *arg)
56 {
57     int i;
58     int *pdata = (int*) arg;
59     int use_write_lock = *pdata;
60     ZebraLockHandle lh = zebra_lock_create(0, "my.LCK");
61     for (i = 0; i<2; i++)
62     {
63         int write_lock = use_write_lock;
64
65         if (use_write_lock == 2) /* random lock */
66             write_lock = (rand() & 3) == 3 ? 1 : 0;
67             
68         if (write_lock)
69         {
70             zebra_lock_w(lh);
71
72             write(test_fd, "L", 1);
73             *seqp++ = 'L';
74             small_sleep();
75             *seqp++ = 'U';  
76             write(test_fd, "U", 1);
77           
78             zebra_unlock(lh);
79         }
80         else
81         {
82             zebra_lock_r(lh);
83             
84             write(test_fd, "l", 1);
85             *seqp++ = 'l';
86             small_sleep();
87             *seqp++ = 'u';
88             write(test_fd, "u", 1);
89             
90             zebra_unlock(lh);
91         }
92     }
93     zebra_lock_destroy(lh);
94     *pdata = 123;
95     return 0;
96 }
97
98 #ifdef WIN32
99 DWORD WINAPI ThreadProc(void *p)
100 {
101     run_func(p);
102     return 0;
103 }
104 #endif
105
106 static void tst_thread(int num, int write_flag)
107 {
108 #ifdef WIN32
109     HANDLE handles[NUM_THREADS];
110     DWORD dwThreadId[NUM_THREADS];
111 #endif
112 #if YAZ_POSIX_THREADS
113     pthread_t child_thread[NUM_THREADS];
114 #endif
115     int i, id[NUM_THREADS];
116
117     seqp = seq;
118     assert (num <= NUM_THREADS);
119     for (i = 0; i < num; i++)
120     {
121         id[i] = write_flag;
122 #if YAZ_POSIX_THREADS
123         pthread_create(&child_thread[i], 0 /* attr */, run_func, &id[i]);
124 #endif
125 #ifdef WIN32
126         if (1)
127         {
128             void *pData = &id[i];
129             handles[i] = CreateThread(
130                 NULL,              /* default security attributes */
131                 0,                 /* use default stack size */
132                 ThreadProc,        /* thread function */
133                 pData,             /* argument to thread function */
134                 0,                 /* use default creation flags */
135                 &dwThreadId[i]);   /* returns the thread identifier */
136         }
137
138 #endif
139     }
140 #if YAZ_POSIX_THREADS
141     for (i = 0; i<num; i++)
142         pthread_join(child_thread[i], 0);
143 #endif
144 #ifdef WIN32
145     WaitForMultipleObjects(num, handles, TRUE, INFINITE);
146 #endif
147     for (i = 0; i < num; i++)
148         YAZ_CHECK(id[i] == 123);
149     *seqp++ = '\0';
150     yaz_log(YLOG_LOG, "tst_thread(%d,%d) returns seq=%s", 
151             num, write_flag, seq);
152 }
153
154 static void tst()
155 {
156     tst_thread(4, 1); /* write locks */
157     if (1)
158     {
159         int i = 0;
160         while (seq[i])
161         {
162             YAZ_CHECK_EQ(seq[i], 'L');
163             YAZ_CHECK_EQ(seq[i+1], 'U');
164             i = i + 2;
165         }
166     }
167
168 #if 0
169     tst_thread(6, 0);  /* read locks */
170 #endif
171 #if 1
172     tst_thread(20, 2); /* random locks */
173 #endif
174 }
175
176 void fork_tst()
177 {
178 #if HAVE_SYS_WAIT_H
179     pid_t pid[2];
180     int i;
181
182     for (i = 0; i<2; i++)
183     {
184         pid[i] = fork();
185         if (!pid[i])
186         {
187             tst();
188             exit(0);
189         }
190     }
191     for (i = 0; i<2; i++)
192     {
193         int status;
194         waitpid(pid[i], &status, 0);
195         YAZ_CHECK(status == 0);
196     }
197 #else
198     tst();
199 #endif
200 }
201
202
203 int main(int argc, char **argv)
204 {
205     char logname[220];
206     YAZ_CHECK_INIT(argc, argv);
207
208     sprintf(logname, "%.200s.log", argv[0]);
209     yaz_log_init_file(logname);
210
211     yaz_log_time_format("%s:%!");
212
213     zebra_flock_init();
214
215     test_fd = open("tstflock.out", (O_BINARY|O_CREAT|O_RDWR), 0666);
216     YAZ_CHECK(test_fd != -1);
217     if (test_fd != -1)
218     {
219         fork_tst();
220     }
221     YAZ_CHECK_TERM;
222 }
223
224
225 /*
226  * Local variables:
227  * c-basic-offset: 4
228  * indent-tabs-mode: nil
229  * End:
230  * vim: shiftwidth=4 tabstop=8 expandtab
231  */
232