death to register
[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
14 #include <afs/stds.h>
15 #include <sys/types.h>
16 #ifdef AFS_NT40_ENV
17 #include <winsock2.h>
18 #include <afsutil.h>
19 #else
20 #include <sys/file.h>
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #endif
24 #include <time.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <rx/xdr.h>
28 #include <rx/rx.h>
29 #include <lock.h>
30 #include <afs/afsutil.h>
31 #include "ubik.h"
32 #include "utst_int.h"
33
34
35 /*! \name useful globals */
36 struct ubik_dbase *dbase;
37 afs_int32 sleepTime;
38 /*\}*/
39
40 int
41 SSAMPLE_Inc(struct rx_call *call)
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 int
100 SSAMPLE_Get(struct rx_call *call, afs_int32 *gnumber)
101 {
102     afs_int32 code, temp;
103     struct ubik_trans *tt;
104     struct timeval tv;
105
106     /* start with a read transaction, since we're only going to do read
107      * operations in this transaction. */
108     code = ubik_BeginTrans(dbase, UBIK_READTRANS, &tt);
109     if (code)
110         return code;
111     printf("about to set lock\n");
112     /* obtain a read lock, so we don't read data the other guy is writing */
113     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
114     printf("now have lock\n");
115     if (code) {
116         ubik_AbortTrans(tt);
117         return code;
118     }
119     /* sleep to allow races */
120     if (sleepTime) {
121         tv.tv_sec = sleepTime;
122         tv.tv_usec = 0;
123 #ifdef AFS_PTHREAD_ENV
124         select(0, 0, 0, 0, &tv);
125 #else
126         IOMGR_Select(0, 0, 0, 0, &tv);
127 #endif
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 int
145 SSAMPLE_QGet(struct rx_call *call, afs_int32 *gnumber)
146 {
147     afs_int32 code, temp;
148     struct ubik_trans *tt;
149     struct timeval tv;
150
151     /* start with a read transaction, since we're only going to do read
152      * operations in this transaction. */
153     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
154     if (code)
155         return code;
156     printf("about to set lock\n");
157     /* obtain a read lock, so we don't read data the other guy is writing */
158     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
159     printf("now have lock\n");
160     if (code) {
161         ubik_AbortTrans(tt);
162         return code;
163     }
164     /* sleep to allow races */
165     if (sleepTime) {
166         tv.tv_sec = sleepTime;
167         tv.tv_usec = 0;
168 #ifdef AFS_PTHREAD_ENV
169         select(0, 0, 0, 0, &tv);
170 #else
171         IOMGR_Select(0, 0, 0, 0, &tv);
172 #endif
173     }
174     /* read the value */
175     code = ubik_Read(tt, &temp, sizeof(afs_int32));
176     if (code == UEOF) {
177         /* premature eof, use 0 */
178         temp = 0;
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 int
190 SSAMPLE_Trun(struct rx_call *call)
191 {
192     afs_int32 code;
193     struct ubik_trans *tt;
194     struct timeval tv;
195
196     /* truncation operation requires a write transaction, too */
197     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
198     if (code)
199         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 #ifdef AFS_PTHREAD_ENV
212         select(0, 0, 0, 0, &tv);
213 #else
214         IOMGR_Select(0, 0, 0, 0, &tv);
215 #endif
216     }
217     /* shrink the file */
218     code = ubik_Truncate(tt, 0);
219     if (code) {
220         ubik_AbortTrans(tt);
221         return code;
222     }
223     /* commit */
224     code = ubik_EndTrans(tt);
225     return code;
226 }
227
228 int
229 SSAMPLE_Test(struct rx_call *call)
230 {
231     afs_int32 code, temp;
232     struct ubik_trans *tt;
233     struct timeval tv;
234
235     /* first start a new transaction.  Must be a write transaction since
236      * we're going to change some data (with ubik_Write) */
237     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
238     if (code)
239         return code;
240     printf("about to set lock\n");
241     /* now set database locks.  Must do this or people may read uncommitted
242      * data.  Note that we're just setting a lock at position 1, which is
243      * this program's convention for locking the whole database */
244     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
245     printf("now have lock\n");
246     if (code) {
247         ubik_AbortTrans(tt);
248         return code;
249     }
250     /* sleep for a little while to make it possible for us to test for some
251      * race conditions */
252     if (sleepTime) {
253         tv.tv_sec = sleepTime;
254         tv.tv_usec = 0;
255 #ifdef AFS_PTHREAD_ENV
256         select(0, 0, 0, 0, &tv);
257 #else
258         IOMGR_Select(0, 0, 0, 0, &tv);
259 #endif
260     }
261     /* read the original value */
262     code = ubik_Read(tt, &temp, sizeof(afs_int32));
263     if (code == UEOF) {
264         printf("short read, using 0\n");
265         temp = 0;
266     } else if (code) {
267         ubik_AbortTrans(tt);
268         return code;
269     }
270     ubik_AbortTrans(tt);        /* surprise! pretend something went wrong */
271     return code;
272 }
273
274
275 #include "AFS_component_version_number.c"
276
277 int
278 main(int argc, char **argv)
279 {
280     afs_int32 code, i;
281     afs_uint32 serverList[MAXSERVERS];
282     afs_uint32 myHost;
283     struct rx_service *tservice;
284     struct rx_securityClass *sc[2];
285     char dbfileName[128];
286
287     if (argc == 1) {
288         printf("usage: userver -servers <serverlist> {-sleep <sleeptime>}\n");
289         exit(0);
290     }
291 #ifdef AFS_NT40_ENV
292     /* initialize winsock */
293     if (afs_winsockInit() < 0)
294         return -1;
295 #endif
296     /* parse our own local arguments */
297     sleepTime = 0;
298     for (i = 1; i < argc; i++) {
299         if (strcmp(argv[i], "-sleep") == 0) {
300             if (i >= argc - 1) {
301                 printf("missing time in -sleep argument\n");
302                 exit(1);
303             }
304             sleepTime = atoi(argv[i + 1]);
305             i++;
306         }
307     }
308     /* call routine to parse command line -servers switch, filling in
309      * myHost and serverList arrays appropriately */
310     code = ubik_ParseServerList(argc, argv, &myHost, serverList);
311     if (code) {
312         printf("could not parse server list, code %d\n", code);
313         exit(1);
314     }
315     /* call ServerInit with the values from ParseServerList.  Also specify the
316      * name to use for the database files (/tmp/testdb), and the port (3000)
317      * for RPC requests.  ServerInit returns a pointer to the database (in
318      * dbase), which is required for creating new transactions */
319
320     sprintf(dbfileName, "%s/testdb", gettmpdir());
321
322     code =
323         ubik_ServerInit(myHost, htons(3000), serverList, dbfileName, &dbase);
324
325     if (code) {
326         printf("ubik init failed with code %d\n", code);
327         exit(1);
328     }
329
330     sc[0] = rxnull_NewServerSecurityObject();
331 #if 0
332     sc[1] = rxvab_NewServerSecurityObject("applexx", 0);
333 #endif
334     tservice = rx_NewService(0, USER_SERVICE_ID, "Sample", sc, 1 /*2 */ ,
335                              SAMPLE_ExecuteRequest);
336     if (tservice == (struct rx_service *)0) {
337         printf("Could not create SAMPLE rx service\n");
338         exit(3);
339     }
340     rx_SetMinProcs(tservice, 2);
341     rx_SetMaxProcs(tservice, 3);
342
343     rx_StartServer(1);          /* Why waste this idle process?? */
344     
345     return 0;
346 }