void IWriter::w_chunk(u32 type, void* data, u32 size) { open_chunk(type); if (type & CFS_CompressMark) w_compressed(data, size); else w(data, size); close_chunk(); }
static void finish_chunk_impl( XferDestHolding *xdh) { XferDestHolding *self = XFER_DEST_HOLDING(xdh); g_mutex_lock(self->state_mutex); close_chunk(self, NULL); g_mutex_unlock(self->state_mutex); }
static gpointer holding_thread( gpointer data) { XferDestHolding *self = XFER_DEST_HOLDING(data); XferElement *elt = XFER_ELEMENT(self); XMsg *msg; gchar *mesg = NULL; GTimer *timer = g_timer_new(); DBG(1, "(this is the holding thread)"); /* This is the outer loop, that loops once for each holding file or * CONTINUE command */ g_mutex_lock(self->state_mutex); while (1) { gboolean done; /* wait until the main thread un-pauses us, and check that we have * the relevant holding info available */ while (self->paused && !elt->cancelled) { DBG(9, "waiting to be unpaused"); g_cond_wait(self->state_cond, self->state_mutex); } DBG(9, "holding_thread done waiting"); if (elt->cancelled) break; self->data_bytes_written = 0; self->header_bytes_written = 0; /* new holding file */ if (self->filename == NULL || strcmp(self->filename, self->new_filename) != 0) { char *tmp_filename; char *pc; int fd; ssize_t write_header_size; if (self->use_bytes < HEADER_BLOCK_BYTES) { self->chunk_status = CHUNK_NO_ROOM; goto no_room; } tmp_filename = g_strjoin(NULL, self->new_filename, ".tmp", NULL); pc = strrchr(tmp_filename, '/'); g_assert(pc != NULL); *pc = '\0'; mkholdingdir(tmp_filename); *pc = '/'; fd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600); if (fd < 0) { self->chunk_status = CHUNK_NO_ROOM; g_free(mesg); mesg = g_strdup_printf("Failed to open '%s': %s", tmp_filename, strerror(errno)); g_free(tmp_filename); goto no_room; } if (self->filename == NULL) { self->chunk_header->type = F_DUMPFILE; } else { self->chunk_header->type = F_CONT_DUMPFILE; } self->chunk_header->cont_filename[0] = '\0'; write_header_size = write_header(self, fd); if (write_header_size != HEADER_BLOCK_BYTES) { self->chunk_status = CHUNK_NO_ROOM; mesg = g_strdup_printf("Failed to write header to '%s': %s", tmp_filename, strerror(errno)); close(fd); unlink(tmp_filename); g_free(tmp_filename); goto no_room; } g_free(tmp_filename); self->use_bytes -= HEADER_BLOCK_BYTES; /* rewrite old_header */ if (self->filename && strcmp(self->filename, self->new_filename) != 0) { close_chunk(self, self->new_filename); } self->filename = self->new_filename; self->new_filename = NULL; self->fd = fd; self->header_bytes_written = HEADER_BLOCK_BYTES; self->chunk_offset = HEADER_BLOCK_BYTES; } DBG(2, "beginning to write chunk"); done = holding_thread_write_chunk(self); DBG(2, "done writing chunk"); if (!done) /* cancelled */ break; no_room: msg = xmsg_new(XFER_ELEMENT(self), XMSG_CHUNK_DONE, 0); msg->header_size = self->header_bytes_written; msg->data_size = self->data_bytes_written; msg->no_room = (self->chunk_status == CHUNK_NO_ROOM); if (mesg) { msg->message = mesg; mesg = NULL; } xfer_queue_message(elt->xfer, msg); /* pause ourselves and await instructions from the main thread */ self->paused = TRUE; /* if this is the last part, we're done with the chunk loop */ if (self->chunk_status == CHUNK_EOF) { break; } } g_mutex_unlock(self->state_mutex); g_debug("sending XMSG_CRC message"); g_debug("xfer-dest-holding CRC: %08x size: %lld", crc32_finish(&elt->crc), (long long)elt->crc.size); msg = xmsg_new(XFER_ELEMENT(self), XMSG_CRC, 0); msg->crc = crc32_finish(&elt->crc); msg->size = elt->crc.size; xfer_queue_message(elt->xfer, msg); msg = xmsg_new(XFER_ELEMENT(self), XMSG_DONE, 0); msg->duration = g_timer_elapsed(timer, NULL); g_timer_destroy(timer); /* tell the main thread we're done */ xfer_queue_message(elt->xfer, msg); return NULL; }