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