death to register
[openafs.git] / src / tsalvaged / salvsync-debug.c
1 /*
2  * Copyright 2006, Sine Nomine Associates 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 /* Main program file. Define globals. */
11 #define MAIN 1
12
13 /*
14  * salvsync debug tool
15  */
16
17
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <dirent.h>
26 #include <sys/stat.h>
27 #include <time.h>
28 #include <errno.h>
29 #ifdef AFS_NT40_ENV
30 #include <io.h>
31 #include <WINNT/afsevent.h>
32 #else
33 #include <sys/param.h>
34 #include <sys/file.h>
35 #ifndef ITIMER_REAL
36 #include <sys/time.h>
37 #endif /* ITIMER_REAL */
38 #endif
39 #include <rx/xdr.h>
40 #include <afs/afsint.h>
41 #include <afs/assert.h>
42 #include <afs/dir.h>
43
44 #include <fcntl.h>
45
46 #ifndef AFS_NT40_ENV
47 #include <afs/osi_inode.h>
48 #endif
49
50 #include <afs/cmd.h>
51 #include <afs/afsutil.h>
52 #include <afs/fileutil.h>
53
54 #include <afs/nfs.h>
55 #include <lwp.h>
56 #include <lock.h>
57 #include <afs/ihandle.h>
58 #include <afs/vnode.h>
59 #include <afs/volume.h>
60 #include <afs/partition.h>
61 #include <afs/daemon_com.h>
62 #include <afs/salvsync.h>
63 #ifdef AFS_NT40_ENV
64 #include <pthread.h>
65 #endif
66
67 int VolumeChanged; /* hack to make dir package happy */
68
69
70 #ifndef AFS_DEMAND_ATTACH_FS
71 int
72 main(int argc, char ** argv)
73 {
74     fprintf(stderr, "*** salvsync-debug is only supported for OpenAFS builds with the demand-attach fileserver extension\n");
75     return -1;
76 }
77 #else /* AFS_DEMAND_ATTACH_FS */
78
79 struct salv_state {
80     afs_uint32 prio;
81     afs_uint32 volume;
82     char partName[16];
83 };
84
85 struct state {
86     afs_int32 reason;
87     struct salv_state * sop;
88 };
89
90 static int common_prolog(struct cmd_syndesc *, struct state *);
91 static int common_salv_prolog(struct cmd_syndesc *, struct state *);
92
93 static int do_salvop(struct state *, afs_int32 command, SYNC_response * res);
94
95 static char * response_code_to_string(afs_int32);
96 static char * command_code_to_string(afs_int32);
97 static char * reason_code_to_string(afs_int32);
98 static char * state_code_to_string(afs_int32);
99
100
101 static int OpStats(struct cmd_syndesc * as, void * rock);
102 static int OpSalvage(struct cmd_syndesc * as, void * rock);
103 static int OpCancel(struct cmd_syndesc * as, void * rock);
104 static int OpCancelAll(struct cmd_syndesc * as, void * rock);
105 static int OpRaisePrio(struct cmd_syndesc * as, void * rock);
106 static int OpQuery(struct cmd_syndesc * as, void * rock);
107
108
109 #ifndef AFS_NT40_ENV
110 #include "AFS_component_version_number.c"
111 #endif
112 #define MAX_ARGS 128
113
114 #define COMMON_PARMS_OFFSET    13
115 #define COMMON_PARMS(ts) \
116     cmd_Seek(ts, COMMON_PARMS_OFFSET); \
117     cmd_AddParm(ts, "-reason", CMD_SINGLE, CMD_OPTIONAL, "sync protocol reason code"); \
118     cmd_AddParm(ts, "-programtype", CMD_SINGLE, CMD_OPTIONAL, "program type code")
119
120 #define COMMON_SALV_PARMS_OFFSET    10
121 #define COMMON_SALV_PARMS(ts) \
122     cmd_Seek(ts, COMMON_SALV_PARMS_OFFSET); \
123     cmd_AddParm(ts, "-volumeid", CMD_SINGLE, 0, "volume id"); \
124     cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL, "partition name"); \
125     cmd_AddParm(ts, "-priority", CMD_SINGLE, CMD_OPTIONAL, "priority")
126
127 #define SALV_PARMS_DECL(ts) \
128     COMMON_SALV_PARMS(ts); \
129     COMMON_PARMS(ts)
130
131 #define COMMON_PARMS_DECL(ts) \
132     COMMON_PARMS(ts)
133
134 int
135 main(int argc, char **argv)
136 {
137     struct cmd_syndesc *ts;
138     int err = 0;
139
140     /* Initialize directory paths */
141     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
142 #ifdef AFS_NT40_ENV
143         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
144 #endif
145         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
146                 argv[0]);
147         exit(2);
148     }
149
150
151     ts = cmd_CreateSyntax("stats", OpStats, NULL, "get salvageserver statistics (SALVSYNC_NOP opcode)");
152     COMMON_PARMS_DECL(ts);
153     cmd_CreateAlias(ts, "nop");
154
155     ts = cmd_CreateSyntax("salvage", OpSalvage, NULL, "schedule a salvage (SALVSYNC_SALVAGE opcode)");
156     SALV_PARMS_DECL(ts);
157
158     ts = cmd_CreateSyntax("cancel", OpCancel, NULL, "cancel a salvage (SALVSYNC_CANCEL opcode)");
159     SALV_PARMS_DECL(ts);
160
161     ts = cmd_CreateSyntax("raiseprio", OpRaisePrio, NULL, "raise a salvage priority (SALVSYNC_RAISEPRIO opcode)");
162     SALV_PARMS_DECL(ts);
163     cmd_CreateAlias(ts, "rp");
164
165     ts = cmd_CreateSyntax("query", OpQuery, NULL, "query salvage status (SALVSYNC_QUERY opcode)");
166     SALV_PARMS_DECL(ts);
167     cmd_CreateAlias(ts, "qry");
168
169     ts = cmd_CreateSyntax("kill", OpCancelAll, NULL, "cancel all scheduled salvages (SALVSYNC_CANCELALL opcode)");
170     COMMON_PARMS_DECL(ts);
171
172     err = cmd_Dispatch(argc, argv);
173     exit(err);
174 }
175
176 static int
177 common_prolog(struct cmd_syndesc * as, struct state * state)
178 {
179     struct cmd_item *ti;
180     VolumePackageOptions opts;
181
182 #ifdef AFS_NT40_ENV
183     if (afs_winsockInit() < 0) {
184         Exit(1);
185     }
186 #endif
187
188     VOptDefaults(debugUtility, &opts);
189     if (VInitVolumePackage2(debugUtility, &opts)) {
190         /* VInitVolumePackage2 can fail on e.g. partition attachment errors,
191          * but we don't really care, since all we're doing is trying to use
192          * SALVSYNC */
193         fprintf(stderr, "errors encountered initializing volume package, but "
194                         "trying to continue anyway\n");
195     }
196     DInit(1);
197
198     if ((ti = as->parms[COMMON_PARMS_OFFSET].items)) {  /* -reason */
199         state->reason = atoi(ti->data);
200     }
201     if ((ti = as->parms[COMMON_PARMS_OFFSET+1].items)) {        /* -programtype */
202         if (!strcmp(ti->data, "fileServer")) {
203             programType = fileServer;
204         } else if (!strcmp(ti->data, "volumeUtility")) {
205             programType = volumeUtility;
206         } else if (!strcmp(ti->data, "salvager")) {
207             programType = salvager;
208         } else if (!strcmp(ti->data, "salvageServer")) {
209             programType = salvageServer;
210         } else if (!strcmp(ti->data, "volumeServer")) {
211             programType = volumeServer;
212         } else if (!strcmp(ti->data, "volumeSalvager")) {
213             programType = volumeSalvager;
214         } else {
215             programType = (ProgramType) atoi(ti->data);
216         }
217     }
218
219     VConnectSALV();
220
221     return 0;
222 }
223
224 static int
225 common_salv_prolog(struct cmd_syndesc * as, struct state * state)
226 {
227     struct cmd_item *ti;
228
229     state->sop = (struct salv_state *) calloc(1, sizeof(struct salv_state));
230     assert(state->sop != NULL);
231
232     if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET].items)) {     /* -volumeid */
233         state->sop->volume = atoi(ti->data);
234     } else {
235         fprintf(stderr, "required argument -volumeid not given\n");
236     }
237
238     if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET+1].items)) {   /* -partition */
239         strlcpy(state->sop->partName, ti->data, sizeof(state->sop->partName));
240     } else {
241         memset(state->sop->partName, 0, sizeof(state->sop->partName));
242     }
243
244     if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET+2].items)) {   /* -prio */
245         state->sop->prio = atoi(ti->data);
246     } else {
247         state->sop->prio = 0;
248     }
249
250     return 0;
251 }
252
253 static int
254 do_salvop(struct state * state, afs_int32 command, SYNC_response * res)
255 {
256     afs_int32 code;
257     SALVSYNC_response_hdr hdr_l, *hdr;
258     SYNC_response res_l;
259
260     if (!res) {
261         res = &res_l;
262         res->payload.len = sizeof(hdr_l);
263         res->payload.buf = hdr = &hdr_l;
264     } else {
265         hdr = (SALVSYNC_response_hdr *) res->payload.buf;
266     }
267
268     fprintf(stderr, "calling SALVSYNC_SalvageVolume with command code %d (%s)\n", 
269             command, command_code_to_string(command));
270
271     code = SALVSYNC_SalvageVolume(state->sop->volume,
272                                   state->sop->partName,
273                                   command,
274                                   state->reason,
275                                   state->sop->prio,
276                                   res);
277
278     switch (code) {
279     case SYNC_OK:
280     case SYNC_DENIED:
281         break;
282     default:
283         fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
284     }
285
286     fprintf(stderr, "SALVSYNC_SalvageVolume returned %d (%s)\n", code, response_code_to_string(code));
287     fprintf(stderr, "protocol response code was %d (%s)\n", 
288             res->hdr.response, response_code_to_string(res->hdr.response));
289     fprintf(stderr, "protocol reason code was %d (%s)\n", 
290             res->hdr.reason, reason_code_to_string(res->hdr.reason));
291
292     printf("state = {\n");
293     if (res->hdr.flags & SALVSYNC_FLAG_VOL_STATS_VALID) {
294         printf("\tstate = %d (%s)\n",
295                hdr->state, state_code_to_string(hdr->state));
296         printf("\tprio = %d\n", hdr->prio);
297     }
298     printf("\tsq_len = %d\n", hdr->sq_len);
299     printf("\tpq_len = %d\n", hdr->pq_len);
300     printf("}\n");
301
302     VDisconnectSALV();
303
304     return 0;
305 }
306
307 static char *
308 response_code_to_string(afs_int32 response)
309 {
310     switch (response) {
311     case SYNC_OK:
312         return "SYNC_OK";
313     case SYNC_DENIED:
314         return "SYNC_DENIED";
315     case SYNC_COM_ERROR:
316         return "SYNC_COM_ERROR";
317     case SYNC_BAD_COMMAND:
318         return "SYNC_BAD_COMMAND";
319     case SYNC_FAILED:
320         return "SYNC_FAILED";
321     default:
322         return "**UNKNOWN**";
323     }
324 }
325
326 static char *
327 command_code_to_string(afs_int32 command)
328 {
329     switch (command) {
330     case SYNC_COM_CHANNEL_CLOSE:
331         return "SYNC_COM_CHANNEL_CLOSE";
332     case SALVSYNC_NOP:
333         return "SALVSYNC_NOP";
334     case SALVSYNC_SALVAGE:
335         return "SALVSYNC_SALVAGE";
336     case SALVSYNC_CANCEL:
337         return "SALVSYNC_CANCEL";
338     case SALVSYNC_RAISEPRIO:
339         return "SALVSYNC_RAISEPRIO";
340     case SALVSYNC_QUERY:
341         return "SALVSYNC_QUERY";
342     case SALVSYNC_CANCELALL:
343         return "SALVSYNC_CANCELLALL";
344     default:
345         return "**UNKNOWN**";
346     }
347 }
348
349 static char *
350 reason_code_to_string(afs_int32 reason)
351 {
352     switch (reason) {
353     case SALVSYNC_WHATEVER:
354         return "SALVSYNC_WHATEVER";
355     case SALVSYNC_ERROR:
356         return "SALVSYNC_ERROR";
357     case SALVSYNC_OPERATOR:
358         return "SALVSYNC_OPERATOR";
359     case SALVSYNC_SHUTDOWN:
360         return "SALVSYNC_SHUTDOWN";
361     case SALVSYNC_NEEDED:
362         return "SALVSYNC_NEEDED";
363     default:
364         return "**UNKNOWN**";
365     }
366 }
367
368 #if 0
369 static char *
370 program_type_to_string(afs_int32 type)
371 {
372     switch ((ProgramType)type) {
373     case fileServer:
374         return "fileServer";
375     case volumeUtility:
376         return "volumeUtility";
377     case salvager:
378         return "salvager";
379     case salvageServer:
380         return "salvageServer";
381     default:
382         return "**UNKNOWN**";
383     }
384 }
385 #endif
386
387 static char *
388 state_code_to_string(afs_int32 state)
389 {
390     switch (state) {
391     case SALVSYNC_STATE_UNKNOWN:
392         return "SALVSYNC_STATE_UNKNOWN";
393     case SALVSYNC_STATE_QUEUED:
394         return "SALVSYNC_STATE_QUEUED";
395     case SALVSYNC_STATE_SALVAGING:
396         return "SALVSYNC_STATE_SALVAGING";
397     case SALVSYNC_STATE_ERROR:
398         return "SALVSYNC_STATE_ERROR";
399     case SALVSYNC_STATE_DONE:
400         return "SALVSYNC_STATE_DONE";
401     default:
402         return "**UNKNOWN**";
403     }
404 }
405
406 static int
407 OpStats(struct cmd_syndesc * as, void * rock)
408 {
409     struct state state;
410
411     common_prolog(as, &state);
412     common_salv_prolog(as, &state);
413
414     do_salvop(&state, SALVSYNC_NOP, NULL);
415
416     return 0;
417 }
418
419 static int
420 OpSalvage(struct cmd_syndesc * as, void * rock)
421 {
422     struct state state;
423
424     common_prolog(as, &state);
425     common_salv_prolog(as, &state);
426
427     do_salvop(&state, SALVSYNC_SALVAGE, NULL);
428
429     return 0;
430 }
431
432 static int
433 OpCancel(struct cmd_syndesc * as, void * rock)
434 {
435     struct state state;
436
437     common_prolog(as, &state);
438     common_salv_prolog(as, &state);
439
440     do_salvop(&state, SALVSYNC_CANCEL, NULL);
441
442     return 0;
443 }
444
445 static int
446 OpCancelAll(struct cmd_syndesc * as, void * rock)
447 {
448     struct state state;
449
450     common_prolog(as, &state);
451     common_salv_prolog(as, &state);
452
453     do_salvop(&state, SALVSYNC_CANCELALL, NULL);
454
455     return 0;
456 }
457
458 static int
459 OpRaisePrio(struct cmd_syndesc * as, void * rock)
460 {
461     struct state state;
462
463     common_prolog(as, &state);
464     common_salv_prolog(as, &state);
465
466     do_salvop(&state, SALVSYNC_RAISEPRIO, NULL);
467
468     return 0;
469 }
470
471 static int
472 OpQuery(struct cmd_syndesc * as, void * rock)
473 {
474     struct state state;
475
476     common_prolog(as, &state);
477     common_salv_prolog(as, &state);
478
479     do_salvop(&state, SALVSYNC_QUERY, NULL);
480
481     return 0;
482 }
483
484 #endif /* AFS_DEMAND_ATTACH_FS */