X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Ffind.c;h=0edd6af8bfd3c28f2f981a6d86fdb4ad94549eeb;hb=911bfb4415195b5c0a98b8c957caa8968313fd81;hp=3ff744e69c16a93cc954036e6556e9e309d92e6b;hpb=d92f70685083588e2a7ce6bc312a735f6937b5a6;p=debian%2Famanda diff --git a/server-src/find.c b/server-src/find.c index 3ff744e..0edd6af 100644 --- a/server-src/find.c +++ b/server-src/find.c @@ -30,38 +30,58 @@ * controlling process for the Amanda backup system */ #include "amanda.h" +#include "match.h" #include "conffile.h" #include "tapefile.h" #include "logfile.h" #include "holding.h" #include "find.h" +#include #include "cmdline.h" int find_match(char *host, char *disk); -void search_holding_disk(find_result_t **output_find); -char *find_nicedate(char *datestamp); +static char *find_nicedate(char *datestamp); +static int len_find_nicedate(char *datestamp); static int find_compare(const void *, const void *); static int parse_taper_datestamp_log(char *logline, char **datestamp, char **level); static gboolean logfile_has_tape(char * label, char * datestamp, char * logfile); static char *find_sort_order = NULL; +static GStringChunk *string_chunk = NULL; find_result_t * find_dump(disklist_t* diskqp) { char *conf_logdir, *logfile = NULL; - int tape, maxtape, logs; + int tape, tape1, maxtape, logs; unsigned seq; - tape_t *tp; + tape_t *tp, *tp1; find_result_t *output_find = NULL; + gboolean *tape_seen = NULL; + if (string_chunk == NULL) { + string_chunk = g_string_chunk_new(32768); + } conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); maxtape = lookup_nb_tape(); + tape_seen = g_new0(gboolean, maxtape+1); for(tape = 1; tape <= maxtape; tape++) { + if (tape_seen[tape] == 1) + continue; tp = lookup_tapepos(tape); if(tp == NULL) continue; + /* find all tape with the same datestamp */ + for (tape1 = tape; tape1 <= maxtape; tape1++) { + tp1 = lookup_tapepos(tape1); + if (tp1 == NULL) continue; + if (strcmp(tp->datestamp, tp1->datestamp) != 0) + continue; + + tape_seen[tape1] = 1; + } + /* search log files */ logs = 0; @@ -75,7 +95,7 @@ find_result_t * find_dump(disklist_t* diskqp) { logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL); if(access(logfile, R_OK) != 0) break; - if (search_logfile(&output_find, tp->label, tp->datestamp, + if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } @@ -86,7 +106,7 @@ find_result_t * find_dump(disklist_t* diskqp) { logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp, ".amflush", NULL); if(access(logfile,R_OK) == 0) { - if (search_logfile(&output_find, tp->label, tp->datestamp, + if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } @@ -97,20 +117,17 @@ find_result_t * find_dump(disklist_t* diskqp) { logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp, NULL); if(access(logfile,R_OK) == 0) { - if (search_logfile(&output_find, tp->label, tp->datestamp, + if (search_logfile(&output_find, NULL, tp->datestamp, logfile, diskqp)) { logs ++; } } - if(logs == 0 && strcmp(tp->datestamp,"0") != 0) - g_fprintf(stderr, - _("Warning: no log files found for tape %s written %s\n"), - tp->label, find_nicedate(tp->datestamp)); } + g_free(tape_seen); amfree(logfile); amfree(conf_logdir); - search_holding_disk(&output_find); + search_holding_disk(&output_find, diskqp); return(output_find); } @@ -201,26 +218,36 @@ find_log(void) void search_holding_disk( - find_result_t **output_find) + find_result_t **output_find, + disklist_t * dynamic_disklist) { GSList *holding_file_list; GSList *e; - char *holding_file; + char *holding_file; disk_t *dp; - dumpfile_t file; + char *orig_name; holding_file_list = holding_get_files(NULL, 1); + if (string_chunk == NULL) { + string_chunk = g_string_chunk_new(32768); + } + for(e = holding_file_list; e != NULL; e = e->next) { + dumpfile_t file; + holding_file = (char *)e->data; if (!holding_file_get_dumpfile(holding_file, &file)) continue; - if (file.dumplevel < 0 || file.dumplevel > 9) + if (file.dumplevel < 0 || file.dumplevel >= DUMP_LEVELS) { + dumpfile_free_data(&file); continue; + } dp = NULL; + orig_name = g_strdup(file.name); for(;;) { char *s; if((dp = lookup_disk(file.name, file.disk))) @@ -229,27 +256,49 @@ search_holding_disk( break; *s = '\0'; } + strcpy(file.name, orig_name); /* restore munged string */ + g_free(orig_name); + if ( dp == NULL ) { - continue; + if (dynamic_disklist == NULL) { + dumpfile_free_data(&file); + continue; + } + dp = add_disk(dynamic_disklist, file.name, file.disk); + enqueue_disk(dynamic_disklist, dp); } if(find_match(file.name,file.disk)) { - find_result_t *new_output_find = - alloc(SIZEOF(find_result_t)); + find_result_t *new_output_find = g_new0(find_result_t, 1); new_output_find->next=*output_find; - new_output_find->timestamp = stralloc(file.datestamp); - new_output_find->hostname = stralloc(file.name); - new_output_find->diskname = stralloc(file.disk); + new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, file.datestamp); + new_output_find->write_timestamp = g_string_chunk_insert_const(string_chunk, "00000000000000"); + new_output_find->hostname = g_string_chunk_insert_const(string_chunk, file.name); + new_output_find->diskname = g_string_chunk_insert_const(string_chunk, file.disk); new_output_find->level=file.dumplevel; - new_output_find->label=stralloc(holding_file); - new_output_find->partnum=stralloc("--"); + new_output_find->label=g_string_chunk_insert_const(string_chunk, holding_file); + new_output_find->partnum = -1; + new_output_find->totalparts = -1; new_output_find->filenum=0; - new_output_find->status=stralloc("OK"); + if (file.is_partial) { + new_output_find->status="PARTIAL"; + new_output_find->dump_status="PARTIAL"; + } else { + new_output_find->status="OK"; + new_output_find->dump_status="OK"; + } + new_output_find->message=""; + new_output_find->kb = holding_file_size(holding_file, 1); + new_output_find->bytes = 0; + + new_output_find->orig_kb = file.orig_size; + *output_find=new_output_find; } + dumpfile_free_data(&file); } - g_slist_free_full(holding_file_list); + slist_free_full(holding_file_list, g_free); } static int @@ -290,12 +339,10 @@ find_compare( case 'b' : compare=compare_possibly_null_strings(i->label, j->label); break; + case 'w': compare=strcmp(i->write_timestamp, j->write_timestamp); + break; case 'p' : - if(strcmp(i->partnum, "--") != 0 && - strcmp(j->partnum, "--") != 0){ - compare = atoi(i->partnum) - atoi(j->partnum); - } - else compare=strcmp(i->partnum,j->partnum); + compare=i->partnum - j->partnum; break; } if(compare != 0) @@ -366,9 +413,9 @@ print_find_result( for(output_find_result=output_find; output_find_result; output_find_result=output_find_result->next) { - char *qdiskname; + char *s; - len=strlen(find_nicedate(output_find_result->timestamp)); + len=len_find_nicedate(output_find_result->timestamp); if((int)len > max_len_datestamp) max_len_datestamp=(int)len; @@ -376,25 +423,26 @@ print_find_result( if((int)len > max_len_hostname) max_len_hostname = (int)len; - qdiskname=quote_string(output_find_result->diskname); - len=strlen(qdiskname); - amfree(qdiskname); + len = len_quote_string(output_find_result->diskname); if((int)len > max_len_diskname) max_len_diskname = (int)len; if (output_find_result->label != NULL) { - len=strlen(output_find_result->label); + len = len_quote_string(output_find_result->label); if((int)len > max_len_label) max_len_label = (int)len; } - len=strlen(output_find_result->status); + len=strlen(output_find_result->status) + 1 + strlen(output_find_result->dump_status); if((int)len > max_len_status) max_len_status = (int)len; - len=strlen(output_find_result->partnum); + s = g_strdup_printf("%d/%d", output_find_result->partnum, + output_find_result->totalparts); + len=strlen(s); if((int)len > max_len_part) max_len_part = (int)len; + amfree(s); } /* @@ -421,13 +469,29 @@ print_find_result( output_find_result=output_find_result->next) { char *qdiskname; char * formatted_label; + char *s; + char *status; qdiskname = quote_string(output_find_result->diskname); - formatted_label = output_find_result->label; - if (formatted_label == NULL) - formatted_label = ""; + if (output_find_result->label == NULL) + formatted_label = stralloc(""); + else + formatted_label = quote_string(output_find_result->label); + + if (strcmp(output_find_result->status, "OK") != 0 || + strcmp(output_find_result->dump_status, "OK") != 0) { + status = vstralloc(output_find_result->status, " ", + output_find_result->dump_status, NULL); + } else { + status = stralloc(output_find_result->status); + } + /*@ignore@*/ - g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %-*s\n", + /* sec and kb are omitted here, for compatibility with the existing + * output from 'amadmin' */ + s = g_strdup_printf("%d/%d", output_find_result->partnum, + output_find_result->totalparts); + g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %s %s\n", max_len_datestamp, find_nicedate(output_find_result->timestamp), max_len_hostname, output_find_result->hostname, @@ -435,11 +499,15 @@ print_find_result( max_len_level, output_find_result->level, max_len_label, formatted_label, max_len_filenum, (long long)output_find_result->filenum, - max_len_part, output_find_result->partnum, - max_len_status, output_find_result->status + max_len_part, s, + status, + output_find_result->message ); + amfree(status); + amfree(s); /*@end@*/ amfree(qdiskname); + amfree(formatted_label); } } } @@ -455,12 +523,6 @@ free_find_result( output_find_result; output_find_result=output_find_result->next) { amfree(prev); - amfree(output_find_result->timestamp); - amfree(output_find_result->hostname); - amfree(output_find_result->diskname); - amfree(output_find_result->label); - amfree(output_find_result->partnum); - amfree(output_find_result->status); prev = output_find_result; } amfree(prev); @@ -476,7 +538,7 @@ find_match( return (dp && dp->todo); } -char * +static char * find_nicedate( char *datestamp) { @@ -512,6 +574,17 @@ find_nicedate( return nice; } +static int +len_find_nicedate( + char *datestamp) +{ + if(strlen(datestamp) <= 8) { + return 10; + } else { + return 19; + } +} + static int parse_taper_datestamp_log( char *logline, @@ -553,9 +626,10 @@ parse_taper_datestamp_log( return 0; } *label = s - 1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; + *label = unquote_string(*label); return 1; } @@ -563,7 +637,7 @@ parse_taper_datestamp_log( static gboolean logfile_has_tape(char * label, char * datestamp, char * logfile) { FILE * logf; - char * ck_datestamp, *ck_label; + char * ck_datestamp, *ck_label = NULL; if((logf = fopen(logfile, "r")) == NULL) { error(_("could not open logfile %s: %s"), logfile, strerror(errno)); /*NOTREACHED*/ @@ -577,9 +651,11 @@ static gboolean logfile_has_tape(char * label, char * datestamp, logfile, curstr); } else if(strcmp(ck_datestamp, datestamp) == 0 && strcmp(ck_label, label) == 0) { + amfree(ck_label); afclose(logf); return TRUE; } + amfree(ck_label); } } @@ -587,9 +663,28 @@ static gboolean logfile_has_tape(char * label, char * datestamp, return FALSE; } -/* Like (strcmp(label1, label2) == 0), except that NULL values force TRUE. */ -static gboolean volume_matches(const char * label1, const char * label2) { - return (label1 == NULL || label2 == NULL || strcmp(label1, label2) == 0); +static gboolean +volume_matches( + const char *label1, + const char *label2, + const char *datestamp) +{ + tape_t *tp; + + if (!label2) + return TRUE; + + if (label1) + return (strcmp(label1, label2) == 0); + + /* check in tapelist */ + if (!(tp = lookup_tapelabel(label2))) + return FALSE; + + if (strcmp(tp->datestamp, datestamp) != 0) + return FALSE; + + return TRUE; } /* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr, @@ -606,26 +701,40 @@ search_logfile( char *host, *host_undo; char *disk, *qdisk, *disk_undo; char *date, *date_undo; - char *partnum=NULL, *partnum_undo; + int partnum; + int totalparts; + int maxparts = -1; char *number; int fileno; - char *current_label = NULL; - char *rest; + char *current_label = stralloc(""); + char *rest, *rest_undo; char *ck_label=NULL; - int level = 0; + int level = 0; off_t filenum; char *ck_datestamp, *datestamp; char *s; int ch; disk_t *dp; - find_result_t *part_find = NULL; /* List for all part of a DLE */ + GHashTable* valid_label; + GHashTable* part_by_dle; + find_result_t *part_find; find_result_t *a_part_find; gboolean right_label = FALSE; gboolean found_something = FALSE; + double sec; + off_t kb; + off_t bytes; + off_t orig_kb; + int taper_part = 0; g_return_val_if_fail(output_find != NULL, 0); g_return_val_if_fail(logfile != NULL, 0); + if (string_chunk == NULL) { + string_chunk = g_string_chunk_new(32768); + } + valid_label = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + part_by_dle = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); datestamp = g_strdup(passed_datestamp); if((logf = fopen(logfile, "r")) == NULL) { @@ -646,29 +755,37 @@ search_logfile( if (strcmp(datestamp, ck_datestamp) != 0) { g_printf(_("Log file %s stamped %s, expecting %s!\n"), logfile, ck_datestamp, datestamp); + amfree(ck_label); break; } } - - right_label = volume_matches(label, ck_label); + + right_label = volume_matches(label, ck_label, ck_datestamp); + if (right_label && ck_label) { + g_hash_table_insert(valid_label, g_strdup(ck_label), + GINT_TO_POINTER(1)); + } if (label && datestamp && right_label) { found_something = TRUE; } amfree(current_label); - current_label = g_strdup(ck_label); + current_label = ck_label; if (datestamp == NULL) { datestamp = g_strdup(ck_datestamp); } + filenum = (off_t)0; } - if (!right_label) { - continue; - } - if ((curlog == L_SUCCESS || + if (right_label && + (curlog == L_SUCCESS || curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) && curprog == P_TAPER) { filenum++; + } else if (right_label && curlog == L_PARTIAL && curprog == P_TAPER && + taper_part == 0) { + filenum++; } - partnum = "--"; + partnum = -1; + totalparts = -1; if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS || curlog == L_DONE || curlog == L_FAIL || curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL || @@ -684,15 +801,20 @@ search_logfile( } if (curlog == L_PART || curlog == L_PARTPARTIAL) { - char * part_label = s - 1; - skip_non_whitespace(s, ch); + char *part_label; + char *qpart_label = s - 1; + taper_part++; + skip_quoted_string(s, ch); s[-1] = '\0'; - if (strcmp(current_label, part_label) != 0) { - g_printf("PART label %s doesn't match START label %s\n", - part_label, current_label); + part_label = unquote_string(qpart_label); + if (!g_hash_table_lookup(valid_label, part_label)) { + amfree(part_label); continue; } + amfree(current_label); + current_label = part_label; + skip_whitespace(s, ch); if(ch == '\0') { g_printf("strange log line in %s \"%s\"\n", @@ -705,6 +827,8 @@ search_logfile( s[-1] = '\0'; fileno = atoi(number); filenum = fileno; + if (filenum == 0) + continue; skip_whitespace(s, ch); if(ch == '\0') { @@ -712,6 +836,8 @@ search_logfile( logfile, curstr); continue; } + } else { + taper_part = 0; } host = s - 1; @@ -745,19 +871,38 @@ search_logfile( if(strlen(date) < 3) { /* old log didn't have datestamp */ level = atoi(date); date = stralloc(datestamp); + partnum = 1; + totalparts = 1; } else { - if (curlog == L_CHUNK || curlog == L_PART || - curlog == L_PARTPARTIAL || curlog == L_DONE){ + if (curprog == P_TAPER && + (curlog == L_CHUNK || curlog == L_PART || + curlog == L_PARTPARTIAL || curlog == L_PARTIAL || + curlog == L_DONE)) { + char *s1, ch1; skip_whitespace(s, ch); - partnum = s - 1; + number = s - 1; skip_non_whitespace(s, ch); - partnum_undo = s - 1; - *partnum_undo = '\0'; + s1 = &s[-1]; + ch1 = *s1; + skip_whitespace(s, ch); + if (*(s-1) != '[') { + *s1 = ch1; + sscanf(number, "%d/%d", &partnum, &totalparts); + if (partnum > maxparts) + maxparts = partnum; + if (totalparts > maxparts) + maxparts = totalparts; + } else { /* nparts is not in all PARTIAL lines */ + partnum = 1; + totalparts = 1; + s = number + 1; + } + } else { + skip_whitespace(s, ch); } - skip_whitespace(s, ch); if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { - g_printf(_("strange log line in %s \"%s\"\n"), - logfile, curstr); + g_printf(_("Fstrange log line in %s \"%s\"\n"), + logfile, s-1); continue; } skip_integer(s, ch); @@ -770,10 +915,91 @@ search_logfile( continue; } rest = s - 1; - if((s = strchr(s, '\n')) != NULL) { - *s = '\0'; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "[sec") == 0) { + skip_whitespace(s, ch); + if(ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + sec = atof(s - 1); + skip_non_whitespace(s, ch); + skip_whitespace(s, ch); + rest = s - 1; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "kb") != 0 && + strcmp(rest, "bytes") != 0) { + g_printf(_("Bstrange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + + skip_whitespace(s, ch); + if (ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + if (strcmp(rest, "kb") == 0) { + kb = atof(s - 1); + bytes = 0; + } else { + bytes = atof(s - 1); + kb = bytes / 1024; + } + skip_non_whitespace(s, ch); + skip_whitespace(s, ch); + rest = s - 1; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "kps") != 0) { + g_printf(_("Cstrange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + + skip_whitespace(s, ch); + if (ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + /* kps = atof(s - 1); */ + skip_non_whitespace(s, ch); + skip_whitespace(s, ch); + rest = s - 1; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "orig-kb") != 0) { + orig_kb = 0; + } else { + + skip_whitespace(s, ch); + if(ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + orig_kb = atof(s - 1); + } + } else { + sec = 0; + kb = 0; + bytes = 0; + orig_kb = 0; + *rest_undo = ' '; } + if (strncmp(rest, "error", 5) == 0) rest += 6; + if (strncmp(rest, "config", 6) == 0) rest += 7; + dp = lookup_disk(host,disk); if ( dp == NULL ) { if (dynamic_disklist == NULL) { @@ -784,33 +1010,96 @@ search_logfile( } if (find_match(host, disk)) { if(curprog == P_TAPER) { - find_result_t *new_output_find = - (find_result_t *)alloc(SIZEOF(find_result_t)); - new_output_find->timestamp = stralloc(date); - new_output_find->hostname=stralloc(host); - new_output_find->diskname=stralloc(disk); + char *key = g_strdup_printf( + "HOST:%s DISK:%s: DATE:%s LEVEL:%d", + host, disk, date, level); + find_result_t *new_output_find = g_new0(find_result_t, 1); + part_find = g_hash_table_lookup(part_by_dle, key); + maxparts = partnum; + if (maxparts < totalparts) + maxparts = totalparts; + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (maxparts < a_part_find->partnum) + maxparts = a_part_find->partnum; + if (maxparts < a_part_find->totalparts) + maxparts = a_part_find->totalparts; + } + new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, date); + new_output_find->write_timestamp = g_string_chunk_insert_const(string_chunk, datestamp); + new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host); + new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk); new_output_find->level=level; - new_output_find->partnum = stralloc(partnum); - new_output_find->label=stralloc(current_label); + new_output_find->partnum = partnum; + new_output_find->totalparts = totalparts; + new_output_find->label=g_string_chunk_insert_const(string_chunk, current_label); new_output_find->status=NULL; + new_output_find->dump_status=NULL; + new_output_find->message=""; new_output_find->filenum=filenum; + new_output_find->sec=sec; + new_output_find->kb=kb; + new_output_find->bytes=bytes; + new_output_find->orig_kb=orig_kb; new_output_find->next=NULL; if (curlog == L_SUCCESS) { - new_output_find->status = stralloc("OK"); + new_output_find->status = "OK"; + new_output_find->dump_status = "OK"; new_output_find->next = *output_find; + new_output_find->partnum = 1; /* L_SUCCESS is pre-splitting */ *output_find = new_output_find; found_something = TRUE; } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE || curlog == L_PARTIAL || curlog == L_FAIL) { /* result line */ if (curlog == L_PARTIAL || curlog == L_FAIL) { - /* change status of each part */ - for (a_part_find = part_find; a_part_find; + /* set dump_status of each part */ + for (a_part_find = part_find; + a_part_find; a_part_find = a_part_find->next) { if (curlog == L_PARTIAL) - a_part_find->status = stralloc("PARTIAL"); - else - a_part_find->status = stralloc(rest); + a_part_find->dump_status = "PARTIAL"; + else { + a_part_find->dump_status = "FAIL"; + a_part_find->message = g_string_chunk_insert_const(string_chunk, rest); + } + } + } else { + if (maxparts > -1) { /* format with part */ + /* must check if all part are there */ + int num_part = maxparts; + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (a_part_find->partnum == num_part && + strcmp(a_part_find->status, "OK") == 0) + num_part--; + } + /* set dump_status of each part */ + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (num_part == 0) { + a_part_find->dump_status = "OK"; + } else { + a_part_find->dump_status = "FAIL"; + a_part_find->message = + g_string_chunk_insert_const(string_chunk, "Missing part"); + } + } + } + } + if (curlog == L_DONE) { + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (a_part_find->totalparts == -1) { + a_part_find->totalparts = maxparts; + } + if (a_part_find->orig_kb == 0) { + a_part_find->orig_kb = orig_kb; + } } } if (part_find) { /* find last element */ @@ -822,73 +1111,74 @@ search_logfile( a_part_find->next = *output_find; *output_find = part_find; part_find = NULL; + maxparts = -1; found_something = TRUE; + g_hash_table_remove(part_by_dle, key); } free_find_result(&new_output_find); } else { /* part line */ - if (curlog == L_PART || curlog == L_CHUNK) - new_output_find->status=stralloc("OK"); - else /* PARTPARTIAL */ - new_output_find->status=stralloc("PARTIAL"); + if (curlog == L_PART || curlog == L_CHUNK) { + new_output_find->status = "OK"; + new_output_find->dump_status = "OK"; + } else { /* PARTPARTIAL */ + new_output_find->status = "PARTIAL"; + new_output_find->dump_status = "PARTIAL"; + } /* Add to part_find list */ - new_output_find->next = part_find; - part_find = new_output_find; + if (part_find) { + new_output_find->next = part_find; + part_find = new_output_find; + } else { + new_output_find->next = NULL; + part_find = new_output_find; + } + g_hash_table_insert(part_by_dle, g_strdup(key), + part_find); found_something = TRUE; } + amfree(key); } - else if(curlog == L_FAIL) { /* print other failures too */ - find_result_t *new_output_find = - (find_result_t *)alloc(SIZEOF(find_result_t)); - new_output_find->next=*output_find; - new_output_find->timestamp = stralloc(date); - new_output_find->hostname=stralloc(host); - new_output_find->diskname=stralloc(disk); + else if(curlog == L_FAIL) { + char *status_failed; + /* print other failures too -- this is a hack to ensure that failures which + * did not make it to tape are also listed in the output of 'amadmin x find'; + * users that do not want this information (e.g., Amanda::DB::Catalog) should + * filter dumps with a NULL label. */ + find_result_t *new_output_find = g_new0(find_result_t, 1); + new_output_find->next = *output_find; + new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, date); + new_output_find->write_timestamp = g_strdup("00000000000000"); /* dump was not written.. */ + new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host); + new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk); new_output_find->level=level; new_output_find->label=NULL; - new_output_find->partnum=stralloc(partnum); + new_output_find->partnum=partnum; + new_output_find->totalparts=totalparts; new_output_find->filenum=0; - new_output_find->status=vstralloc( + new_output_find->sec=sec; + new_output_find->kb=kb; + new_output_find->bytes=bytes; + new_output_find->orig_kb=orig_kb; + status_failed = vstralloc( "FAILED (", program_str[(int)curprog], ") ", rest, NULL); + new_output_find->status = g_string_chunk_insert_const(string_chunk, status_failed); + amfree(status_failed); + new_output_find->dump_status=""; + new_output_find->message=""; *output_find=new_output_find; found_something = TRUE; + maxparts = -1; } } amfree(disk); } } - if (part_find != NULL) { - if (label) { - /* parse log file until PARTIAL/DONE/SUCCESS/FAIL from taper */ - while(get_logline(logf)) { - if (curprog == P_TAPER && - (curlog == L_DONE || curlog == L_SUCCESS || - curlog == L_PARTIAL || curlog == L_FAIL)) { - break; - } - } - } - for (a_part_find = part_find; a_part_find; - a_part_find = a_part_find->next) { - if (curlog == L_PARTIAL) - a_part_find->status = stralloc("PARTIAL"); - else if (curlog == L_FAIL) - a_part_find->status = stralloc("FAIL"); - } - for (a_part_find = part_find; - a_part_find->next != NULL; - a_part_find=a_part_find->next) { - } - /* merge part_find to *output_find */ - a_part_find->next = *output_find; - *output_find = part_find; - part_find = NULL; - } - + g_hash_table_destroy(valid_label); afclose(logf); amfree(datestamp); amfree(current_label); @@ -926,20 +1216,28 @@ dumps_match( (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) && (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) && (!level || *level== '\0' || match_level(level, level_str)) && - (!ok || !strcmp(cur_result->status, "OK"))){ + (!ok || !strcmp(cur_result->status, "OK")) && + (!ok || !strcmp(cur_result->dump_status, "OK"))){ - find_result_t *curmatch = alloc(SIZEOF(find_result_t)); + find_result_t *curmatch = g_new0(find_result_t, 1); memcpy(curmatch, cur_result, SIZEOF(find_result_t)); - curmatch->timestamp = stralloc(cur_result->timestamp); - curmatch->hostname = stralloc(cur_result->hostname); - curmatch->diskname = stralloc(cur_result->diskname); + curmatch->timestamp = cur_result->timestamp; + curmatch->write_timestamp = cur_result->write_timestamp; + curmatch->hostname = cur_result->hostname; + curmatch->diskname = cur_result->diskname; curmatch->level = cur_result->level; - curmatch->label = stralloc(cur_result->label); + curmatch->label = cur_result->label? cur_result->label : NULL; curmatch->filenum = cur_result->filenum; - curmatch->status = stralloc(cur_result->status); - curmatch->partnum = stralloc(cur_result->partnum); - + curmatch->sec = cur_result->sec; + curmatch->kb = cur_result->kb; + curmatch->bytes = cur_result->bytes; + curmatch->orig_kb = cur_result->orig_kb; + curmatch->status = cur_result->status; + curmatch->dump_status = cur_result->dump_status; + curmatch->message = cur_result->message; + curmatch->partnum = cur_result->partnum; + curmatch->totalparts = cur_result->totalparts; curmatch->next = matches; matches = curmatch; } @@ -970,32 +1268,59 @@ dumps_match_dumpspecs( cur_result; cur_result=cur_result->next) { char level_str[NUM_STR_SIZE]; + char *zeropad_ts = NULL; + char *zeropad_w_ts = NULL; g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level); + + /* get the timestamp padded to full width */ + if (strlen(cur_result->timestamp) < 14) { + zeropad_ts = g_new0(char, 15); + memset(zeropad_ts, '0', 14); + memcpy(zeropad_ts, cur_result->timestamp, strlen(cur_result->timestamp)); + } + if (strlen(cur_result->write_timestamp) < 14) { + zeropad_w_ts = g_new0(char, 15); + memset(zeropad_w_ts, '0', 14); + memcpy(zeropad_w_ts, cur_result->write_timestamp, strlen(cur_result->write_timestamp)); + } + for (dumpspec = dumpspecs; dumpspec; dumpspec = dumpspec->next) { ds = (dumpspec_t *)dumpspec->data; if((!ds->host || *ds->host == '\0' || match_host(ds->host, cur_result->hostname)) && (!ds->disk || *ds->disk == '\0' || match_disk(ds->disk, cur_result->diskname)) && - (!ds->datestamp || *ds->datestamp== '\0' || match_datestamp(ds->datestamp, cur_result->timestamp)) && + (!ds->datestamp || *ds->datestamp== '\0' + || match_datestamp(ds->datestamp, cur_result->timestamp) + || (zeropad_ts && match_datestamp(ds->datestamp, zeropad_ts))) && + (!ds->write_timestamp || *ds->write_timestamp== '\0' + || match_datestamp(ds->write_timestamp, cur_result->write_timestamp) + || (zeropad_w_ts && match_datestamp(ds->write_timestamp, zeropad_w_ts))) && (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) && - (!ok || !strcmp(cur_result->status, "OK"))){ + (!ok || !strcmp(cur_result->status, "OK")) && + (!ok || !strcmp(cur_result->dump_status, "OK"))) { find_result_t *curmatch = alloc(SIZEOF(find_result_t)); memcpy(curmatch, cur_result, SIZEOF(find_result_t)); - curmatch->timestamp = stralloc(cur_result->timestamp); - curmatch->hostname = stralloc(cur_result->hostname); - curmatch->diskname = stralloc(cur_result->diskname); + curmatch->timestamp = cur_result->timestamp; + curmatch->write_timestamp = cur_result->write_timestamp; + curmatch->hostname = cur_result->hostname; + curmatch->diskname = cur_result->diskname; curmatch->level = cur_result->level; - curmatch->label = stralloc(cur_result->label); + curmatch->label = cur_result->label? cur_result->label : NULL; curmatch->filenum = cur_result->filenum; - curmatch->status = stralloc(cur_result->status); - curmatch->partnum = stralloc(cur_result->partnum); + curmatch->status = cur_result->status; + curmatch->dump_status = cur_result->dump_status; + curmatch->message = cur_result->message; + curmatch->partnum = cur_result->partnum; + curmatch->totalparts = cur_result->totalparts; curmatch->next = matches; matches = curmatch; break; } } + + amfree(zeropad_ts); } return(matches);