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