static int write_to_changed_file(struct asfd *asfd, struct asfd *chfd, struct manios *manios, struct slist *slist, int end_flags) { struct sbuf *sb; if(!slist) return 0; while((sb=slist->head)) { if(sb->flags & SBUF_NEED_DATA) { switch(sbuf_needs_data(sb, asfd, chfd, manios, slist, end_flags)) { case 0: return 0; case 1: continue; default: return -1; } } else { // No change, can go straight in. if(manio_write_sbuf(manios->changed, sb)) return -1; if(write_endfile(sb, manios)) return -1; // Move along. slist_advance(slist); } } return 0; }
static int sbuf_needs_data(struct sbuf *sb, struct asfd *asfd, struct asfd *chfd, struct manios *manios, struct slist *slist, int end_flags) { int ret=-1; struct blk *blk; static struct iobuf wbuf; struct blist *blist=slist->blist; if(!(sb->flags & SBUF_HEADER_WRITTEN_TO_MANIFEST)) { if(manio_write_sbuf(manios->changed, sb)) goto end; sb->flags |= SBUF_HEADER_WRITTEN_TO_MANIFEST; } while((blk=sb->protocol2->bstart) && blk->got==BLK_GOT && (blk->next || end_flags&END_BACKUP)) { if(blk->got_save_path && !blk_is_zero_length(blk)) { if(breaking && breakcount--==0) { breakpoint(breaking, __func__); goto end; } if(manio_write_sig_and_path(manios->changed, blk)) goto end; if(manios->changed->sig_count==0) { // Have finished a manifest file. Want to start // using it as a dedup candidate now. if(manio_component_to_chfd(chfd, manios->changed->offset->ppath)) goto end; if(!blk->requested) { // Also let the client know, so that it // can free memory if there was a long // consecutive number of unrequested // blocks. get_wbuf_from_index(&wbuf, blk->index); if(asfd->write(asfd, &wbuf)) goto end; } } } if(blk==sb->protocol2->bend) { blist_adjust_head(blist, sb); if(write_endfile(sb, manios)) return -1; slist_advance(slist); return 1; } if(sb->protocol2->bsighead==sb->protocol2->bstart) sb->protocol2->bsighead=blk->next; sb->protocol2->bstart=blk->next; if(blk==blist->blk_from_champ_chooser) blist->blk_from_champ_chooser=blk->next; } if(!blk && sb && !sb->protocol2->bend && (end_flags&END_BACKUP)) { // Write endfile for the very last file. if(write_endfile(sb, manios)) return -1; } ret=0; end: blist_adjust_head(blist, sb); return ret; }
static int sbuf_needs_data(struct sbuf *sb, struct asfd *asfd, struct asfd *chfd, struct manios *manios, struct slist *slist, int end_flags) { int ret=-1; struct blk *blk; static struct iobuf wbuf; struct blist *blist=slist->blist; static int unrequested=0; if(!(sb->flags & SBUF_HEADER_WRITTEN_TO_MANIFEST)) { if(manio_write_sbuf(manios->changed, sb)) goto end; sb->flags |= SBUF_HEADER_WRITTEN_TO_MANIFEST; } while((blk=sb->protocol2->bstart) && blk->got==BLK_GOT && (blk->next || end_flags&END_BACKUP)) { if(blk->got_save_path && !blk_is_zero_length(blk)) { if(breaking && breakcount--==0) { breakpoint(breaking, __func__); goto end; } if(manio_write_sig_and_path(manios->changed, blk)) goto end; if(manios->changed->sig_count==0) { // Have finished a manifest file. Want to start // using it as a dedup candidate now. if(manio_component_to_chfd(chfd, manios->changed->offset->ppath)) goto end; // The champ chooser has the candidate. Now, // empty our local hash table. hash_delete_all(); // Add the most recent block, so identical // adjacent blocks are deduplicated well. if(hash_load_blk(blk)) goto end; } } if(!blk->requested) unrequested++; if(unrequested>BLKS_MAX_UNREQUESTED) { unrequested=0; // Let the client know that it can free memory if there // was a long consecutive number of unrequested blocks. get_wbuf_from_index(&wbuf, blk->index); if(asfd->write(asfd, &wbuf)) goto end; } if(blk==sb->protocol2->bend) { blist_adjust_head(blist, sb); if(write_endfile(sb, manios)) return -1; slist_advance(slist); return 1; } if(sb->protocol2->bsighead==sb->protocol2->bstart) sb->protocol2->bsighead=blk->next; sb->protocol2->bstart=blk->next; if(blk==blist->blk_from_champ_chooser) blist->blk_from_champ_chooser=blk->next; } if(!blk && sb && !sb->protocol2->bend && (end_flags&END_BACKUP)) { // Write endfile for the very last file. if(write_endfile(sb, manios)) return -1; } ret=0; end: blist_adjust_head(blist, sb); return ret; }