From 6184700b6c631a3ea1852687dbf4f8661b2608e4 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 22 Aug 2002 17:12:31 +0000 Subject: [PATCH] Make bls read multi-job file git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@115 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/stored/bls.c | 247 +++++++++++++++++++++++++------------ bacula/src/stored/record.c | 146 +++++++++++----------- bacula/src/stored/record.h | 7 ++ 3 files changed, 251 insertions(+), 149 deletions(-) diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index 3e405c6fd3..94086f6057 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -73,6 +73,32 @@ static void usage() exit(1); } +static char *rec_state_to_str(DEV_RECORD *rec) +{ + static char buf[200]; + buf[0] = 0; + if (rec->state & REC_NO_HEADER) { + strcat(buf, "Nohdr,"); + } + if (rec->state & REC_PARTIAL_RECORD) { + strcat(buf, "partial,"); + } + if (rec->state & REC_BLOCK_EMPTY) { + strcat(buf, "empty,"); + } + if (rec->state & REC_NO_MATCH) { + strcat(buf, "Nomatch,"); + } + if (rec->state & REC_CONTINUATION) { + strcat(buf, "cont,"); + } + if (buf[0]) { + buf[strlen(buf)-1] = 0; + } + return buf; +} + + int main (int argc, char *argv[]) { @@ -433,6 +459,8 @@ static void do_ls(char *infname) struct stat statp; int type; long record_file_index; + uint32_t num_files = 0; + int record; if (dump_label) { dump_volume_label(dev); @@ -451,7 +479,7 @@ Warning, this Volume is a continuation of Volume %s\n", for ( ;; ) { SESSION_LABEL sessrec; - if (!read_record(dev, block, rec)) { + if (!read_block_from_device(dev, block)) { Dmsg0(20, "!read_record()\n"); if (dev->state & ST_EOT) { if (!mount_next_volume(infname)) { @@ -471,99 +499,158 @@ Warning, this Volume is a continuation of Volume %s\n", display_error_status(); break; } - - if (debug_level >= 30) { - Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId, - FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream), - rec->data_len); - } - - - /* - * Check for End of File record (all zeros) - * NOTE: this no longer exists - */ - if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) { - Emsg0(M_ERROR_TERM, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n"); + if (verbose) { + Dmsg2(10, "Block: %d blen=%d\n", block->BlockNumber, block->block_len); } - /* - * Check for Start or End of Session Record - * - */ - if (rec->FileIndex < 0) { - char *rtype; - memset(&sessrec, 0, sizeof(sessrec)); - switch (rec->FileIndex) { - case PRE_LABEL: - rtype = "Fresh Volume Label"; - break; - case VOL_LABEL: - rtype = "Volume Label"; - unser_volume_label(dev, rec); - break; - case SOS_LABEL: - rtype = "Begin Session"; - unser_session_label(&sessrec, rec); + record = 0; + for ( ;; ) { + if (!read_record_from_block(block, rec)) { + if (rec->state & REC_NO_HEADER) { + Dmsg2(30, "!read,nohdr-break. stat=%s blk=%d\n", rec_state_to_str(rec), + block->BlockNumber); break; - case EOS_LABEL: - rtype = "End Session"; - break; - case EOM_LABEL: - rtype = "End of Media"; - break; - default: - rtype = "Unknown"; + } + if (rec->state & REC_NO_MATCH) { + Dmsg2(30, "!read,nomatch-break. stat=%s blk=%d\n", rec_state_to_str(rec), + block->BlockNumber); break; + } + } + /* + * At this point, we have at least a record header. + * Now decide if we want this record or not, but remember + * before accessing the record, we may need to read again to + * get all the data. + */ + record++; + if (verbose) { + Dmsg6(30, "recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record, + rec_state_to_str(rec), block->BlockNumber, + rec->VolSessionId, rec->VolSessionTime, rec->FileIndex); } - if (debug_level > 0) { - printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", - rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); + if (debug_level >= 30) { + Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId, + FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream), + rec->data_len); } - Dmsg1(40, "Got label = %d\n", rec->FileIndex); - if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ - Dmsg0(40, "Get EOM LABEL\n"); - break; /* yes, get out */ + /* + * Check for End of File record (all zeros) + * NOTE: this no longer exists + */ + if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) { + Emsg0(M_ERROR_TERM, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n"); } - continue; /* ignore other labels */ - } /* end if label record */ - - /* - * Apply BSR filter - */ - if (bsr && !match_bsr(bsr, rec, &dev->VolHdr, &sessrec)) { - continue; - } - /* File Attributes stream */ - if (rec->Stream == STREAM_UNIX_ATTRIBUTES) { - char *ap, *fp; - sscanf(rec->data, "%ld %d", &record_file_index, &type); - if (record_file_index != rec->FileIndex) { - Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n", - rec->FileIndex, record_file_index); + /* + * Check for Start or End of Session Record + * + */ + if (rec->FileIndex < 0) { + char *rtype; + memset(&sessrec, 0, sizeof(sessrec)); + switch (rec->FileIndex) { + case PRE_LABEL: + rtype = "Fresh Volume Label"; + break; + case VOL_LABEL: + rtype = "Volume Label"; + unser_volume_label(dev, rec); + break; + case SOS_LABEL: + rtype = "Begin Session"; + unser_session_label(&sessrec, rec); + break; + case EOS_LABEL: + rtype = "End Session"; + break; + case EOM_LABEL: + rtype = "End of Media"; + break; + default: + rtype = "Unknown"; + break; + } + if (debug_level > 0) { + printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); + } + + Dmsg1(40, "Got label = %d\n", rec->FileIndex); + if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ + Dmsg0(100, "EOM LABEL break\n"); + rec->remainder = 0; + break; /* yes, get out */ + } + rec->remainder = 0; + if (rec->state & REC_BLOCK_EMPTY) { + Dmsg0(100, "Empty, break.\n"); + break; /* don't want record, read next block */ + } else { + Dmsg0(100, "Label, continue.\n"); + continue; /* we don't want record, read next one */ + } + } /* end if label record */ + + /* + * Apply BSR filter + */ + if (bsr && !match_bsr(bsr, rec, &dev->VolHdr, &sessrec)) { + if (verbose) { + Dmsg5(10, "BSR no match rec=%d block=%d SessId=%d SessTime=%d FI=%d\n", + record, block->BlockNumber, rec->VolSessionId, rec->VolSessionTime, + rec->FileIndex); + } + rec->remainder = 0; + if (rec->state & REC_BLOCK_EMPTY) { + Dmsg0(100, "Empty, break.\n"); + break; /* don't want record, read next block */ + } else { + Dmsg0(100, "BSR reject, continue.\n"); + continue; /* we don't want record, read next one */ + } } - ap = rec->data; - - while (*ap++ != ' ') /* skip record file index */ - ; - while (*ap++ != ' ') /* skip type */ - ; - /* Save filename and position to attributes */ - fp = fname; - while (*ap != 0) { - *fp++ = *ap++; + if (rec->state & REC_PARTIAL_RECORD) { + Dmsg6(10, "Partial, break. recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record, + rec_state_to_str(rec), block->BlockNumber, + rec->VolSessionId, rec->VolSessionTime, rec->FileIndex); + break; /* read second part of record */ } - *fp = *ap++; /* terminate filename & point to attribs */ - decode_stat(ap, &statp); - /* Skip to link name */ - while (*ap++ != 0) - ; - print_ls_output(fname, ap, type, &statp); + /* File Attributes stream */ + if (rec->Stream == STREAM_UNIX_ATTRIBUTES) { + char *ap, *fp; + sscanf(rec->data, "%ld %d", &record_file_index, &type); + if (record_file_index != rec->FileIndex) { + Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n", + rec->FileIndex, record_file_index); + } + ap = rec->data; + + while (*ap++ != ' ') /* skip record file index */ + ; + while (*ap++ != ' ') /* skip type */ + ; + /* Save filename and position to attributes */ + fp = fname; + while (*ap != 0) { + *fp++ = *ap++; + } + *fp = *ap++; /* terminate filename & point to attribs */ + + decode_stat(ap, &statp); + /* Skip to link name */ + while (*ap++ != 0) + ; + print_ls_output(fname, ap, type, &statp); + num_files++; + } } } + if (verbose) { + printf("%u files found.\n", num_files); + } return; } diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index edfb265b68..fb2dae35f7 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -2,7 +2,7 @@ * * record.c -- tape record handling functions * - * Kern Sibbald, April MMI + * Kern Sibbald, April MMI * * Version $Id$ * @@ -119,7 +119,7 @@ void free_record(DEV_RECORD *rec) * if necessary, handle getting a new Volume * * Returns: 0 on failure - * 1 on success + * 1 on success */ int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record) { @@ -127,15 +127,15 @@ int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record) while (!read_record_from_block(block, record)) { Dmsg2(90, "!read_record_from_block data_len=%d rem=%d\n", record->data_len, - record->remainder); + record->remainder); if (!read_block_from_dev(dev, block)) { Dmsg0(200, "===== Got read block I/O error ======\n"); - return 0; + return 0; } } Dmsg4(90, "read_record FI=%s SessId=%d Strm=%s len=%d\n", - FI_to_ascii(record->FileIndex), record->VolSessionId, - stream_to_ascii(record->Stream), record->data_len); + FI_to_ascii(record->FileIndex), record->VolSessionId, + stream_to_ascii(record->Stream), record->data_len); record->File = dev->file; record->Block = dev->block_num; return 1; @@ -146,7 +146,7 @@ int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record) * Write a Record to the block * * Returns: 0 on failure (none or partially written) - * 1 on success (all bytes written) + * 1 on success (all bytes written) * * and remainder returned in packet. * @@ -181,22 +181,22 @@ rem=%d remainder=%d\n", if (rec->remainder == 0) { /* Require enough room to write a full header */ if (remlen >= RECHDR_LENGTH) { - ser_begin(block->bufp, RECHDR_LENGTH); - ser_uint32(rec->VolSessionId); - ser_uint32(rec->VolSessionTime); - ser_int32(rec->FileIndex); - ser_int32(rec->Stream); - ser_uint32(rec->data_len); - ASSERT(ser_length(block->bufp) == RECHDR_LENGTH); - - block->bufp += RECHDR_LENGTH; - block->binbuf += RECHDR_LENGTH; - remlen -= RECHDR_LENGTH; - rec->remainder = rec->data_len; + ser_begin(block->bufp, RECHDR_LENGTH); + ser_uint32(rec->VolSessionId); + ser_uint32(rec->VolSessionTime); + ser_int32(rec->FileIndex); + ser_int32(rec->Stream); + ser_uint32(rec->data_len); + ASSERT(ser_length(block->bufp) == RECHDR_LENGTH); + + block->bufp += RECHDR_LENGTH; + block->binbuf += RECHDR_LENGTH; + remlen -= RECHDR_LENGTH; + rec->remainder = rec->data_len; } else { - rec->remainder = rec->data_len + RECHDR_LENGTH; - sm_check(__FILE__, __LINE__, False); - return 0; + rec->remainder = rec->data_len + RECHDR_LENGTH; + sm_check(__FILE__, __LINE__, False); + return 0; } } else { /* @@ -219,12 +219,12 @@ rem=%d remainder=%d\n", ser_uint32(rec->VolSessionTime); ser_int32(rec->FileIndex); if (rec->remainder > rec->data_len) { - ser_int32(rec->Stream); /* normal full header */ - ser_uint32(rec->data_len); - rec->remainder = rec->data_len; /* must still do data record */ + ser_int32(rec->Stream); /* normal full header */ + ser_uint32(rec->data_len); + rec->remainder = rec->data_len; /* must still do data record */ } else { - ser_int32(-rec->Stream); /* mark this as a continuation record */ - ser_uint32(rec->remainder); /* bytes to do */ + ser_int32(-rec->Stream); /* mark this as a continuation record */ + ser_uint32(rec->remainder); /* bytes to do */ } ASSERT(ser_length(block->bufp) == RECHDR_LENGTH); @@ -237,7 +237,7 @@ rem=%d remainder=%d\n", } if (remlen == 0) { sm_check(__FILE__, __LINE__, False); - return 0; /* partial transfer */ + return 0; /* partial transfer */ } /* @@ -248,36 +248,36 @@ rem=%d remainder=%d\n", if (rec->remainder > 0) { /* Write as much of data as possible */ if (remlen >= rec->remainder) { - memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, - rec->remainder); - block->bufp += rec->remainder; - block->binbuf += rec->remainder; + memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, + rec->remainder); + block->bufp += rec->remainder; + block->binbuf += rec->remainder; } else { - memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, - remlen); - if (!sm_check_rtn(__FILE__, __LINE__, False)) { - /* We damaged a buffer */ + memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, + remlen); + if (!sm_check_rtn(__FILE__, __LINE__, False)) { + /* We damaged a buffer */ Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n\ rem=%d remainder=%d\n", - FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len, - remlen, rec->remainder); + FI_to_ascii(rec->FileIndex), rec->VolSessionId, + stream_to_ascii(rec->Stream), rec->data_len, + remlen, rec->remainder); Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n", - block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf, - remlen); + block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf, + remlen); Dmsg2(0, "Damaged block: buf=%x binbuffrombuf=%d \n", - block->buf, block->bufp-block->buf); + block->buf, block->bufp-block->buf); Emsg0(M_ABORT, 0, "Damaged buffer\n"); - } + } - block->bufp += remlen; - block->binbuf += remlen; - rec->remainder -= remlen; - return 0; /* did partial transfer */ + block->bufp += remlen; + block->binbuf += remlen; + rec->remainder -= remlen; + return 0; /* did partial transfer */ } } - rec->remainder = 0; /* did whole transfer */ + rec->remainder = 0; /* did whole transfer */ sm_check(__FILE__, __LINE__, False); return 1; } @@ -286,7 +286,7 @@ rem=%d remainder=%d\n", /* * Read a Record from the block * Returns: 0 on failure - * 1 on success + * 1 on success */ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) { @@ -300,13 +300,16 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) remlen = block->binbuf; + /* Clear state flags */ + rec->state = 0; + /* * Get the header. There is always a full header, * otherwise we find it in the next block. */ if (remlen >= RECHDR_LENGTH) { Dmsg3(90, "read_record_block: remlen=%d data_len=%d rem=%d\n", - remlen, rec->data_len, rec->remainder); + remlen, rec->data_len, rec->remainder); unser_begin(block->bufp, RECHDR_LENGTH); unser_uint32(VolSessionId); @@ -324,20 +327,22 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) * if Stream is negative, it means that this is a continuation * of a previous partially written record. */ - if (Stream < 0) { /* continuation record? */ + if (Stream < 0) { /* continuation record? */ Dmsg1(500, "Got negative Stream => continuation. remainder=%d\n", - rec->remainder); + rec->remainder); + rec->state |= REC_CONTINUATION; if (!rec->remainder) { /* if we didn't read previously */ - rec->data_len = 0; /* return data as if no continuation */ - } else if (rec->VolSessionId != VolSessionId || - rec->VolSessionTime != VolSessionTime || - rec->Stream != -Stream) { - return 0; /* This is from some other Session */ - } - rec->Stream = -Stream; /* set correct Stream */ - } else { /* Regular record */ - rec->Stream = Stream; - rec->data_len = 0; /* transfer to beginning of data */ + rec->data_len = 0; /* return data as if no continuation */ + } else if (rec->VolSessionId != VolSessionId || + rec->VolSessionTime != VolSessionTime || + rec->Stream != -Stream) { + rec->state |= REC_NO_MATCH; + return 0; /* This is from some other Session */ + } + rec->Stream = -Stream; /* set correct Stream */ + } else { /* Regular record */ + rec->Stream = Stream; + rec->data_len = 0; /* transfer to beginning of data */ } rec->VolSessionId = VolSessionId; rec->VolSessionTime = VolSessionTime; @@ -345,8 +350,8 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) Dmsg6(90, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%d\n\ remlen=%d data_len=%d\n", - FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), data_bytes, remlen, rec->data_len); + FI_to_ascii(rec->FileIndex), rec->VolSessionId, + stream_to_ascii(rec->Stream), data_bytes, remlen, rec->data_len); } else { /* * No more records in this block because the number @@ -358,13 +363,14 @@ remlen=%d data_len=%d\n", */ Dmsg0(90, "read_record_block: nothing\n"); if (!rec->remainder) { - rec->remainder = 1; /* set to expect continuation */ - rec->data_len = 0; /* no data transferred */ + rec->remainder = 1; /* set to expect continuation */ + rec->data_len = 0; /* no data transferred */ } + rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY); return 0; } - ASSERT(data_bytes < MAX_BLOCK_LENGTH); /* temp sanity check */ + ASSERT(data_bytes < MAX_BLOCK_LENGTH); /* temp sanity check */ rec->data = check_pool_memory_size(rec->data, rec->data_len+data_bytes); @@ -388,13 +394,15 @@ remlen=%d data_len=%d\n", block->bufp += remlen; block->binbuf -= remlen; rec->data_len += remlen; - rec->remainder = 1; /* partial record transferred */ + rec->remainder = 1; /* partial record transferred */ Dmsg1(90, "read_record_block: partial xfered=%d\n", rec->data_len); + rec->state |= (REC_PARTIAL_RECORD | REC_BLOCK_EMPTY); + /********FIXME********* this should return 1 */ return 0; } rec->remainder = 0; Dmsg4(90, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, stream_to_ascii(rec->Stream), rec->data_len); - return 1; /* transferred full record */ + return 1; /* transferred full record */ } diff --git a/bacula/src/stored/record.h b/bacula/src/stored/record.h index 4e8919b3b7..fe6f41cea1 100644 --- a/bacula/src/stored/record.h +++ b/bacula/src/stored/record.h @@ -55,6 +55,12 @@ typedef struct s_record_hdr { uint32_t data_len; } RECORD_HDR; +#define REC_NO_HEADER 0x01 /* No header read */ +#define REC_PARTIAL_RECORD 0x02 /* returning partial record */ +#define REC_BLOCK_EMPTY 0x04 /* not enough data in block */ +#define REC_NO_MATCH 0x08 /* No match on continuation data */ +#define REC_CONTINUATION 0x10 /* Continuation record found */ + /* * DEV_RECORD for reading and writing records. * It consists of a Record Header, and the Record Data @@ -74,6 +80,7 @@ typedef struct s_dev_rec { int32_t Stream; /* stream number */ uint32_t data_len; /* current record length */ uint32_t remainder; /* remaining bytes to read/write */ + uint32_t state; /* state bits */ uint8_t ser_buf[RECHDR_LENGTH]; /* serialized record header goes here */ POOLMEM *data; /* Record data. This MUST be a memory pool item */ } DEV_RECORD; -- 2.39.5