/** * Update File Attribute data * We do the following: * 1. expand the bsock buffer to be large enough * 2. Write a "header" into the buffer with serialized data * VolSessionId * VolSeesionTime * FileIndex * Stream * data length that follows * start of raw byte data from the Device record. * Note, this is primarily for Attribute data, but can * also handle any device record. The Director must know * the raw byte data format that is defined for each Stream. * Now Restore Objects pass through here STREAM_RESTORE_OBJECT */ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { JCR *jcr = dcr->jcr; BSOCK *dir = jcr->dir_bsock; ser_declare; #ifdef NO_ATTRIBUTES_TEST return true; #endif dir->msg = check_pool_memory_size(dir->msg, sizeof(FileAttributes) + MAX_NAME_LENGTH + sizeof(DEV_RECORD) + rec->data_len + 1); dir->msglen = bsnprintf(dir->msg, sizeof(FileAttributes) + MAX_NAME_LENGTH + 1, FileAttributes, jcr->Job); ser_begin(dir->msg + dir->msglen, 0); ser_uint32(rec->VolSessionId); ser_uint32(rec->VolSessionTime); ser_int32(rec->FileIndex); ser_int32(rec->Stream); ser_uint32(rec->data_len); ser_bytes(rec->data, rec->data_len); dir->msglen = ser_length(dir->msg); Dmsg1(1800, ">dird %s\n", dir->msg); /* Attributes */ return dir->send(); }
static inline void write_continue_header_to_block(DEV_BLOCK *block, DEV_RECORD *rec) { ser_declare; rec->remlen = block->buf_len - block->binbuf; /* * We have unwritten bytes from a previous * time. Presumably we have a new buffer (possibly * containing a volume label), so the new header * should be able to fit in the block -- otherwise we have * an error. Note, we have to continue splitting the * data record if it is longer than the block. * * First, write the header. * * Every time we write a header and it is a continuation * of a previous partially written record, we store the * Stream as -Stream in the record header. */ ser_begin(block->bufp, WRITE_RECHDR_LENGTH); if (BLOCK_VER == 1) { ser_uint32(rec->VolSessionId); ser_uint32(rec->VolSessionTime); } else { block->VolSessionId = rec->VolSessionId; block->VolSessionTime = 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 */ } else { ser_int32(-rec->Stream); /* mark this as a continuation record */ ser_uint32(rec->remainder); /* bytes to do */ } /* * Require enough room to write a full header */ ASSERT(rec->remlen >= WRITE_RECHDR_LENGTH); block->bufp += WRITE_RECHDR_LENGTH; block->binbuf += WRITE_RECHDR_LENGTH; rec->remlen -= WRITE_RECHDR_LENGTH; if (rec->FileIndex > 0) { /* * If data record, update what we have in this block */ if (block->FirstIndex == 0) { block->FirstIndex = rec->FileIndex; } block->LastIndex = rec->FileIndex; } }
static inline bool write_header_to_block(DEV_BLOCK *block, DEV_RECORD *rec) { ser_declare; rec->remlen = block->buf_len - block->binbuf; /* * Require enough room to write a full header */ if (rec->remlen >= WRITE_RECHDR_LENGTH) { ser_begin(block->bufp, WRITE_RECHDR_LENGTH); if (BLOCK_VER == 1) { ser_uint32(rec->VolSessionId); ser_uint32(rec->VolSessionTime); } else { block->VolSessionId = rec->VolSessionId; block->VolSessionTime = rec->VolSessionTime; } ser_int32(rec->FileIndex); ser_int32(rec->Stream); ser_uint32(rec->data_len); block->bufp += WRITE_RECHDR_LENGTH; block->binbuf += WRITE_RECHDR_LENGTH; rec->remlen -= WRITE_RECHDR_LENGTH; rec->remainder = rec->data_len; if (rec->FileIndex > 0) { /* * If data record, update what we have in this block */ if (block->FirstIndex == 0) { block->FirstIndex = rec->FileIndex; } block->LastIndex = rec->FileIndex; } } else { rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH; return false; } return true; }
static inline ssize_t write_header_to_block(DEV_BLOCK *block, const DEV_RECORD *rec, int32_t Stream) { ser_declare; /* * Require enough room to write a full header */ if (block_write_navail(block) < WRITE_RECHDR_LENGTH) return -1; ser_begin(block->bufp, WRITE_RECHDR_LENGTH); if (BLOCK_VER == 1) { ser_uint32(rec->VolSessionId); ser_uint32(rec->VolSessionTime); } else { block->VolSessionId = rec->VolSessionId; block->VolSessionTime = rec->VolSessionTime; } ser_int32(rec->FileIndex); ser_int32(Stream); ser_uint32(rec->remainder); /* each header tracks remaining user bytes to write */ block->bufp += WRITE_RECHDR_LENGTH; block->binbuf += WRITE_RECHDR_LENGTH; if (rec->FileIndex > 0) { /* * If data record, update what we have in this block */ if (block->FirstIndex == 0) { block->FirstIndex = rec->FileIndex; } block->LastIndex = rec->FileIndex; } return WRITE_RECHDR_LENGTH; }
/* * Called by Append phase */ void write_container(struct container* c) { assert(c->meta.chunk_num == g_hash_table_size(c->meta.map)); if (container_empty(c)) { /* An empty container * It possibly occurs in the end of backup */ container_count--; VERBOSE("Append phase: Deny writing an empty container %lld", c->meta.id); return; } VERBOSE("Append phase: Writing container %lld of %d chunks", c->meta.id, c->meta.chunk_num); if (destor.simulation_level < SIMULATION_APPEND) { unsigned char * cur = &c->data[CONTAINER_SIZE - CONTAINER_META_SIZE]; ser_declare; ser_begin(cur, CONTAINER_META_SIZE); ser_int64(c->meta.id); ser_int32(c->meta.chunk_num); ser_int32(c->meta.data_size); GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, c->meta.map); while (g_hash_table_iter_next(&iter, &key, &value)) { struct metaEntry *me = (struct metaEntry *) value; ser_bytes(&me->fp, sizeof(fingerprint)); ser_bytes(&me->len, sizeof(int32_t)); ser_bytes(&me->off, sizeof(int32_t)); } ser_end(cur, CONTAINER_META_SIZE); pthread_mutex_lock(&mutex); if (fseek(fp, c->meta.id * CONTAINER_SIZE + 8, SEEK_SET) != 0) { perror("Fail seek in container store."); exit(1); } if(fwrite(c->data, CONTAINER_SIZE, 1, fp) != 1){ perror("Fail to write a container in container store."); exit(1); } pthread_mutex_unlock(&mutex); } else { char buf[CONTAINER_META_SIZE]; memset(buf, 0, CONTAINER_META_SIZE); ser_declare; ser_begin(buf, CONTAINER_META_SIZE); ser_int64(c->meta.id); ser_int32(c->meta.chunk_num); ser_int32(c->meta.data_size); GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, c->meta.map); while (g_hash_table_iter_next(&iter, &key, &value)) { struct metaEntry *me = (struct metaEntry *) value; ser_bytes(&me->fp, sizeof(fingerprint)); ser_bytes(&me->len, sizeof(int32_t)); ser_bytes(&me->off, sizeof(int32_t)); } ser_end(buf, CONTAINER_META_SIZE); pthread_mutex_lock(&mutex); if(fseek(fp, c->meta.id * CONTAINER_META_SIZE + 8, SEEK_SET) != 0){ perror("Fail seek in container store."); exit(1); } if(fwrite(buf, CONTAINER_META_SIZE, 1, fp) != 1){ perror("Fail to write a container in container store."); exit(1); } pthread_mutex_unlock(&mutex); } }