afs.h: fix out of tree build failures
[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     waitpid(serverPid, &status, 0);
165
166     if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) {
167         fprintf(stderr, "Server died exited on signal %d\n", WTERMSIG(status));
168         return -1;
169     }
170     if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
171         fprintf(stderr, "Server exited with code %d\n", WEXITSTATUS(status));
172         return -1;
173     }
174     return 0;
175 }
176
177 int
178 afstest_StartTestRPCService(const char *configPath,
179                             pid_t signal_pid,
180                             u_short port,
181                             u_short serviceId,
182                             afs_int32 (*proc) (struct rx_call *))
183 {
184     struct afsconf_dir *dir;
185     struct rx_securityClass **classes;
186     afs_int32 numClasses;
187     int code;
188     struct rx_service *service;
189     struct afsconf_bsso_info bsso;
190
191     memset(&bsso, 0, sizeof(bsso));
192
193     dir = afsconf_Open(configPath);
194     if (dir == NULL) {
195         fprintf(stderr, "Server: Unable to open config directory\n");
196         return -1;
197     }
198
199     code = rx_Init(htons(port));
200     if (code != 0) {
201         fprintf(stderr, "Server: Unable to initialise RX\n");
202         return -1;
203     }
204
205     if (signal_pid != 0) {
206         kill(signal_pid, SIGUSR1);
207     }
208
209     bsso.dir = dir;
210     afsconf_BuildServerSecurityObjects_int(&bsso, &classes, &numClasses);
211     service = rx_NewService(0, serviceId, "test", classes, numClasses,
212                             proc);
213     if (service == NULL) {
214         fprintf(stderr, "Server: Unable to start to test service\n");
215         return -1;
216     }
217
218     rx_StartServer(1);
219
220     return 0; /* Not reached, we donated ourselves to StartServer */
221 }