backup: Remove obsolete test programs
[openafs.git] / tests / common / servers.c
1 #include <afsconfig.h>
2 #include <afs/param.h>
3
4 #include <roken.h>
5
6 #ifdef HAVE_SYS_WAIT_H
7 #include <sys/wait.h>
8 #endif
9
10 #include <rx/rx.h>
11
12 #include <afs/authcon.h>
13 #include <afs/cellconfig.h>
14 #define UBIK_INTERNALS
15 #include <ubik.h>
16
17 #include <tests/tap/basic.h>
18
19 #include "common.h"
20
21 static void
22 check_startup(pid_t pid, char *log, int *a_started, int *a_stopped)
23 {
24     int status;
25     struct rx_connection *conn;
26     struct ubik_debug udebug;
27     afs_int32 isclone;
28     pid_t exited;
29     int code;
30
31     memset(&udebug, 0, sizeof(udebug));
32
33     opr_Assert(pid > 0);
34
35     exited = waitpid(pid, &status, WNOHANG);
36     if (exited < 0) {
37         opr_Assert(errno == ECHILD);
38     }
39
40     if (exited != 0) {
41         /* pid is no longer running; vlserver must have died during startup */
42         *a_stopped = 1;
43         return;
44     }
45
46     if (!afstest_file_contains(log, "Starting AFS vlserver")) {
47         /* vlserver hasn't logged the "Starting AFS vlserver" line yet, so it's
48          * presumably still starting up. */
49         return;
50     }
51
52     /*
53      * If we're going to write to the db, we also need to wait until recovery
54      * has the UBIK_RECHAVEDB state bit (without that, we won't be able to
55      * start write transactions). If we're just reading from the db, we
56      * wouldn't need to wait for this, but we don't know whether our caller
57      * will be writing to the db or not. It shouldn't take long for
58      * UBIK_RECHAVEDB to get set anyway, so just always check if it's been set
59      * (via VOTE_XDebug).
60      */
61
62     conn = rx_NewConnection(afstest_MyHostAddr(), htons(7003), VOTE_SERVICE_ID,
63                             rxnull_NewClientSecurityObject(), 0);
64     code = VOTE_XDebug(conn, &udebug, &isclone);
65     rx_DestroyConnection(conn);
66     if (code != 0) {
67         diag("VOTE_XDebug returned %d while waiting for vlserver startup",
68              code);
69         return;
70     }
71
72     if (udebug.amSyncSite && (udebug.recoveryState & UBIK_RECHAVEDB) != 0) {
73         /* Okay, it's set! We have finished startup. */
74         *a_started = 1;
75     }
76 }
77
78 /* Start up the VLserver, using the configuration in dirname, and putting our
79  * logs there too.
80  */
81
82 int
83 afstest_StartVLServer(char *dirname, pid_t *serverPid)
84 {
85     pid_t pid;
86     char *logPath;
87     int started = 0;
88     int stopped = 0;
89     int try;
90     FILE *fh;
91     int code = 0;
92
93     logPath = afstest_asprintf("%s/VLLog", dirname);
94
95     /* Create/truncate the log in advance (since we look at it to detect when
96      * the vlserver has started). */
97     fh = fopen(logPath, "w");
98     opr_Assert(fh != NULL);
99     fclose(fh);
100
101     pid = fork();
102     if (pid == -1) {
103         exit(1);
104         /* Argggggghhhhh */
105     } else if (pid == 0) {
106         char *binPath, *dbPath;
107
108         /* Child */
109         binPath = afstest_obj_path("src/tvlserver/vlserver");
110         dbPath = afstest_asprintf("%s/vldb", dirname);
111
112         execl(binPath, "vlserver",
113               "-logfile", logPath, "-database", dbPath, "-config", dirname, NULL);
114         fprintf(stderr, "Running %s failed\n", binPath);
115         exit(1);
116     }
117
118     /*
119      * Wait for the vlserver to startup. Try to check if the vlserver is ready
120      * by checking the log file and the urecovery_state (check_startup()), but
121      * if it's taking too long, just return success anyway. If the vlserver
122      * isn't ready yet, then the caller's tests may fail, but we can't wait
123      * forever.
124      */
125
126     diag("waiting for vlserver to startup");
127
128     usleep(5000); /* 5ms */
129     check_startup(pid, logPath, &started, &stopped);
130     for (try = 0; !started && !stopped; try++) {
131         if (try > 100 * 5) {
132             diag("waited too long for vlserver to finish starting up; "
133                  "proceeding anyway");
134             goto done;
135         }
136
137         usleep(1000 * 10); /* 10ms */
138         check_startup(pid, logPath, &started, &stopped);
139     }
140
141     if (stopped) {
142         fprintf(stderr, "vlserver died during startup\n");
143         code = -1;
144         goto done;
145     }
146
147     diag("vlserver started after try %d", try);
148
149  done:
150     *serverPid = pid;
151
152     free(logPath);
153
154     return code;
155 }
156
157 int
158 afstest_StopServer(pid_t serverPid)
159 {
160     int status;
161
162     kill(serverPid, SIGTERM);
163
164     if (waitpid(serverPid, &status, 0) < 0) {
165         sysbail("waitpid");
166     }
167
168     if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) {
169         fprintf(stderr, "Server died exited on signal %d\n", WTERMSIG(status));
170         return -1;
171     }
172     if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
173         fprintf(stderr, "Server exited with code %d\n", WEXITSTATUS(status));
174         return -1;
175     }
176     return 0;
177 }
178
179 int
180 afstest_StartTestRPCService(const char *configPath,
181                             pid_t signal_pid,
182                             u_short port,
183                             u_short serviceId,
184                             afs_int32 (*proc) (struct rx_call *))
185 {
186     struct afsconf_dir *dir;
187     struct rx_securityClass **classes;
188     afs_int32 numClasses;
189     int code;
190     struct rx_service *service;
191     struct afsconf_bsso_info bsso;
192
193     memset(&bsso, 0, sizeof(bsso));
194
195     dir = afsconf_Open(configPath);
196     if (dir == NULL) {
197         fprintf(stderr, "Server: Unable to open config directory\n");
198         return -1;
199     }
200
201     code = rx_Init(htons(port));
202     if (code != 0) {
203         fprintf(stderr, "Server: Unable to initialise RX\n");
204         return -1;
205     }
206
207     if (signal_pid != 0) {
208         kill(signal_pid, SIGUSR1);
209     }
210
211     bsso.dir = dir;
212     afsconf_BuildServerSecurityObjects_int(&bsso, &classes, &numClasses);
213     service = rx_NewService(0, serviceId, "test", classes, numClasses,
214                             proc);
215     if (service == NULL) {
216         fprintf(stderr, "Server: Unable to start to test service\n");
217         return -1;
218     }
219
220     rx_StartServer(1);
221
222     return 0; /* Not reached, we donated ourselves to StartServer */
223 }