Esempio n. 1
0
File: askdir.c Progetto: AlD/bareos
/**
 * 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();
}
Esempio n. 2
0
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;
   }
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
/*
 * 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);
	}

}