pull-prototypes-to-head-20020821
[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("$Header$");
14
15 #include <afs/stds.h>
16 #include <sys/types.h>
17 #ifdef AFS_NT40_ENV
18 #include <winsock2.h>
19 #include <afsutil.h>
20 #else
21 #include <sys/file.h>
22 #include <netdb.h>
23 #include <netinet/in.h>
24 #endif
25 #include <time.h>
26 #include <stdio.h>
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #else
30 #ifdef HAVE_STRINGS_H
31 #include <strings.h>
32 #endif
33 #endif
34 #include <rx/xdr.h>
35 #include <rx/rx.h>
36 #include <lock.h>
37 #include "ubik.h"
38 #include "utst_int.h"
39
40
41 /* useful globals */
42 struct ubik_dbase *dbase;
43 afs_int32 sleepTime;
44
45 SAMPLE_Inc(rxconn)
46 struct rx_connection    *rxconn;
47 {
48     afs_int32 code, temp;
49     struct ubik_trans   *tt;
50     struct timeval tv;
51
52     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
53     if (code)
54         return code;
55     printf("about to set lock\n");
56     /* now set database locks.  Must do this or people may read uncommitted
57           data.  Note that we're just setting a lock at position 1, which is
58 this program's convention for locking the whole database */
59     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
60     printf("now have lock\n");
61     if (code) {
62         ubik_AbortTrans(tt);
63         return code;
64     }
65     /* sleep for a little while to make it possible for us to test for some
66         race conditions */
67     if (sleepTime) {
68         tv.tv_sec = sleepTime;
69         tv.tv_usec = 0;
70         IOMGR_Select(0, 0, 0, 0, &tv);
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     }
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     }
135     else if (code) {
136         ubik_AbortTrans(tt);
137         return code;
138     }
139     *gnumber = temp;
140     /* end the transaction, automatically releasing locks */
141     code = ubik_EndTrans(tt);
142     return code;
143 }
144
145
146 SAMPLE_QGet(rxconn, gnumber)
147 struct rx_connection    *rxconn;
148 afs_int32 *gnumber;
149 {
150     afs_int32 code, temp;
151     struct ubik_trans   *tt;
152     struct timeval tv;
153
154     /* start with a read transaction, since we're only going to do read
155           operations in this transaction. */
156     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
157     if (code)
158         return code;
159     printf("about to set lock\n");
160     /* obtain a read lock, so we don't read data the other guy is writing */
161     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
162     printf("now have lock\n");
163     if (code) {
164         ubik_AbortTrans(tt);
165         return code;
166     }
167     /* sleep to allow races */
168     if (sleepTime) {
169         tv.tv_sec = sleepTime;
170         tv.tv_usec = 0;
171         IOMGR_Select(0, 0, 0, 0, &tv);
172     }
173     /* read the value */
174     code = ubik_Read(tt, &temp, sizeof(afs_int32));
175     if (code == UEOF) {
176         /* premature eof, use 0 */
177         temp = 0;
178     }
179     else if (code) {
180         ubik_AbortTrans(tt);
181         return code;
182     }
183     *gnumber = temp;
184     /* end the transaction, automatically releasing locks */
185     code = ubik_EndTrans(tt);
186     return code;
187 }
188
189
190 SAMPLE_Trun(rxconn)
191 struct rx_connection    *rxconn;
192 {
193     afs_int32 code;
194     struct ubik_trans   *tt;
195     struct timeval tv;
196
197     /* truncation operation requires a write transaction, too */
198     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
199     if (code) return code;
200     printf("about to set lock\n");
201     /* lock the database */
202     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
203     printf("now have lock\n");
204     if (code) {
205         ubik_AbortTrans(tt);
206         return code;
207     }
208     if (sleepTime) {
209         tv.tv_sec = sleepTime;
210         tv.tv_usec = 0;
211         IOMGR_Select(0, 0, 0, 0, &tv);
212     }
213     /* shrink the file */
214     code = ubik_Truncate(tt, 0);
215     if (code) {
216         ubik_AbortTrans(tt);
217         return code;
218     }
219     /* commit */
220     code = ubik_EndTrans(tt);
221     return code;
222 }
223
224
225 SAMPLE_Test(rxconn)
226 struct rx_connection    *rxconn;
227 {
228     afs_int32 code, temp;
229     struct ubik_trans   *tt;
230     struct timeval tv;
231
232     /* first start a new transaction.  Must be a write transaction since
233       we're going to change some data (with ubik_Write) */
234     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
235     if (code) 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     }
259     else if (code) {
260         ubik_AbortTrans(tt);
261         return code;
262     }
263     ubik_AbortTrans(tt);    /* surprise! pretend something went wrong */
264     return code;
265 }
266
267
268 #include "AFS_component_version_number.c"
269
270 main(argc, argv)
271     int argc;
272     char **argv; {
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 = ubik_ServerInit (myHost, htons(3000), serverList, dbfileName,
317                             &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 }