X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=restore-src%2Famfetchdump.c;h=e0764d79d22b6b162a3e0cd131b15dfc5f811b9e;hb=7906a3b9f861a26c6fd0423ca5232665d1b48caf;hp=bdeb114c50fe28e21c3311d84a8babb9b9efeda6;hpb=e442edb4d5816c4ad107ad9e71164f845eba70ad;p=debian%2Famanda diff --git a/restore-src/amfetchdump.c b/restore-src/amfetchdump.c index bdeb114..e0764d7 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,17 @@ 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; + + /* usage_order helps to determine the order in which multiple tapes were + * used in a single run; it is set as the tapes are added, as sorted by + * dumpfile part number */ + int usage_order; } needed_tape_t; /* local functions */ -tapelist_t *list_needed_tapes(GSList *dumpspecs, int only_one); +tapelist_t *list_needed_tapes(GSList *dumpspecs, int only_one, disklist_t *diskqp); void usage(void); int main(int argc, char **argv); @@ -91,6 +95,26 @@ 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"; + + /* if the tape timestamps match, sort them by usage_order, which is derived + * from the order the tapes were written in a single run */ + int r = strcmp(a_ds, b_ds); + if (r != 0) + return r; + return (a_nt->usage_order > b_nt->usage_order)? 1 : -1; +} + /* * 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 @@ -99,25 +123,20 @@ usage(void) tapelist_t * list_needed_tapes( GSList * dumpspecs, - int only_one) + int only_one, + disklist_t *diskqp) { - needed_tape_t *needed_tapes = NULL, *curtape = NULL; - disklist_t diskqp; + 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); + int usage_order_counter = 0; + 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); @@ -126,19 +145,25 @@ 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 */ matches = dumps_match_dumpspecs(alldumps, dumpspecs, 1); - sort_find_result("Dhklp", &matches); + + /* D = dump_timestamp, newest first + * h = hostname + * k = diskname + * l = level + * p = partnum + * w = write_timestamp */ + sort_find_result("Dhklpw", &matches); + for(curmatch = matches; curmatch; curmatch = curmatch->next) { int havetape = 0; - int have_part = 0; /* keep only first dump if only_one */ if (only_one && @@ -156,35 +181,16 @@ list_needed_tapes( 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) && - !strcmp(rsttemp->hostname, curmatch->hostname) && - !strcmp(rsttemp->diskname, curmatch->diskname) && - !strcmp(rsttemp->timestamp, curmatch->timestamp) && - rsttemp->level == curmatch->level) { - have_part = 1; - } - } - } - if (have_part) - continue; - for(curtape = needed_tapes; curtape; curtape = curtape->next) { + for(iter = needed_tapes; iter; iter = iter->next) { + needed_tape_t *curtape = iter->data; if (!strcmp(curtape->label, curmatch->label)) { - find_result_t *rsttemp = NULL; - find_result_t *rstfile; int keep = 1; havetape = 1; - for(rsttemp = curtape->files; - rsttemp; - rsttemp=rsttemp->next){ + 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"), @@ -197,56 +203,78 @@ list_needed_tapes( break; } - rstfile = alloc(SIZEOF(find_result_t)); - memcpy(rstfile, curmatch, SIZEOF(find_result_t)); - rstfile->next = curtape->files; - - if (curmatch->filenum < 1) - curtape->isafile = 1; - else curtape->isafile = 0; - curtape->files = rstfile; + 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; + needed_tape_t *newtape = g_new0(needed_tape_t, 1); + newtape->usage_order = usage_order_counter++; + newtape->files = g_slist_prepend(newtape->files, curmatch); + newtape->isafile = (curmatch->filenum < 1); 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++; + needed_tapes = g_slist_prepend(needed_tapes, newtape); } /* if(!havetape) */ } /* for(curmatch = matches ... */ - if(numtapes == 0){ + 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); } @@ -270,6 +298,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: @@ -378,12 +408,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 | @@ -404,14 +445,17 @@ main( /* Decide what tapes we'll need */ needed_tapes = list_needed_tapes(dumpspecs, - rst_flags->pipe_to_fd == STDOUT_FILENO); + 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(); @@ -422,6 +466,7 @@ main( flush_open_outputs(1, NULL); else flush_open_outputs(0, NULL); + free_disklist(&diskq); free_rst_flags(rst_flags); return(0); @@ -430,7 +475,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); + } } }