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