int backup_phase2_server(gzFile *cmanfp, const char *phase1data, const char *phase2data, const char *unchangeddata, const char *datadirtmp, struct dpth *dpth, const char *currentdata, const char *working, const char *client, struct cntr *p1cntr, int resume, struct cntr *cntr, struct config *cconf) { int ars=0; int ret=0; gzFile p1zp=NULL; char *deltmppath=NULL; char *last_requested=NULL; // Where to write phase2data. // Data is not getting written to a compressed file. // This is important for recovery if the power goes. FILE *p2fp=NULL; // unchanged data FILE *ucfp=NULL; int resume_partial=resume; struct sbuf cb; // file list in current manifest struct sbuf p1b; // file list from client struct sbuf rb; // receiving file from client init_sbuf(&cb); init_sbuf(&p1b); init_sbuf(&rb); if(!(p1zp=gzopen_file(phase1data, "rb"))) goto error; // Open in read+write mode, so that they can be read through if // we need to resume. // First, open them in a+ mode, so that they will be created if they // do not exist. if(!(ucfp=open_file(unchangeddata, "a+b"))) goto error; if(!(p2fp=open_file(phase2data, "a+b"))) goto error; close_fp(&ucfp); close_fp(&p2fp); if(!(ucfp=open_file(unchangeddata, "r+b"))) goto error; if(!(p2fp=open_file(phase2data, "r+b"))) goto error; if(resume && do_resume(p1zp, p2fp, ucfp, dpth, cconf, client, p1cntr, cntr)) goto error; logp("Begin phase2 (receive file data)\n"); if(!(deltmppath=prepend_s(working, "delta.tmp", strlen("delta.tmp")))) goto error; while(1) { int sts=0; // logp("in loop, %s %s %c\n", // *cmanfp?"got cmanfp":"no cmanfp", // rb.path?:"no rb.path", rb.path?'X':rb.cmd); if(rb.path) write_status(client, STATUS_BACKUP, rb.path, p1cntr, cntr); else write_status(client, STATUS_BACKUP, p1b.path, p1cntr, cntr); if((last_requested || !p1zp || writebuflen) && (ars=do_stuff_to_receive(&rb, p2fp, datadirtmp, dpth, working, &last_requested, deltmppath, cntr, cconf))) { if(ars<0) goto error; // 1 means ok. break; } if((sts=do_stuff_to_send(&p1b, &last_requested))<0) goto error; if(!sts && p1zp) { free_sbuf(&p1b); if((ars=sbuf_fill_phase1(NULL, p1zp, &p1b, cntr))) { if(ars<0) goto error; // ars==1 means it ended ok. gzclose_fp(&p1zp); //logp("ended OK - write phase2end"); if(async_write_str(CMD_GEN, "backupphase2end")) goto error; } //logp("check: %s\n", p1b.path); if(!*cmanfp) { // No old manifest, need to ask for a new file. //logp("no cmanfp\n"); if(process_new(&p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, &resume_partial, cntr, cconf)) goto error; } else { // Have an old manifest, look for it there. // Might already have it, or be ahead in the old // manifest. if(cb.path) { if((ars=maybe_process_file(&cb, &p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, &resume_partial, cntr, cconf))) { if(ars<0) goto error; // Do not free it - need to send stuff. continue; } //free_sbuf(&p1b); } while(*cmanfp) { free_sbuf(&cb); if((ars=sbuf_fill(NULL, *cmanfp, &cb, cntr))) { // ars==1 means it ended ok. if(ars<0) goto error; gzclose_fp(cmanfp); //logp("ran out of current manifest\n"); if(process_new(&p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, &resume_partial, cntr, cconf)) goto error; break; } //logp("against: %s\n", cb.path); if((ars=maybe_process_file(&cb, &p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, &resume_partial, cntr, cconf))) { if(ars<0) goto error; // Do not free it - need to send stuff. break; } } } } } goto end; error: ret=-1; end: if(close_fp(&p2fp)) { logp("error closing %s in backup_phase2_server\n", phase2data); ret=-1; } if(close_fp(&ucfp)) { logp("error closing %s in backup_phase2_server\n", unchangeddata); ret=-1; } free(deltmppath); free_sbuf(&cb); free_sbuf(&p1b); free_sbuf(&rb); gzclose_fp(&p1zp); if(!ret) unlink(phase1data); logp("End phase2 (receive file data)\n"); return ret; }
int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs, const char *incexc, int resume, struct conf **cconfs) { int ret=0; struct manio *p1manio=NULL; struct dpth *dpth=NULL; char *deltmppath=NULL; char *last_requested=NULL; // Where to write changed data. // Data is not getting written to a compressed file. // This is important for recovery if the power goes. struct fzp *chfp=NULL; struct fzp *ucfp=NULL; // unchanged data struct fzp *cmanfp=NULL; // previous (current) manifest. struct sbuf *cb=NULL; // file list in current manifest struct sbuf *p1b=NULL; // file list from client struct sbuf *rb=NULL; // receiving file from client struct asfd *asfd=as->asfd; int breaking=0; int breakcount=0; if(get_int(cconfs[OPT_BREAKPOINT])>=2000 && get_int(cconfs[OPT_BREAKPOINT])<3000) { breaking=get_int(cconfs[OPT_BREAKPOINT]); breakcount=breaking-2000; } logp("Begin phase2 (receive file data)\n"); if(!(dpth=dpth_alloc()) || dpth_protocol1_init(dpth, sdirs->currentdata, get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS]))) goto error; if(open_previous_manifest(&cmanfp, sdirs, incexc, cconfs)) goto error; if(get_int(cconfs[OPT_DIRECTORY_TREE])) { // Need to make sure we do not try to create a path that is // too long. if(build_path_w(sdirs->treepath)) goto error; treepathlen=strlen(sdirs->treepath); init_fs_max(sdirs->treepath); } if(!(p1manio=manio_alloc()) || manio_init_read(p1manio, sdirs->phase1data) || !(cb=sbuf_alloc(cconfs)) || !(p1b=sbuf_alloc(cconfs)) || !(rb=sbuf_alloc(cconfs))) goto error; manio_set_protocol(p1manio, PROTO_1); if(resume && do_resume(p1manio, sdirs, dpth, cconfs)) goto error; // Unchanged and changed should now be truncated correctly, we just // have to open them for appending. if(!(ucfp=fzp_open(sdirs->unchanged, "a+b")) || !(chfp=fzp_open(sdirs->changed, "a+b"))) goto error; if(manio_closed(p1manio) && manio_open_next_fpath(p1manio)) goto error; while(1) { if(breaking) { if(breakcount--==0) return breakpoint(cconfs, __func__); } //printf("in loop, %s %s %c\n", // cmanfp?"got cmanfp":"no cmanfp", // rb->path.buf?:"no rb->path", // rb->path.buf?'X':rb->path.cmd); if(write_status(CNTR_STATUS_BACKUP, rb->path.buf?rb->path.buf:p1b->path.buf, cconfs)) goto error; if(last_requested || manio_closed(p1manio) || asfd->writebuflen) { switch(do_stuff_to_receive(asfd, sdirs, cconfs, rb, chfp, dpth, &last_requested)) { case 0: break; case 1: goto end; // Finished ok. case -1: goto error; } } switch(do_stuff_to_send(asfd, p1b, &last_requested)) { case 0: break; case 1: continue; case -1: goto error; } if(manio_closed(p1manio)) continue; sbuf_free_content(p1b); switch(manio_sbuf_fill_phase1(p1manio, asfd, p1b, NULL, sdirs, cconfs)) { case 0: break; case 1: manio_close(p1manio); if(asfd->write_str(asfd, CMD_GEN, "backupphase2end")) goto error; break; case -1: goto error; } if(!cmanfp) { // No old manifest, need to ask for a new file. if(process_new(sdirs, cconfs, p1b, ucfp)) goto error; continue; } // Have an old manifest, look for it there. // Might already have it, or be ahead in the old // manifest. if(cb->path.buf) switch(maybe_process_file(asfd, sdirs, cb, p1b, ucfp, cconfs)) { case 0: break; case 1: continue; case -1: goto error; } while(cmanfp) { sbuf_free_content(cb); switch(sbufl_fill(cb, asfd, cmanfp, cconfs)) { case 0: break; case 1: fzp_close(&cmanfp); if(process_new(sdirs, cconfs, p1b, ucfp)) goto error; continue; case -1: goto error; } switch(maybe_process_file(asfd, sdirs, cb, p1b, ucfp, cconfs)) { case 0: continue; case 1: break; case -1: goto error; } break; } } error: ret=-1; end: if(fzp_close(&chfp)) { logp("error closing %s in %s\n", sdirs->changed, __func__); ret=-1; } if(fzp_close(&ucfp)) { logp("error closing %s in %s\n", sdirs->unchanged, __func__); ret=-1; } free_w(&deltmppath); sbuf_free(&cb); sbuf_free(&p1b); sbuf_free(&rb); manio_free(&p1manio); fzp_close(&cmanfp); dpth_free(&dpth); if(!ret) unlink(sdirs->phase1data); logp("End phase2 (receive file data)\n"); return ret; }
int backup_phase2_server(struct asfd *asfd, struct sdirs *sdirs, struct conf *cconf, gzFile *cmanfp, struct dpthl *dpthl, int resume) { int ars=0; int ret=0; gzFile p1zp=NULL; char *deltmppath=NULL; char *last_requested=NULL; // Where to write phase2data. // Data is not getting written to a compressed file. // This is important for recovery if the power goes. FILE *p2fp=NULL; // unchanged data FILE *ucfp=NULL; struct sbuf *cb=NULL; // file list in current manifest struct sbuf *p1b=NULL; // file list from client struct sbuf *rb=NULL; // receiving file from client if(!(cb=sbuf_alloc(cconf)) || !(p1b=sbuf_alloc(cconf)) || !(rb=sbuf_alloc(cconf))) goto error; if(!(p1zp=gzopen_file(sdirs->phase1data, "rb"))) goto error; // Open in read+write mode, so that they can be read through if // we need to resume. // First, open them in a+ mode, so that they will be created if they // do not exist. if(!(ucfp=open_file(sdirs->unchangeddata, "a+b")) || !(p2fp=open_file(sdirs->phase2data, "a+b"))) goto error; close_fp(&ucfp); close_fp(&p2fp); if(!(ucfp=open_file(sdirs->unchangeddata, "r+b")) || !(p2fp=open_file(sdirs->phase2data, "r+b"))) goto error; if(resume && do_resume(p1zp, p2fp, ucfp, dpthl, cconf)) goto error; logp("Begin phase2 (receive file data)\n"); while(1) { int sts=0; //printf("in loop, %s %s %c\n", // *cmanfp?"got cmanfp":"no cmanfp", // rb->path.buf?:"no rb->path", // rb->path.buf?'X':rb->path.cmd); if(write_status(STATUS_BACKUP, rb->path.buf?rb->path.buf:p1b->path.buf, cconf)) goto error; if((last_requested || !p1zp || asfd->writebuflen) && (ars=do_stuff_to_receive(asfd, sdirs, cconf, rb, p2fp, dpthl, &last_requested))) { if(ars<0) goto error; // 1 means ok. break; } if((sts=do_stuff_to_send(asfd, p1b, &last_requested))<0) goto error; if(!sts && p1zp) { sbuf_free_content(p1b); if((ars=sbufl_fill_phase1(p1b, NULL, p1zp, cconf->cntr))) { if(ars<0) goto error; // ars==1 means it ended ok. gzclose_fp(&p1zp); //logp("ended OK - write phase2end"); if(asfd->write_str(asfd, CMD_GEN, "backupphase2end")) goto error; } //logp("check: %s\n", p1b.path); if(!*cmanfp) { // No old manifest, need to ask for a new file. //logp("no cmanfp\n"); if(process_new(sdirs, cconf, p1b, ucfp, dpthl)) goto error; } else { // Have an old manifest, look for it there. // Might already have it, or be ahead in the old // manifest. if(cb->path.buf) { if((ars=maybe_process_file(asfd, sdirs, cconf, cb, p1b, ucfp, dpthl))) { if(ars<0) goto error; // Do not free it - need to send stuff. continue; } //free_sbufl(&p1b); } while(*cmanfp) { sbuf_free_content(cb); if((ars=sbufl_fill(cb, asfd, NULL, *cmanfp, cconf->cntr))) { // ars==1 means it ended ok. if(ars<0) goto error; gzclose_fp(cmanfp); //logp("ran out of current manifest\n"); if(process_new(sdirs, cconf, p1b, ucfp, dpthl)) goto error; break; } //logp("against: %s\n", cb.path); if((ars=maybe_process_file(asfd, sdirs, cconf, cb, p1b, ucfp, dpthl))) { if(ars<0) goto error; // Do not free it - need to send stuff. break; } } } } } goto end; error: ret=-1; end: if(close_fp(&p2fp)) { logp("error closing %s in backup_phase2_server\n", sdirs->phase2data); ret=-1; } if(close_fp(&ucfp)) { logp("error closing %s in backup_phase2_server\n", sdirs->unchangeddata); ret=-1; } free(deltmppath); sbuf_free(cb); sbuf_free(p1b); sbuf_free(rb); gzclose_fp(&p1zp); if(!ret) unlink(sdirs->phase1data); logp("End phase2 (receive file data)\n"); return ret; }