kill-ubik-pthread-env-20080718
[openafs.git] / src / ubik / utst_server.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #include <afs/stds.h>
17 #include <sys/types.h>
18 #ifdef AFS_NT40_ENV
19 #include <winsock2.h>
20 #include <afsutil.h>
21 #else
22 #include <sys/file.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #endif
26 #include <time.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <rx/xdr.h>
30 #include <rx/rx.h>
31 #include <lock.h>
32 #include "ubik.h"
33 #include "utst_int.h"
34
35
36 /* useful globals */
37 struct ubik_dbase *dbase;
38 afs_int32 sleepTime;
39
40 SAMPLE_Inc(rxconn)
41      struct rx_connection *rxconn;
42 {
43     afs_int32 code, temp;
44     struct ubik_trans *tt;
45     struct timeval tv;
46
47     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
48     if (code)
49         return code;
50     printf("about to set lock\n");
51     /* now set database locks.  Must do this or people may read uncommitted
52      * data.  Note that we're just setting a lock at position 1, which is
53      * this program's convention for locking the whole database */
54     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
55     printf("now have lock\n");
56     if (code) {
57         ubik_AbortTrans(tt);
58         return code;
59     }
60     /* sleep for a little while to make it possible for us to test for some
61      * race conditions */
62     if (sleepTime) {
63         tv.tv_sec = sleepTime;
64         tv.tv_usec = 0;
65 #ifdef AFS_PTHREAD_ENV
66         select(0, 0, 0, 0, &tv);
67 #else
68         IOMGR_Select(0, 0, 0, 0, &tv);
69 #endif
70     }
71     /* read the original value */
72     code = ubik_Read(tt, &temp, sizeof(afs_int32));
73     if (code == UEOF) {
74         /* short read */
75         temp = 0;
76     } else if (code) {
77         ubik_AbortTrans(tt);
78         return code;
79     }
80     temp++;                     /* bump the value here */
81     /* reset the file pointer back to where it was before the read */
82     code = ubik_Seek(tt, 0, 0);
83     if (code) {
84         ubik_AbortTrans(tt);
85         return code;
86     }
87     /* write the data back */
88     code = ubik_Write(tt, &temp, sizeof(afs_int32));
89     if (code) {
90         ubik_AbortTrans(tt);
91         return code;
92     }
93     /* finally, we commit the transaction */
94     code = ubik_EndTrans(tt);
95     temp = 0;
96     return code;
97 }
98
99
100 SAMPLE_Get(rxconn, gnumber)
101      struct rx_connection *rxconn;
102      afs_int32 *gnumber;
103 {
104     afs_int32 code, temp;
105     struct ubik_trans *tt;
106     struct timeval tv;
107
108     /* start with a read transaction, since we're only going to do read
109      * operations in this transaction. */
110     code = ubik_BeginTrans(dbase, UBIK_READTRANS, &tt);
111     if (code)
112         return code;
113     printf("about to set lock\n");
114     /* obtain a read lock, so we don't read data the other guy is writing */
115     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
116     printf("now have lock\n");
117     if (code) {
118         ubik_AbortTrans(tt);
119         return code;
120     }
121     /* sleep to allow races */
122     if (sleepTime) {
123         tv.tv_sec = sleepTime;
124         tv.tv_usec = 0;
125 #ifdef AFS_PTHREAD_ENV
126         select(0, 0, 0, 0, &tv);
127 #else
128         IOMGR_Select(0, 0, 0, 0, &tv);
129 #endif
130     }
131     /* read the value */
132     code = ubik_Read(tt, &temp, sizeof(afs_int32));
133     if (code == UEOF) {
134         /* premature eof, use 0 */
135         temp = 0;
136     } else if (code) {
137         ubik_AbortTrans(tt);
138         return code;
139     }
140     *gnumber = temp;
141     /* end the transaction, automatically releasing locks */
142     code = ubik_EndTrans(tt);
143     return code;
144 }
145
146
147 SAMPLE_QGet(rxconn, gnumber)
148      struct rx_connection *rxconn;
149      afs_int32 *gnumber;
150 {
151     afs_int32 code, temp;
152     struct ubik_trans *tt;
153     struct timeval tv;
154
155     /* start with a read transaction, since we're only going to do read
156      * operations in this transaction. */
157     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
158     if (code)
159         return code;
160     printf("about to set lock\n");
161     /* obtain a read lock, so we don't read data the other guy is writing */
162     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
163     printf("now have lock\n");
164     if (code) {
165         ubik_AbortTrans(tt);
166         return code;
167     }
168     /* sleep to allow races */
169     if (sleepTime) {
170         tv.tv_sec = sleepTime;
171         tv.tv_usec = 0;
172 #ifdef AFS_PTHREAD_ENV
173         select(0, 0, 0, 0, &tv);
174 #else
175         IOMGR_Select(0, 0, 0, 0, &tv);
176 #endif
177     }
178     /* read the value */
179     code = ubik_Read(tt, &temp, sizeof(afs_int32));
180     if (code == UEOF) {
181         /* premature eof, use 0 */
182         temp = 0;
183     } else if (code) {
184         ubik_AbortTrans(tt);
185         return code;
186     }
187     *gnumber = temp;
188     /* end the transaction, automatically releasing locks */
189     code = ubik_EndTrans(tt);
190     return code;
191 }
192
193
194 SAMPLE_Trun(rxconn)
195      struct rx_connection *rxconn;
196 {
197     afs_int32 code;
198     struct ubik_trans *tt;
199     struct timeval tv;
200
201     /* truncation operation requires a write transaction, too */
202     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
203     if (code)
204         return code;
205     printf("about to set lock\n");
206     /* lock the database */
207     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
208     printf("now have lock\n");
209     if (code) {
210         ubik_AbortTrans(tt);
211         return code;
212     }
213     if (sleepTime) {
214         tv.tv_sec = sleepTime;
215         tv.tv_usec = 0;
216 #ifdef AFS_PTHREAD_ENV
217         select(0, 0, 0, 0, &tv);
218 #else
219         IOMGR_Select(0, 0, 0, 0, &tv);
220 #endif
221     }
222     /* shrink the file */
223     code = ubik_Truncate(tt, 0);
224     if (code) {
225         ubik_AbortTrans(tt);
226         return code;
227     }
228     /* commit */
229     code = ubik_EndTrans(tt);
230     return code;
231 }
232
233
234 SAMPLE_Test(rxconn)
235      struct rx_connection *rxconn;
236 {
237     afs_int32 code, temp;
238     struct ubik_trans *tt;
239     struct timeval tv;
240
241     /* first start a new transaction.  Must be a write transaction since
242      * we're going to change some data (with ubik_Write) */
243     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
244     if (code)
245         return code;
246     printf("about to set lock\n");
247     /* now set database locks.  Must do this or people may read uncommitted
248      * data.  Note that we're just setting a lock at position 1, which is
249      * this program's convention for locking the whole database */
250     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
251     printf("now have lock\n");
252     if (code) {
253         ubik_AbortTrans(tt);
254         return code;
255     }
256     /* sleep for a little while to make it possible for us to test for some
257      * race conditions */
258     if (sleepTime) {
259         tv.tv_sec = sleepTime;
260         tv.tv_usec = 0;
261 #ifdef AFS_PTHREAD_ENV
262         select(0, 0, 0, 0, &tv);
263 #else
264         IOMGR_Select(0, 0, 0, 0, &tv);
265 #endif
266     }
267     /* read the original value */
268     code = ubik_Read(tt, &temp, sizeof(afs_int32));
269     if (code == UEOF) {
270         printf("short read, using 0\n");
271         temp = 0;
272     } else if (code) {
273         ubik_AbortTrans(tt);
274         return code;
275     }
276     ubik_AbortTrans(tt);        /* surprise! pretend something went wrong */
277     return code;
278 }
279
280
281 #include "AFS_component_version_number.c"
282
283 main(argc, argv)
284      int argc;
285      char **argv;
286 {
287     register afs_int32 code, i;
288     afs_int32 serverList[MAXSERVERS];
289     afs_int32 myHost;
290     struct rx_service *tservice;
291     struct rx_securityClass *sc[2];
292     extern int SAMPLE_ExecuteRequest();
293     char dbfileName[128];
294
295     if (argc == 1) {
296         printf("usage: userver -servers <serverlist> {-sleep <sleeptime>}\n");
297         exit(0);
298     }
299 #ifdef AFS_NT40_ENV
300     /* initialize winsock */
301     if (afs_winsockInit() < 0)
302         return -1;
303 #endif
304     /* parse our own local arguments */
305     sleepTime = 0;
306     for (i = 1; i < argc; i++) {
307         if (strcmp(argv[i], "-sleep") == 0) {
308             if (i >= argc - 1) {
309                 printf("missing time in -sleep argument\n");
310                 exit(1);
311             }
312             sleepTime = atoi(argv[i + 1]);
313             i++;
314         }
315     }
316     /* call routine to parse command line -servers switch, filling in
317      * myHost and serverList arrays appropriately */
318     code = ubik_ParseServerList(argc, argv, &myHost, serverList);
319     if (code) {
320         printf("could not parse server list, code %d\n", code);
321         exit(1);
322     }
323     /* call ServerInit with the values from ParseServerList.  Also specify the
324      * name to use for the database files (/tmp/testdb), and the port (3000)
325      * for RPC requests.  ServerInit returns a pointer to the database (in
326      * dbase), which is required for creating new transactions */
327
328     sprintf(dbfileName, "%s/testdb", gettmpdir());
329
330     code =
331         ubik_ServerInit(myHost, htons(3000), serverList, dbfileName, &dbase);
332
333     if (code) {
334         printf("ubik init failed with code %d\n", code);
335         return;
336     }
337
338     sc[0] = rxnull_NewServerSecurityObject();
339 #if 0
340     sc[1] = rxvab_NewServerSecurityObject("applexx", 0);
341 #endif
342     tservice = rx_NewService(0, USER_SERVICE_ID, "Sample", sc, 1 /*2 */ ,
343                              SAMPLE_ExecuteRequest);
344     if (tservice == (struct rx_service *)0) {
345         printf("Could not create SAMPLE rx service\n");
346         exit(3);
347     }
348     rx_SetMinProcs(tservice, 2);
349     rx_SetMaxProcs(tservice, 3);
350
351     rx_StartServer(1);          /* Why waste this idle process?? */
352 }