X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=restore-src%2Famfetchdump.c;h=ec3d83da17281b205ee0bf30a5944514da7162db;hb=21170aaf9015a4c519265834456fc309932f24c0;hp=d33d56d132cac6e0dc72ea66c6c0d42c17db0fb4;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/restore-src/amfetchdump.c b/restore-src/amfetchdump.c index d33d56d..ec3d83d 100644 --- a/restore-src/amfetchdump.c +++ b/restore-src/amfetchdump.c @@ -39,6 +39,7 @@ #include "changer.h" #include "logfile.h" #include "cmdline.h" +#include "server_util.h" #define CREAT_MODE 0640 @@ -49,14 +50,12 @@ int get_lock = 0; typedef struct needed_tapes_s { char *label; int isafile; - find_result_t *files; - struct needed_tapes_s *next; - struct needed_tapes_s *prev; + GSList *files; } needed_tape_t; /* local functions */ -tapelist_t *list_needed_tapes(GSList *dumpspecs); +tapelist_t *list_needed_tapes(GSList *dumpspecs, int only_one, disklist_t *diskqp); void usage(void); int main(int argc, char **argv); @@ -91,6 +90,21 @@ usage(void) exit(1); } +static gint +sort_needed_tapes_by_write_timestamp( + gconstpointer a, + gconstpointer b) +{ + needed_tape_t *a_nt = (needed_tape_t *)a; + needed_tape_t *b_nt = (needed_tape_t *)b; + tape_t *a_t = a_nt->isafile? NULL : lookup_tapelabel(a_nt->label); + tape_t *b_t = b_nt->isafile? NULL : lookup_tapelabel(b_nt->label); + char *a_ds = a_t? a_t->datestamp : "none"; + char *b_ds = b_t? b_t->datestamp : "none"; + + return strcmp(a_ds, b_ds); +} + /* * Build the list of tapes we'll be wanting, and include data about the * files we want from said tapes while we're at it (the whole find_result @@ -98,24 +112,20 @@ usage(void) */ tapelist_t * list_needed_tapes( - GSList * dumpspecs) + GSList * dumpspecs, + int only_one, + disklist_t *diskqp) { - needed_tape_t *needed_tapes = NULL, *curtape = NULL; - disklist_t diskqp; - dumpspec_t *ds = NULL; + GSList *needed_tapes = NULL; + GSList *seen_dumps = NULL; + GSList *iter, *iter2; find_result_t *alldumps = NULL; + find_result_t *curmatch = NULL; + find_result_t *matches = NULL; tapelist_t *tapes = NULL; - int numtapes = 0; - char *conf_diskfile, *conf_tapelist; - - /* For disks and tape lists */ - conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); - if(read_diskfile(conf_diskfile, &diskqp) != 0) { - error(_("could not load disklist \"%s\""), conf_diskfile); - /*NOTREACHED*/ - } - amfree(conf_diskfile); + char *conf_tapelist; + /* Load the tape list */ conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if(read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); @@ -124,123 +134,127 @@ list_needed_tapes( amfree(conf_tapelist); /* Grab a find_output_t of all logged dumps */ - alldumps = find_dump(&diskqp); - free_disklist(&diskqp); + alldumps = find_dump(diskqp); if(alldumps == NULL){ g_fprintf(stderr, _("No dump records found\n")); exit(1); } /* Compare all known dumps to our match list, note what we'll need */ - while (dumpspecs) { - find_result_t *curmatch = NULL; - find_result_t *matches = NULL; - ds = (dumpspec_t *)dumpspecs->data; - - matches = dumps_match(alldumps, ds->host, ds->disk, - ds->datestamp, ds->level, 1); - sort_find_result("Dhklp", &matches); - for(curmatch = matches; curmatch; curmatch = curmatch->next){ - int havetape = 0; - int have_part = 0; - if(strcmp("OK", curmatch->status)){ - g_fprintf(stderr,_("Dump %s %s %s %d had status '%s', skipping\n"), - curmatch->timestamp, curmatch->hostname, - curmatch->diskname, curmatch->level, - curmatch->status); - continue; - } - /* check if we already have that part */ - for(curtape = needed_tapes; curtape; curtape = curtape->next) { - find_result_t *rsttemp = NULL; - for(rsttemp = curtape->files; - rsttemp; - rsttemp=rsttemp->next) { - if (strcmp(rsttemp->partnum, curmatch->partnum) == 0) - have_part = 1; - } - } - if (have_part) - continue; - for(curtape = needed_tapes; curtape; curtape = curtape->next) { - if(!strcmp(curtape->label, curmatch->label)){ - find_result_t *rsttemp = NULL; - find_result_t *rstfile = alloc(SIZEOF(find_result_t)); - int keep = 1; - - memcpy(rstfile, curmatch, SIZEOF(find_result_t)); - - havetape = 1; - - for(rsttemp = curtape->files; - rsttemp; - rsttemp=rsttemp->next){ - if(rstfile->filenum == rsttemp->filenum){ - g_fprintf(stderr, _("Seeing multiple entries for tape " + matches = dumps_match_dumpspecs(alldumps, dumpspecs, 1); + sort_find_result("Dhklpw", &matches); + for(curmatch = matches; curmatch; curmatch = curmatch->next) { + int havetape = 0; + + /* keep only first dump if only_one */ + if (only_one && + curmatch != matches && + (strcmp(curmatch->hostname, matches->hostname) || + strcmp(curmatch->diskname, matches->diskname) || + strcmp(curmatch->timestamp, matches->timestamp) || + curmatch->level != matches->level)) { + continue; + } + if(strcmp("OK", curmatch->status)){ + g_fprintf(stderr,_("Dump %s %s %s %d had status '%s', skipping\n"), + curmatch->timestamp, curmatch->hostname, + curmatch->diskname, curmatch->level, + curmatch->status); + continue; + } + + for(iter = needed_tapes; iter; iter = iter->next) { + needed_tape_t *curtape = iter->data; + if (!strcmp(curtape->label, curmatch->label)) { + int keep = 1; + + havetape = 1; + + for(iter2 = curtape->files; iter2; iter2 = iter2->next){ + find_result_t *rsttemp = iter2->data; + if(curmatch->filenum == rsttemp->filenum){ + g_fprintf(stderr, _("Seeing multiple entries for tape " "%s file %lld, using most recent\n"), curtape->label, - (long long)rstfile->filenum); - keep = 0; - } - } - if(!keep){ - amfree(rstfile); - break; + (long long)curmatch->filenum); + keep = 0; } - rstfile->next = curtape->files; - - if(curmatch->filenum < 1) curtape->isafile = 1; - else curtape->isafile = 0; - curtape->files = rstfile; + } + if(!keep){ break; } + + curtape->isafile = (curmatch->filenum < 1); + curtape->files = g_slist_prepend(curtape->files, curmatch); + break; } - if(!havetape){ - find_result_t *rstfile = alloc(SIZEOF(find_result_t)); - needed_tape_t *newtape = - alloc(SIZEOF(needed_tape_t)); - memcpy(rstfile, curmatch, SIZEOF(find_result_t)); - rstfile->next = NULL; - newtape->files = rstfile; - if(curmatch->filenum < 1) newtape->isafile = 1; - else newtape->isafile = 0; - newtape->label = curmatch->label; - if(needed_tapes){ - needed_tapes->prev->next = newtape; - newtape->prev = needed_tapes->prev; - needed_tapes->prev = newtape; - } - else{ - needed_tapes = newtape; - needed_tapes->prev = needed_tapes; - } - newtape->next = NULL; - numtapes++; -#if 0 -// free_find_result(rstfile); -#endif - } /* if(!havetape) */ - - } /* for(curmatch = matches ... */ - dumpspecs = dumpspecs->next; - } /* while (dumpspecs) */ - - if(numtapes == 0){ + } + if (!havetape) { + needed_tape_t *newtape = g_new0(needed_tape_t, 1); + newtape->files = g_slist_prepend(newtape->files, curmatch); + newtape->isafile = (curmatch->filenum < 1); + newtape->label = curmatch->label; + needed_tapes = g_slist_prepend(needed_tapes, newtape); + } /* if(!havetape) */ + + } /* for(curmatch = matches ... */ + + if(g_slist_length(needed_tapes) == 0){ g_fprintf(stderr, _("No matching dumps found\n")); exit(1); /* NOTREACHED */ } - /* stick that list in a structure that librestore will understand */ - for(curtape = needed_tapes; curtape; curtape = curtape->next) { - find_result_t *curfind = NULL; - for(curfind = curtape->files; curfind; curfind = curfind->next) { - tapes = append_to_tapelist(tapes, curtape->label, - curfind->filenum, -1, curtape->isafile); + /* sort the tapelist by tape write_timestamp */ + needed_tapes = g_slist_sort(needed_tapes, sort_needed_tapes_by_write_timestamp); + + /* stick that list in a structure that librestore will understand, removing + * files we have already seen in the process; this prefers the earliest written + * copy of any dumps which are available on multiple tapes */ + seen_dumps = NULL; + for(iter = needed_tapes; iter; iter = iter->next) { + needed_tape_t *curtape = iter->data; + for(iter2 = curtape->files; iter2; iter2 = iter2->next) { + find_result_t *curfind = iter2->data; + find_result_t *prev; + GSList *iter; + int have_part; + + /* have we already seen this? */ + have_part = 0; + for (iter = seen_dumps; iter; iter = iter->next) { + prev = iter->data; + + if (!strcmp(prev->partnum, curfind->partnum) && + !strcmp(prev->hostname, curfind->hostname) && + !strcmp(prev->diskname, curfind->diskname) && + !strcmp(prev->timestamp, curfind->timestamp) && + prev->level == curfind->level) { + have_part = 1; + break; + } + } + + if (!have_part) { + seen_dumps = g_slist_prepend(seen_dumps, curfind); + tapes = append_to_tapelist(tapes, curtape->label, + curfind->filenum, -1, curtape->isafile); + } } } - g_fprintf(stderr, _("%d tape(s) needed for restoration\n"), numtapes); + /* free our resources */ + for (iter = needed_tapes; iter; iter = iter->next) { + needed_tape_t *curtape = iter->data; + g_slist_free(curtape->files); + g_free(curtape); + } + g_slist_free(seen_dumps); + g_slist_free(needed_tapes); + free_find_result(&matches); + + /* and we're done */ + g_fprintf(stderr, _("%d tape(s) needed for restoration\n"), num_entries(tapes)); return(tapes); } @@ -264,6 +278,8 @@ main( rst_flags_t *rst_flags; int minimum_arguments; config_overwrites_t *cfg_ovr = NULL; + disklist_t diskq; + char * conf_diskfile = NULL; /* * Configure program for internationalization: @@ -372,12 +388,23 @@ main( /*NOTREACHED*/ } - config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_FATAL, argv[optind++]); + config_init(CONFIG_INIT_EXPLICIT_NAME, argv[optind++]); apply_config_overwrites(cfg_ovr); + conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); + read_diskfile(conf_diskfile, &diskq); + amfree(conf_diskfile); + + if (config_errors(NULL) >= CFGERR_WARNINGS) { + config_print_errors(); + if (config_errors(NULL) >= CFGERR_ERRORS) { + g_critical(_("errors processing config file")); + } + } + check_running_as(RUNNING_AS_DUMPUSER); - dbrename(config_name, DBG_SUBDIR_SERVER); + dbrename(get_config_name(), DBG_SUBDIR_SERVER); dumpspecs = cmdline_parse_dumpspecs(argc - optind, argv + optind, CMDLINE_PARSE_DATESTAMP | @@ -397,14 +424,18 @@ main( /* Decide what tapes we'll need */ - needed_tapes = list_needed_tapes(dumpspecs); + needed_tapes = list_needed_tapes(dumpspecs, + rst_flags->pipe_to_fd == STDOUT_FILENO, + &diskq); parent_pid = getpid(); atexit(cleanup); get_lock = lock_logfile(); /* config is loaded, should be ok here */ if(get_lock == 0) { - error(_("%s exists: amdump or amflush is already running, or you must run amcleanup"), rst_conf_logfile); + char *process_name = get_master_process(rst_conf_logfile); + error(_("%s exists: %s is already running, or you must run amcleanup"), rst_conf_logfile, process_name); } + log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); search_tapes(NULL, stdin, rst_flags->alt_tapedev == NULL, needed_tapes, dumpspecs, rst_flags, NULL); cleanup(); @@ -415,6 +446,7 @@ main( flush_open_outputs(1, NULL); else flush_open_outputs(0, NULL); + free_disklist(&diskq); free_rst_flags(rst_flags); return(0); @@ -423,7 +455,10 @@ main( static void cleanup(void) { - if(parent_pid == getpid()) { - if(get_lock) unlink(rst_conf_logfile); + if (parent_pid == getpid()) { + if (get_lock) { + log_add(L_INFO, "pid-done %ld\n", (long)getpid()); + unlink(rst_conf_logfile); + } } }