d063cdc3deaca8aa7f14ce7adf021657d5cc5b25
[invirt/third/libt4.git] / lock_tester.cc
1 //
2 // Lock server tester
3 //
4
5 #include "lock_protocol.h"
6 #include "lock_client.h"
7 #include "rpc/rpc.h"
8 #include <arpa/inet.h>
9 #include <vector>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include "lang/verify.h"
13 #include "lock_client_cache_rsm.h"
14 #include "tprintf.h"
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include "lock.h"
18
19 char tprintf_thread_prefix = 'c';
20
21 // must be >= 2
22 const int nt = 6; //XXX: lab1's rpc handlers are blocking. Since rpcs uses a thread pool of 10 threads, we cannot test more than 10 blocking rpc.
23 std::string dst;
24 lock_client_cache_rsm **lc = new lock_client_cache_rsm * [nt];
25 lock_protocol::lockid_t a = "1";
26 lock_protocol::lockid_t b = "2";
27 lock_protocol::lockid_t c = "3";
28
29 // check_grant() and check_release() check that the lock server
30 // doesn't grant the same lock to both clients.
31 // it assumes that lock names are distinct in the first byte.
32 int ct[256];
33 std::mutex count_mutex;
34
35 void
36 check_grant(lock_protocol::lockid_t lid)
37 {
38     lock ml(count_mutex);
39     int x = lid[0] & 0x0f;
40     if(ct[x] != 0){
41         fprintf(stderr, "error: server granted %s twice\n", lid.c_str());
42         fprintf(stdout, "error: server granted %s twice\n", lid.c_str());
43         exit(1);
44     }
45     ct[x] += 1;
46 }
47
48 void
49 check_release(lock_protocol::lockid_t lid)
50 {
51     lock ml(count_mutex);
52     int x = lid[0] & 0x0f;
53     if(ct[x] != 1){
54         fprintf(stderr, "error: client released un-held lock %s\n",  lid.c_str());
55         exit(1);
56     }
57     ct[x] -= 1;
58 }
59
60 void
61 test1(void)
62 {
63     tprintf ("acquire a release a acquire a release a\n");
64     lc[0]->acquire(a);
65     check_grant(a);
66     lc[0]->release(a);
67     check_release(a);
68     lc[0]->acquire(a);
69     check_grant(a);
70     lc[0]->release(a);
71     check_release(a);
72
73     tprintf ("acquire a acquire b release b release a\n");
74     lc[0]->acquire(a);
75     check_grant(a);
76     lc[0]->acquire(b);
77     check_grant(b);
78     lc[0]->release(b);
79     check_release(b);
80     lc[0]->release(a);
81     check_release(a);
82 }
83
84 void *
85 test2(void *x) 
86 {
87     int i = * (int *) x;
88
89     tprintf ("test2: client %d acquire a release a\n", i);
90     lc[i]->acquire(a);
91     tprintf ("test2: client %d acquire done\n", i);
92     check_grant(a);
93     sleep(1);
94     tprintf ("test2: client %d release\n", i);
95     check_release(a);
96     lc[i]->release(a);
97     tprintf ("test2: client %d release done\n", i);
98     return 0;
99 }
100
101 void *
102 test3(void *x)
103 {
104     int i = * (int *) x;
105
106     tprintf ("test3: client %d acquire a release a concurrent\n", i);
107     for (int j = 0; j < 10; j++) {
108         lc[i]->acquire(a);
109         check_grant(a);
110         tprintf ("test3: client %d got lock\n", i);
111         check_release(a);
112         lc[i]->release(a);
113     }
114     return 0;
115 }
116
117 void *
118 test4(void *x)
119 {
120     int i = * (int *) x;
121
122     tprintf ("test4: thread %d acquire a release a concurrent; same clnt\n", i);
123     for (int j = 0; j < 10; j++) {
124         lc[0]->acquire(a);
125         check_grant(a);
126         tprintf ("test4: thread %d on client 0 got lock\n", i);
127         check_release(a);
128         lc[0]->release(a);
129     }
130     return 0;
131 }
132
133 void *
134 test5(void *x)
135 {
136     int i = * (int *) x;
137
138     tprintf ("test5: client %d acquire a release a concurrent; same and diff clnt\n", i);
139     for (int j = 0; j < 10; j++) {
140         if (i < 5)  lc[0]->acquire(a);
141         else  lc[1]->acquire(a);
142         check_grant(a);
143         tprintf ("test5: client %d got lock\n", i);
144         check_release(a);
145         if (i < 5) lc[0]->release(a);
146         else lc[1]->release(a);
147     }
148     return 0;
149 }
150
151 int
152 main(int argc, char *argv[])
153 {
154     std::thread th[nt];
155     int test = 0;
156
157     setvbuf(stdout, NULL, _IONBF, 0);
158     setvbuf(stderr, NULL, _IONBF, 0);
159     srandom(getpid());
160
161     if(argc < 2) {
162         fprintf(stderr, "Usage: %s [host:]port [test]\n", argv[0]);
163         exit(1);
164     }
165
166     dst = argv[1]; 
167
168     if (argc > 2) {
169         test = atoi(argv[2]);
170         if(test < 1 || test > 5){
171             tprintf("Test number must be between 1 and 5\n");
172             exit(1);
173         }
174     }
175
176     tprintf("cache lock client\n");
177     for (int i = 0; i < nt; i++) lc[i] = new lock_client_cache_rsm(dst);
178
179     if(!test || test == 1){
180         test1();
181     }
182
183     if(!test || test == 2){
184         // test2
185         for (int i = 0; i < nt; i++) {
186             int *a = new int (i);
187             th[i] = std::thread(test2, a);
188         }
189         for (int i = 0; i < nt; i++) {
190             th[i].join();
191         }
192     }
193
194     if(!test || test == 3){
195         tprintf("test 3\n");
196
197         // test3
198         for (int i = 0; i < nt; i++) {
199             int *a = new int (i);
200             th[i] = std::thread(test3, a);
201         }
202         for (int i = 0; i < nt; i++) {
203             th[i].join();
204         }
205     }
206
207     if(!test || test == 4){
208         tprintf("test 4\n");
209
210         // test 4
211         for (int i = 0; i < 2; i++) {
212             int *a = new int (i);
213             th[i] = std::thread(test4, a);
214         }
215         for (int i = 0; i < 2; i++) {
216             th[i].join();
217         }
218     }
219
220     if(!test || test == 5){
221         tprintf("test 5\n");
222
223         // test 5
224
225         for (int i = 0; i < nt; i++) {
226             int *a = new int (i);
227             th[i] = std::thread(test5, a);
228         }
229         for (int i = 0; i < nt; i++) {
230             th[i].join();
231         }
232     }
233
234     tprintf ("%s: passed all tests successfully\n", argv[0]);
235
236 }