LCOV - code coverage report
Current view: top level - src/server/protocol2 - backup_phase2.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 337 402 83.8 %
Date: 2017-08-31 Functions: 24 27 88.9 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../asfd.h"
       4             : #include "../../async.h"
       5             : #include "../../attribs.h"
       6             : #include "../../base64.h"
       7             : #include "../../cmd.h"
       8             : #include "../../cntr.h"
       9             : #include "../../cstat.h"
      10             : #include "../../handy.h"
      11             : #include "../../hexmap.h"
      12             : #include "../../iobuf.h"
      13             : #include "../../log.h"
      14             : #include "../../server/manio.h"
      15             : #include "../../protocol2/blist.h"
      16             : #include "../../protocol2/rabin/rabin.h"
      17             : #include "../../slist.h"
      18             : #include "../child.h"
      19             : #include "../manios.h"
      20             : #include "../resume.h"
      21             : #include "champ_chooser/champ_client.h"
      22             : #include "champ_chooser/champ_server.h"
      23             : #include "champ_chooser/hash.h"
      24             : #include "dpth.h"
      25             : #include "backup_phase2.h"
      26             : 
      27             : #define END_SIGS                0x01
      28             : #define END_BACKUP              0x02
      29             : #define END_REQUESTS            0x04
      30             : #define END_BLK_REQUESTS        0x08
      31             : 
      32             : #define BLKS_MAX_UNREQUESTED    BLKS_MAX_IN_MEM/4
      33             : // This needs to be greater than BLKS_MAX_UNREQUESTED
      34             : #define SLIST_MAX_IN_MEM        BLKS_MAX_IN_MEM
      35             : 
      36             : static int breaking=0;
      37             : static int breakcount=0;
      38             : 
      39             : static int data_needed(struct sbuf *sb)
      40             : {
      41       33720 :         if(sb->path.cmd==CMD_FILE)
      42             :                 return 1;
      43       16674 :         if(sb->path.cmd==CMD_METADATA)
      44             :                 return 1;
      45             :         return 0;
      46             : }
      47             : 
      48           4 : static int manio_component_to_chfd(struct asfd *chfd, char *path)
      49             : {
      50             :         struct iobuf wbuf;
      51           4 :         iobuf_from_str(&wbuf, CMD_MANIFEST, path);
      52           4 :         return chfd->write(chfd, &wbuf);
      53             : }
      54             : 
      55           0 : static int unchanged(struct sbuf *csb, struct sbuf *sb,
      56             :         struct manios *manios, struct asfd *chfd)
      57             : {
      58           0 :         int ret=-1;
      59           0 :         char *fpath=NULL;
      60           0 :         if(!(fpath=strdup_w(manios->changed->offset->fpath, __func__)))
      61             :                 goto end;
      62           0 :         if(manio_copy_entry(csb, sb,
      63             :                 manios->current, manios->unchanged)<0)
      64             :                         goto end;
      65           0 :         if(strcmp(fpath, manios->changed->offset->fpath))
      66             :         {
      67             :                 // If the copy crossed a manio boundary, we should tell the
      68             :                 // champ server to load the previous one as a candidate.
      69           0 :                 if(manio_component_to_chfd(chfd, fpath))
      70             :                         goto end;
      71             :         }
      72             :         ret=0;
      73             : end:
      74           0 :         free_w(&fpath);
      75           0 :         return ret;
      76             : }
      77             : 
      78             : // Return -1 for error, 0 for entry not changed, 1 for entry changed (or new).
      79           0 : static int found_in_current_manifest(struct sbuf *csb, struct sbuf *sb,
      80             :         struct manios *manios, struct asfd *chfd,
      81             :         struct cntr *cntr)
      82             : {
      83             :         // Located the entry in the current manifest.
      84             :         // If the file type changed, I think it is time to back it up again
      85             :         // (for example, EFS changing to normal file, or back again).
      86           0 :         if(csb->path.cmd!=sb->path.cmd)
      87             :         {
      88           0 :                 if(manio_forward_through_sigs(csb, manios->current)<0)
      89             :                         return -1;
      90           0 :                 return 1;
      91             :         }
      92             : 
      93             :         // mtime is the actual file data.
      94             :         // ctime is the attributes or meta data.
      95           0 :         if(csb->statp.st_mtime==sb->statp.st_mtime
      96           0 :           && csb->statp.st_ctime==sb->statp.st_ctime)
      97             :         {
      98             :                 // Got an unchanged file.
      99           0 :                 cntr_add_same(cntr, sb->path.cmd);
     100           0 :                 return unchanged(csb, sb, manios, chfd);
     101             :         }
     102             : 
     103           0 :         if(csb->statp.st_mtime==sb->statp.st_mtime
     104           0 :           && csb->statp.st_ctime!=sb->statp.st_ctime)
     105             :         {
     106             :                 // FIX THIS:
     107             :                 // File data stayed the same, but attributes or meta data
     108             :                 // changed. We already have the attributes, but may need to
     109             :                 // get extra meta data.
     110           0 :                 cntr_add_same(cntr, sb->path.cmd);
     111           0 :                 return unchanged(csb, sb, manios, chfd);
     112             :         }
     113             : 
     114             :         // File data changed.
     115           0 :         cntr_add_changed(cntr, sb->path.cmd);
     116           0 :         if(manio_forward_through_sigs(csb, manios->current)<0)
     117             :                 return -1;
     118           0 :         return 1;
     119             : }
     120             : 
     121             : // Return -1 for error, 0 for entry not changed, 1 for entry changed (or new).
     122       33720 : static int entry_changed(struct sbuf *sb,
     123             :         struct manios *manios, struct asfd *chfd, struct sbuf **csb,
     124             :         struct cntr *cntr)
     125             : {
     126             :         static int finished=0;
     127             :         int pcmp;
     128             : 
     129       33720 :         if(finished)
     130             :         {
     131       33710 :                 cntr_add_new(cntr, sb->path.cmd);
     132       33710 :                 return 1;
     133             :         }
     134             : 
     135          10 :         if(*csb && (*csb)->path.buf)
     136             :         {
     137             :                 // Already have an entry.
     138             :         }
     139             :         else
     140             :         {
     141             :                 // Need to read another.
     142          10 :                 switch(manio_read(manios->current, *csb))
     143             :                 {
     144             :                         case 1: // Reached the end.
     145          10 :                                 sbuf_free(csb);
     146          10 :                                 finished=1;
     147          10 :                                 cntr_add_new(cntr, sb->path.cmd);
     148          10 :                                 return 1;
     149             :                         case -1: return -1;
     150             :                 }
     151           0 :                 if(!(*csb)->path.buf)
     152             :                 {
     153           0 :                         logp("Should have a path at this point, but do not, in %s\n", __func__);
     154           0 :                         return -1;
     155             :                 }
     156             :                 // Got an entry.
     157             :         }
     158             : 
     159             :         while(1)
     160             :         {
     161           0 :                 if(!(pcmp=sbuf_pathcmp(*csb, sb)))
     162           0 :                         return found_in_current_manifest(*csb, sb,
     163             :                                         manios, chfd, cntr);
     164           0 :                 else if(pcmp>0)
     165             :                 {
     166           0 :                         cntr_add_new(cntr, sb->path.cmd);
     167           0 :                         return 1;
     168             :                 }
     169             : //              cntr_add_deleted(cntr, (*csb)->path.cmd);
     170             :                 // Behind - need to read more data from the old manifest.
     171           0 :                 switch(manio_read(manios->current, *csb))
     172             :                 {
     173             :                         case 1: // Reached the end.
     174           0 :                                 sbuf_free(csb);
     175           0 :                                 cntr_add_new(cntr, sb->path.cmd);
     176           0 :                                 return 1;
     177             :                         case -1: return -1;
     178             :                 }
     179             :                 // Got something, go back around the loop.
     180             :         }
     181             : 
     182             :         return 0;
     183             : }
     184             : 
     185        8523 : static int add_data_to_store(struct cntr *cntr,
     186             :         struct slist *slist, struct iobuf *rbuf, struct dpth *dpth)
     187             : {
     188             :         static struct blk *blk=NULL;
     189             : 
     190             :         // Find the first one in the list that was requested.
     191             :         // FIX THIS: Going up the list here, and then later
     192             :         // when writing to the manifest is not efficient.
     193       17046 :         for(blk=slist->blist->head;
     194        8522 :                 blk && (!blk->requested || blk->got==BLK_GOT); blk=blk->next)
     195             :         {
     196             :         //      logp("try: %d %d\n", blk->index, blk->got);
     197             :         }
     198        8523 :         if(!blk)
     199             :         {
     200           1 :                 logp("Received data but could not find next requested block.\n");
     201           1 :                 if(!slist->blist->head)
     202           1 :                         logp("and slist->blist->head is null\n");
     203             :                 else
     204           0 :                         logp("head index: %" PRIu64 "\n", slist->blist->head->index);
     205             :                 return -1;
     206             :         }
     207             : 
     208             : // FIX THIS
     209             : #ifndef UTEST
     210             :         if(blk_verify(blk->fingerprint, blk->md5sum, rbuf->buf, rbuf->len)<=0)
     211             :         {
     212             :                 logp("ERROR: Block %" PRIu64 " from client did not verify.\n",
     213             :                         blk->index);
     214             :                 return -1;
     215             :         }
     216             : #endif
     217             : 
     218             :         // Add it to the data store straight away.
     219        8522 :         if(dpth_protocol2_fwrite(dpth, rbuf, blk)) return -1;
     220             : 
     221        8522 :         cntr_add(cntr, CMD_DATA, 0);
     222             : 
     223        8522 :         blk->got=BLK_GOT;
     224        8522 :         blk=blk->next;
     225             : 
     226             :         return 0;
     227             : }
     228             : 
     229       17034 : static int set_up_for_sig_info(struct slist *slist, struct iobuf *attr,
     230             :         uint64_t index)
     231             : {
     232             :         struct sbuf *sb;
     233             : 
     234       50701 :         for(sb=slist->add_sigs_here; sb; sb=sb->next)
     235             :         {
     236       50701 :                 if(!sb->protocol2->index)
     237       16642 :                         continue;
     238       34059 :                 if(index==sb->protocol2->index)
     239             :                         break;
     240             :         }
     241       17034 :         if(!sb)
     242             :         {
     243           0 :                 logp("Could not find %" PRIu64 " in request list\n", index);
     244             :                 return -1;
     245             :         }
     246             :         // Replace the attribs with the more recent values.
     247       17034 :         iobuf_free_content(&sb->attr);
     248       17034 :         iobuf_move(&sb->attr, attr);
     249             : 
     250             :         // Mark the end of the previous file.
     251       17034 :         slist->add_sigs_here->protocol2->bend=slist->blist->tail;
     252             : 
     253       17034 :         slist->add_sigs_here=sb;
     254             : 
     255             :         // Incoming sigs now need to get added to 'add_sigs_here'
     256             :         return 0;
     257             : }
     258             : 
     259             : /*
     260             : static void dump_blks(const char *msg, struct blk *b)
     261             : {
     262             :         struct blk *xx;
     263             :         for(xx=b; xx; xx=xx->next)
     264             :                 printf("%s: %d %d %p\n", msg, xx->index, xx->got, xx);
     265             : }
     266             : */
     267             : 
     268       25058 : static int add_to_sig_list(struct slist *slist, struct iobuf *rbuf)
     269             : {
     270             :         // Goes on slist->add_sigs_here
     271             :         struct blk *blk;
     272             :         struct protocol2 *protocol2;
     273             : 
     274       25058 :         if(!(blk=blk_alloc())) return -1;
     275       25058 :         blist_add_blk(slist->blist, blk);
     276             : 
     277       25058 :         protocol2=slist->add_sigs_here->protocol2;
     278       25058 :         if(!protocol2->bstart) protocol2->bstart=blk;
     279       25058 :         if(!protocol2->bsighead) protocol2->bsighead=blk;
     280             : 
     281       25058 :         if(blk_set_from_iobuf_sig(blk, rbuf)) return -1;
     282             : 
     283             :         // Need to send sigs to champ chooser, therefore need to point
     284             :         // to the oldest unsent one if nothing is pointed to yet.
     285       25058 :         if(!slist->blist->blk_for_champ_chooser)
     286       16490 :                 slist->blist->blk_for_champ_chooser=blk;
     287             : 
     288             :         return 0;
     289             : }
     290             : 
     291       50647 : static int deal_with_read(struct iobuf *rbuf, struct slist *slist,
     292             :         struct cntr *cntr, uint8_t *end_flags, struct dpth *dpth)
     293             : {
     294       50647 :         int ret=0;
     295             :         static struct iobuf attr;
     296             :         static uint64_t index;
     297             : 
     298       50647 :         switch(rbuf->cmd)
     299             :         {
     300             :                 /* Incoming block data. */
     301             :                 case CMD_DATA:
     302        8523 :                         if(add_data_to_store(cntr, slist, rbuf, dpth))
     303             :                                 goto error;
     304             :                         goto end;
     305             : 
     306             :                 /* Incoming block signatures. */
     307             :                 case CMD_ATTRIBS_SIGS:
     308             : 
     309       17034 :                         iobuf_init(&attr);
     310       17034 :                         iobuf_move(&attr, rbuf);
     311       17034 :                         index=decode_file_no(&attr);
     312             : 
     313             :                         // Need to go through slist to find the matching
     314             :                         // entry.
     315       17034 :                         if(set_up_for_sig_info(slist, &attr, index))
     316             :                                 goto error;
     317             :                         return 0;
     318             :                 case CMD_SIG:
     319       25058 :                         if(add_to_sig_list(slist, rbuf))
     320             :                                 goto error;
     321             :                         goto end;
     322             : 
     323             :                 /* Incoming control/message stuff. */
     324             :                 case CMD_MESSAGE:
     325             :                 case CMD_WARNING:
     326             :                 {
     327           6 :                         struct cntr *cntr=NULL;
     328           6 :                         log_recvd(rbuf, cntr, 0);
     329           6 :                         goto end;
     330             :                 }
     331             :                 case CMD_GEN:
     332          25 :                         if(!strcmp(rbuf->buf, "sigs_end"))
     333             :                         {
     334          13 :                                 (*end_flags)|=END_SIGS;
     335          13 :                                 goto end;
     336             :                         }
     337          12 :                         else if(!strcmp(rbuf->buf, "backup_end"))
     338             :                         {
     339          12 :                                 (*end_flags)|=END_BACKUP;
     340          12 :                                 goto end;
     341             :                         }
     342             :                         break;
     343             :                 case CMD_INTERRUPT:
     344             :                 {
     345             :                         uint64_t file_no;
     346           1 :                         file_no=base64_to_uint64(rbuf->buf);
     347           1 :                         if(slist_del_sbuf_by_index(slist, file_no))
     348             :                                 goto error;
     349             :                         goto end;
     350             :                 }
     351             :                 default:
     352             :                         break;
     353             :         }
     354             : 
     355           0 :         iobuf_log_unexpected(rbuf, __func__);
     356             : error:
     357             :         ret=-1;
     358             : end:
     359       33613 :         iobuf_free_content(rbuf);
     360       33613 :         return ret;
     361             : }
     362             : 
     363      216982 : static int get_wbuf_from_sigs(struct iobuf *wbuf, struct slist *slist,
     364             :         uint8_t *end_flags)
     365             : {
     366             :         static char req[32]="";
     367      216982 :         struct sbuf *sb=slist->blks_to_request;
     368             : 
     369       13327 :         while(sb && !(sb->flags & SBUF_NEED_DATA)) sb=sb->next;
     370             : 
     371      216982 :         if(!sb)
     372             :         {
     373          16 :                 slist->blks_to_request=NULL;
     374          16 :                 if((*end_flags)&END_SIGS && !((*end_flags)&END_BLK_REQUESTS))
     375             :                 {
     376           3 :                         iobuf_from_str(wbuf,
     377             :                                 CMD_GEN, (char *)"blk_requests_end");
     378           3 :                         (*end_flags)|=END_BLK_REQUESTS;
     379             :                 }
     380             :                 return 0;
     381             :         }
     382      216966 :         if(!sb->protocol2->bsighead)
     383             :         {
     384             :                 // Trying to move onto the next file.
     385             :                 // ??? Does this really work?
     386      129027 :                 if(sb->protocol2->bend)
     387             :                 {
     388           0 :                         slist->blks_to_request=sb->next;
     389             :                         printf("move to next\n");
     390             :                 }
     391      129027 :                 if((*end_flags)&END_SIGS && !((*end_flags)&END_BLK_REQUESTS))
     392             :                 {
     393          10 :                         iobuf_from_str(wbuf,
     394             :                                 CMD_GEN, (char *)"blk_requests_end");
     395          10 :                         (*end_flags)|=END_BLK_REQUESTS;
     396             :                 }
     397             :                 return 0;
     398             :         }
     399             : 
     400       87939 :         if(sb->protocol2->bsighead->got==BLK_INCOMING)
     401             :                 return 0;
     402             : 
     403       12538 :         if(sb->protocol2->bsighead->got==BLK_NOT_GOT)
     404             :         {
     405        8522 :                 base64_from_uint64(sb->protocol2->bsighead->index, req);
     406        8522 :                 iobuf_from_str(wbuf, CMD_DATA_REQ, req);
     407        8522 :                 sb->protocol2->bsighead->requested=1;
     408             :         }
     409             : 
     410             :         // Move on.
     411       12538 :         if(sb->protocol2->bsighead==sb->protocol2->bend)
     412             :         {
     413        8517 :                 slist->blks_to_request=sb->next;
     414        8517 :                 sb->protocol2->bsighead=sb->protocol2->bstart;
     415             :         }
     416             :         else
     417             :         {
     418        4021 :                 sb->protocol2->bsighead=sb->protocol2->bsighead->next;
     419             :         }
     420             :         return 0;
     421             : }
     422             : 
     423      208447 : static void get_wbuf_from_files(struct iobuf *wbuf, struct slist *slist,
     424             :         struct manios *manios, uint8_t *end_flags, uint64_t *file_no)
     425             : {
     426      208447 :         struct sbuf *sb=slist->last_requested;
     427      208447 :         if(!sb)
     428             :         {
     429      157689 :                 if(!manios->phase1 && !((*end_flags)&END_REQUESTS))
     430             :                 {
     431          18 :                         iobuf_from_str(wbuf, CMD_GEN, (char *)"requests_end");
     432          18 :                         (*end_flags)|=END_REQUESTS;
     433             :                 }
     434             :                 return;
     435             :         }
     436             : 
     437       50758 :         if(sb->flags & SBUF_SENT_PATH || !(sb->flags & SBUF_NEED_DATA))
     438             :         {
     439       33712 :                 slist->last_requested=sb->next;
     440             :                 return;
     441             :         }
     442             : 
     443             :         // Only need to request the path at this stage.
     444       17046 :         iobuf_copy(wbuf, &sb->path);
     445       17046 :         sb->flags |= SBUF_SENT_PATH;
     446       17046 :         sb->protocol2->index=(*file_no)++;
     447             : }
     448             : 
     449           2 : static void get_wbuf_from_index(struct iobuf *wbuf, uint64_t index)
     450             : {
     451             :         static char *p;
     452             :         static char tmp[32];
     453           2 :         p=tmp;
     454           2 :         p+=to_base64(index, tmp);
     455           2 :         *p='\0';
     456           2 :         iobuf_from_str(wbuf, CMD_WRAP_UP, tmp);
     457           2 : }
     458             : 
     459       33704 : static int write_endfile(struct sbuf *sb, struct manios *manios)
     460             : {
     461             :         struct iobuf endfile;
     462             : 
     463       33704 :         if(sb->flags & SBUF_END_WRITTEN_TO_MANIFEST)
     464             :                 return 0;
     465       33704 :         if(!iobuf_is_filedata(&sb->path))
     466             :                 return 0;
     467             : 
     468       17036 :         sb->flags |= SBUF_END_WRITTEN_TO_MANIFEST;
     469             :         // FIX THIS: Should give a proper length and md5sum.
     470       17036 :         iobuf_from_str(&endfile, CMD_END_FILE, (char *)"0:0");
     471       17036 :         return iobuf_send_msg_fzp(&endfile, manios->changed->fzp);
     472             : }
     473             : 
     474      233992 : static void blist_adjust_head(struct blist *blist, struct sbuf *sb)
     475             : {
     476             :         struct blk *b;
     477      259050 :         while(blist->head!=sb->protocol2->bstart)
     478             :         {
     479       25058 :                 b=blist->head->next;
     480       25058 :                 if(blist->head==blist->blk_from_champ_chooser)
     481        8508 :                         blist->blk_from_champ_chooser=b;
     482       25058 :                 blk_free(&blist->head);
     483       25058 :                 blist->head=b;
     484             :         }
     485      233992 :         if(!blist->head)
     486       51771 :                 blist->tail=NULL;
     487      233992 : }
     488             : 
     489      233992 : static int sbuf_needs_data(struct sbuf *sb, struct asfd *asfd,
     490             :         struct asfd *chfd, struct manios *manios,
     491             :         struct slist *slist, int end_flags)
     492             : {
     493      233992 :         int ret=-1;
     494             :         struct blk *blk;
     495             :         static struct iobuf wbuf;
     496      233992 :         struct blist *blist=slist->blist;
     497             :         static int unrequested=0;
     498             : 
     499      233992 :         if(!(sb->flags & SBUF_HEADER_WRITTEN_TO_MANIFEST))
     500             :         {
     501       17036 :                 if(manio_write_sbuf(manios->changed, sb)) goto end;
     502       17036 :                 sb->flags |= SBUF_HEADER_WRITTEN_TO_MANIFEST;
     503             :         }
     504             : 
     505      242025 :         while((blk=sb->protocol2->bstart)
     506      190254 :                 && blk->got==BLK_GOT
     507       59413 :                 && (blk->next || end_flags&END_BACKUP))
     508             :         {
     509       25058 :                 if(blk->got_save_path
     510       25058 :                   && !blk_is_zero_length(blk))
     511             :                 {
     512       25058 :                         if(breaking && breakcount--==0)
     513             :                         {
     514           0 :                                 breakpoint(breaking, __func__);
     515           0 :                                 goto end;
     516             :                         }
     517       25058 :                         if(manio_write_sig_and_path(manios->changed, blk))
     518             :                                 goto end;
     519       25058 :                         if(manios->changed->sig_count==0)
     520             :                         {
     521             :                                 // Have finished a manifest file. Want to start
     522             :                                 // using it as a dedup candidate now.
     523           4 :                                 if(manio_component_to_chfd(chfd,
     524           4 :                                         manios->changed->offset->ppath))
     525             :                                                 goto end;
     526             : 
     527             :                                 // The champ chooser has the candidate. Now,
     528             :                                 // empty our local hash table.
     529           4 :                                 hash_delete_all();
     530             :                                 // Add the most recent block, so identical
     531             :                                 // adjacent blocks are deduplicated well.
     532           4 :                                 if(hash_load_blk(blk))
     533             :                                         goto end;
     534             :                         }
     535             :                 }
     536             : 
     537       25058 :                 if(!blk->requested)
     538       16536 :                         unrequested++;
     539             : 
     540       25058 :                 if(unrequested>BLKS_MAX_UNREQUESTED)
     541             :                 {
     542           2 :                         unrequested=0;
     543             :                         // Let the client know that it can free memory if there
     544             :                         // was a long consecutive number of unrequested blocks.
     545           2 :                         get_wbuf_from_index(&wbuf, blk->index);
     546           2 :                         if(asfd->write(asfd, &wbuf))
     547             :                                 goto end;
     548             :                 }
     549             : 
     550       25058 :                 if(blk==sb->protocol2->bend)
     551             :                 {
     552       17025 :                         blist_adjust_head(blist, sb);
     553       17025 :                         if(write_endfile(sb, manios)) return -1;
     554       17025 :                         slist_advance(slist);
     555       17025 :                         return 1;
     556             :                 }
     557             : 
     558        8033 :                 if(sb->protocol2->bsighead==sb->protocol2->bstart)
     559        8020 :                         sb->protocol2->bsighead=blk->next;
     560        8033 :                 sb->protocol2->bstart=blk->next;
     561        8033 :                 if(blk==blist->blk_from_champ_chooser)
     562        4021 :                         blist->blk_from_champ_chooser=blk->next;
     563             :         }
     564      216967 :         if(!blk && sb && !sb->protocol2->bend && (end_flags&END_BACKUP))
     565             :         {
     566             :                 // Write endfile for the very last file.
     567          11 :                 if(write_endfile(sb, manios)) return -1;
     568             :         }
     569             :         ret=0;
     570             : end:
     571      216967 :         blist_adjust_head(blist, sb);
     572      216967 :         return ret;
     573             : }
     574             : 
     575      216984 : static int write_to_changed_file(struct asfd *asfd,
     576             :         struct asfd *chfd, struct manios *manios,
     577             :         struct slist *slist, int end_flags)
     578             : {
     579             :         struct sbuf *sb;
     580      216984 :         if(!slist) return 0;
     581             : 
     582      250677 :         while((sb=slist->head))
     583             :         {
     584      250660 :                 if(sb->flags & SBUF_NEED_DATA)
     585             :                 {
     586      233992 :                         switch(sbuf_needs_data(sb, asfd, chfd, manios, slist,
     587             :                                 end_flags))
     588             :                         {
     589             :                                 case 0: return 0;
     590       17025 :                                 case 1: continue;
     591           0 :                                 default: return -1;
     592             :                         }
     593             : 
     594             :                 }
     595             :                 else
     596             :                 {
     597             :                         // No change, can go straight in.
     598       16668 :                         if(manio_write_sbuf(manios->changed, sb)) return -1;
     599       16668 :                         if(write_endfile(sb, manios)) return -1;
     600             : 
     601             :                         // Move along.
     602       16668 :                         slist_advance(slist);
     603             :                 }
     604             :         }
     605             :         return 0;
     606             : }
     607             : 
     608      216982 : static int maybe_add_from_scan(struct manios *manios,
     609             :         struct slist *slist, struct asfd *chfd, struct sbuf **csb,
     610             :         struct cntr *cntr)
     611             : {
     612      216982 :         int ret=-1;
     613      216982 :         struct sbuf *snew=NULL;
     614             : 
     615             :         while(1)
     616             :         {
     617      250702 :                 sbuf_free(&snew);
     618      250702 :                 if(!manios->phase1) return 0;
     619             :                 // Limit the amount loaded into memory at any one time.
     620       33738 :                 if(slist->count>SLIST_MAX_IN_MEM)
     621             :                         return 0;
     622       67458 :                 if(!(snew=sbuf_alloc(PROTO_2))) goto end;
     623             : 
     624       33738 :                 switch(manio_read(manios->phase1, snew))
     625             :                 {
     626             :                         case 0: break;
     627          18 :                         case 1: manio_close(&manios->phase1);
     628          18 :                                 ret=0; // Finished.
     629             :                         default: goto end;
     630             :                 }
     631             : 
     632       33720 :                 switch(entry_changed(snew, manios, chfd, csb, cntr))
     633             :                 {
     634           0 :                         case 0: continue; // No change.
     635             :                         case 1: break;
     636             :                         default: goto end; // Error.
     637             :                 }
     638             : 
     639      101160 :                 if(data_needed(snew)) snew->flags|=SBUF_NEED_DATA;
     640             : 
     641       33720 :                 slist_add_sbuf(slist, snew);
     642       33720 :                 snew=NULL;
     643             :         }
     644             :         return 0;
     645             : end:
     646          18 :         sbuf_free(&snew);
     647          18 :         return ret;
     648             : }
     649             : 
     650      216981 : static int append_for_champ_chooser(struct asfd *chfd,
     651             :         struct blist *blist, int end_flags)
     652             : {
     653             :         static int finished_sending=0;
     654             :         static struct iobuf wbuf;
     655             :         static struct blk *blk=NULL;
     656             : 
     657      242039 :         while(blist->blk_for_champ_chooser)
     658             :         {
     659      112824 :                 blk=blist->blk_for_champ_chooser;
     660             :                 // If we send too many blocks to the champ chooser at once,
     661             :                 // it can go faster than we can send paths to completed
     662             :                 // manifests to it. This means that deduplication efficiency
     663             :                 // is reduced (although speed may be faster).
     664             :                 // So limit the sending.
     665      225648 :                 if(blk->index
     666      112824 :                   - blist->head->index > MANIFEST_SIG_MAX)
     667             :                         return 0;
     668             : 
     669       25058 :                 blk_to_iobuf_sig(blk, &wbuf);
     670             : 
     671       25058 :                 switch(chfd->append_all_to_write_buffer(chfd, &wbuf))
     672             :                 {
     673             :                         case APPEND_OK: break;
     674             :                         case APPEND_BLOCKED:
     675             :                                 return 0; // Try again later.
     676             :                         default: return -1;
     677             :                 }
     678       25058 :                 blist->blk_for_champ_chooser=blk->next;
     679             :         }
     680      129215 :         if(end_flags&END_SIGS
     681       49976 :           && !finished_sending && !blist->blk_for_champ_chooser)
     682             :         {
     683          13 :                 iobuf_from_str(&wbuf, CMD_GEN, (char *)"sigs_end");
     684          13 :                 switch(chfd->append_all_to_write_buffer(chfd, &wbuf))
     685             :                 {
     686             :                         case APPEND_OK: break;
     687             :                         case APPEND_BLOCKED:
     688             :                                 return 0; // Try again later.
     689             :                         default: return -1;
     690             :                 }
     691          12 :                 finished_sending++;
     692             :         }
     693             :         return 0;
     694             : }
     695             : 
     696       25063 : static int mark_not_got(struct blk *blk, struct dpth *dpth)
     697             : {
     698             :         const char *path;
     699             : 
     700       25063 :         if(blk->got!=BLK_INCOMING) return 0;
     701        8522 :         blk->got=BLK_NOT_GOT;
     702             : 
     703             :         // Need to get the data for this blk from the client.
     704             :         // Set up the details of where it will be saved.
     705        8522 :         if(!(path=dpth_protocol2_mk(dpth))) return -1;
     706             : 
     707             :         // FIX THIS: make dpth give us the path in a uint8 array.
     708        8522 :         blk->savepath=savepathstr_with_sig_to_uint64(path);
     709        8522 :         blk->got_save_path=1;
     710             :         // Load it into our local hash table.
     711        8522 :         if(hash_load_blk(blk))
     712             :                 return -1;
     713        8522 :         if(dpth_protocol2_incr_sig(dpth))
     714             :                 return -1;
     715        8522 :         return 0;
     716             : }
     717             : 
     718       25058 : static struct hash_strong *in_local_hash(struct blk *blk)
     719             : {
     720             :         static struct hash_weak *hash_weak;
     721             : 
     722       25058 :         if(!(hash_weak=hash_weak_find(blk->fingerprint)))
     723             :                 return NULL;
     724        4014 :         return hash_strong_find(hash_weak, blk->md5sum);
     725             : }
     726             : 
     727       37587 : static int simple_deduplicate_blk(struct blk *blk)
     728             : {
     729             :         static struct hash_strong *hash_strong;
     730       37587 :         if(blk->got!=BLK_INCOMING)
     731             :                 return 0;
     732       25058 :         if((hash_strong=in_local_hash(blk)))
     733             :         {
     734        4014 :                 blk->savepath=hash_strong->savepath;
     735        4014 :                 blk->got_save_path=1;
     736        4014 :                 blk->got=BLK_GOT;
     737        4014 :                 return 1;
     738             :         }
     739             :         return 0;
     740             : }
     741             : 
     742       25058 : static int mark_up_to_index(struct blist *blist,
     743             :         uint64_t index, struct dpth *dpth)
     744             : {
     745             :         struct blk *blk;
     746             : 
     747             :         // Mark everything that was not got, up to the given index.
     748       62645 :         for(blk=blist->blk_from_champ_chooser;
     749       50116 :           blk && blk->index!=index; blk=blk->next)
     750             :         {
     751       12529 :                 if(simple_deduplicate_blk(blk))
     752           0 :                         continue;
     753       12529 :                 if(mark_not_got(blk, dpth))
     754             :                         return -1;
     755             :         }
     756       25058 :         if(!blk)
     757             :         {
     758           0 :                 logp("Could not find index from champ chooser: %" PRIu64 "\n",
     759             :                         index);
     760             :                 return -1;
     761             :         }
     762       25058 :         simple_deduplicate_blk(blk);
     763             : 
     764             : //logp("Found index from champ chooser: %lu\n", index);
     765             : //printf("index from cc: %d\n", index);
     766       25058 :         blist->blk_from_champ_chooser=blk;
     767             :         return 0;
     768             : }
     769             : 
     770       12524 : static int deal_with_sig_from_chfd(struct iobuf *rbuf, struct blist *blist,
     771             :         struct dpth *dpth)
     772             : {
     773             :         static struct blk b;
     774       12524 :         if(blk_set_from_iobuf_index_and_savepath(&b, rbuf))
     775             :                 return -1;
     776             : 
     777       12524 :         if(mark_up_to_index(blist, b.index, dpth))
     778             :                 return -1;
     779       12524 :         blist->blk_from_champ_chooser->savepath=b.savepath;
     780       12524 :         blist->blk_from_champ_chooser->got=BLK_GOT;
     781       12524 :         blist->blk_from_champ_chooser->got_save_path=1;
     782       12524 :         return 0;
     783             : }
     784             : 
     785       12534 : static int deal_with_wrap_up_from_chfd(struct iobuf *rbuf, struct blist *blist,
     786             :         struct dpth *dpth)
     787             : {
     788             :         static struct blk b;
     789       12534 :         if(blk_set_from_iobuf_wrap_up(&b, rbuf))
     790             :                 return -1;
     791             : 
     792       12534 :         if(mark_up_to_index(blist, b.index, dpth)) return -1;
     793       12534 :         if(mark_not_got(blist->blk_from_champ_chooser, dpth)) return -1;
     794       12534 :         return 0;
     795             : }
     796             : 
     797       25059 : static int deal_with_read_from_chfd(struct asfd *chfd,
     798             :         struct blist *blist, struct dpth *dpth, struct cntr *cntr)
     799             : {
     800       25059 :         int ret=-1;
     801             : 
     802             :         // Deal with champ chooser read here.
     803             :         //printf("read from cc: %s\n", chfd->rbuf->buf);
     804       25059 :         switch(chfd->rbuf->cmd)
     805             :         {
     806             :                 case CMD_SIG:
     807             :                         // Get these for blks that the champ chooser has found.
     808       12524 :                         if(deal_with_sig_from_chfd(chfd->rbuf, blist, dpth))
     809             :                                 goto end;
     810       12524 :                         cntr_add_same(cntr, CMD_DATA);
     811             :                         break;
     812             :                 case CMD_WRAP_UP:
     813       12534 :                         if(deal_with_wrap_up_from_chfd(chfd->rbuf, blist, dpth))
     814             :                                 goto end;
     815             :                         break;
     816             :                 default:
     817           1 :                         iobuf_log_unexpected(chfd->rbuf, __func__);
     818             :                         goto end;
     819             :         }
     820             :         ret=0;
     821             : end:
     822       25059 :         iobuf_free_content(chfd->rbuf);
     823       25059 :         return ret;
     824             : }
     825             : 
     826          12 : static int check_for_missing_work_in_slist(struct slist *slist)
     827             : {
     828          12 :         struct sbuf *sb=NULL;
     829             : 
     830          12 :         if(slist->blist->head)
     831             :         {
     832           0 :                 logp("ERROR: finishing but still want block: %" PRIu64 "\n",
     833             :                         slist->blist->head->index);
     834             :                 return -1;
     835             :         }
     836             : 
     837          15 :         for(sb=slist->head; sb; sb=sb->next)
     838             :         {
     839           4 :                 if(!(sb->flags & SBUF_END_WRITTEN_TO_MANIFEST))
     840             :                 {
     841           1 :                         logp("ERROR: finishing but still waiting for: %s\n",
     842             :                                 iobuf_to_printable(&slist->head->path));
     843             :                         return -1;
     844             :                 }
     845             :         }
     846             :         return 0;
     847             : }
     848             : 
     849             : #ifndef UTEST
     850             : static
     851             : #endif
     852          24 : int do_backup_phase2_server_protocol2(struct async *as, struct asfd *chfd,
     853             :         struct sdirs *sdirs, int resume, struct conf **confs)
     854             : {
     855          24 :         int ret=-1;
     856          24 :         uint8_t end_flags=0;
     857          24 :         struct slist *slist=NULL;
     858             :         struct iobuf wbuf;
     859          24 :         struct dpth *dpth=NULL;
     860          24 :         man_off_t *p1pos=NULL;
     861          24 :         struct manios *manios=NULL;
     862             :         // This is used to tell the client that a number of consecutive blocks
     863             :         // have been found and can be freed.
     864          24 :         struct asfd *asfd=NULL;
     865          24 :         struct cntr *cntr=NULL;
     866          24 :         struct sbuf *csb=NULL;
     867          24 :         uint64_t file_no=1;
     868             : 
     869          24 :         if(!as)
     870             :         {
     871           1 :                 logp("async not provided to %s()\n", __func__);
     872           1 :                 goto end;
     873             :         }
     874          23 :         if(!sdirs)
     875             :         {
     876           2 :                 logp("sdirs not provided to %s()\n", __func__);
     877           2 :                 goto end;
     878             :         }
     879          21 :         if(!confs)
     880             :         {
     881           1 :                 logp("confs not provided to %s()\n", __func__);
     882           1 :                 goto end;
     883             :         }
     884          20 :         asfd=as->asfd;
     885          20 :         if(!asfd)
     886             :         {
     887           1 :                 logp("asfd not provided to %s()\n", __func__);
     888           1 :                 goto end;
     889             :         }
     890          19 :         if(!chfd)
     891             :         {
     892           1 :                 logp("chfd not provided to %s()\n", __func__);
     893           1 :                 goto end;
     894             :         }
     895          18 :         cntr=get_cntr(confs);
     896          18 :         if(get_int(confs[OPT_BREAKPOINT])>=2000
     897           0 :           && get_int(confs[OPT_BREAKPOINT])<3000)
     898             :         {
     899           0 :                 breaking=get_int(confs[OPT_BREAKPOINT]);
     900           0 :                 breakcount=breaking-2000;
     901             :         }
     902             : 
     903          18 :         blks_generate_init();
     904             : 
     905          18 :         logp("Phase 2 begin (recv backup data)\n");
     906             : 
     907          18 :         if(!(dpth=dpth_alloc())
     908          36 :           || dpth_protocol2_init(dpth,
     909          18 :                 sdirs->data,
     910          18 :                 get_string(confs[OPT_CNAME]),
     911          18 :                 sdirs->cfiles,
     912             :                 get_int(confs[OPT_MAX_STORAGE_SUBDIRS])))
     913             :                         goto end;
     914          18 :         if(resume)
     915             :         {
     916           0 :                 if(!(p1pos=do_resume(sdirs, dpth, confs)))
     917             :                         goto end;
     918           0 :                 if(cntr_send_sdirs(asfd, sdirs, confs, CNTR_STATUS_BACKUP))
     919             :                         goto end;
     920             :         }
     921             : 
     922          18 :         if(!(manios=manios_open_phase2(sdirs, p1pos, PROTO_2))
     923          42 :           || !(slist=slist_alloc())
     924          18 :           || !(csb=sbuf_alloc(PROTO_2)))
     925             :                 goto end;
     926             : 
     927          18 :         iobuf_free_content(asfd->rbuf);
     928             : 
     929             :         memset(&wbuf, 0, sizeof(struct iobuf));
     930      216994 :         while(!(end_flags&END_BACKUP))
     931             :         {
     932      216982 :                 if(write_status(CNTR_STATUS_BACKUP,
     933      217008 :                         csb && csb->path.buf?csb->path.buf:"", cntr))
     934             :                                 goto end;
     935             : 
     936      216982 :                 if(maybe_add_from_scan(manios, slist, chfd, &csb, cntr))
     937             :                         goto end;
     938             : 
     939      216982 :                 if(!wbuf.len)
     940             :                 {
     941      216982 :                         if(get_wbuf_from_sigs(&wbuf, slist, &end_flags))
     942             :                                 goto end;
     943      216982 :                         if(!wbuf.len)
     944             :                         {
     945      208447 :                                 get_wbuf_from_files(&wbuf, slist,
     946             :                                         manios, &end_flags, &file_no);
     947             :                         }
     948             :                 }
     949             : 
     950      216982 :                 if(wbuf.len
     951       25599 :                  && asfd->append_all_to_write_buffer(asfd, &wbuf)==APPEND_ERROR)
     952             :                         goto end;
     953             : 
     954      216981 :                 if(append_for_champ_chooser(chfd, slist->blist, end_flags))
     955             :                         goto end;
     956             : 
     957      216980 :                 if(as->read_write(as))
     958             :                 {
     959           2 :                         logp("error from as->read_write in %s\n", __func__);
     960           2 :                         goto end;
     961             :                 }
     962             : 
     963      267624 :                 while(asfd->rbuf->buf)
     964             :                 {
     965       50647 :                         if(deal_with_read(asfd->rbuf, slist, cntr,
     966             :                                 &end_flags, dpth))
     967             :                                         goto end;
     968             :                         // Get as much out of the readbuf as possible.
     969       50646 :                         if(asfd->parse_readbuf(asfd))
     970             :                                 goto end;
     971             :                 }
     972      242035 :                 while(chfd->rbuf->buf)
     973             :                 {
     974       50118 :                         if(deal_with_read_from_chfd(chfd,
     975       25059 :                                 slist->blist, dpth, cntr))
     976             :                                         goto end;
     977             :                         // Get as much out of the readbuf as possible.
     978       25058 :                         if(chfd->parse_readbuf(chfd))
     979             :                                 goto end;
     980             :                 }
     981             : 
     982      216976 :                 if(write_to_changed_file(asfd, chfd, manios,
     983             :                         slist, end_flags))
     984             :                                 goto end;
     985             :         }
     986             : 
     987             :         // Hack: If there are some entries left after the last entry that
     988             :         // contains block data, it will not be written to the changed file
     989             :         // yet because the last entry of block data has not had
     990             :         // sb->protocol2->bend set.
     991          12 :         if(slist->head && slist->head->next)
     992             :         {
     993           8 :                 struct sbuf *sb=NULL;
     994           8 :                 sb=slist->head;
     995           8 :                 slist->head=sb->next;
     996           8 :                 sbuf_free(&sb);
     997           8 :                 if(write_to_changed_file(asfd, chfd, manios,
     998             :                         slist, end_flags))
     999             :                                 goto end;
    1000             :         }
    1001             : 
    1002          12 :         if(manios_close(&manios))
    1003             :                 goto end;
    1004             : 
    1005          36 :         if(check_for_missing_work_in_slist(slist))
    1006             :                 goto end;
    1007             : 
    1008             :         // Need to release the last left. There should be one at most.
    1009          11 :         if(dpth->head && dpth->head->next)
    1010             :         {
    1011           0 :                 logp("ERROR: More data locks remaining after: %s\n",
    1012           0 :                         dpth->head->save_path);
    1013           0 :                 goto end;
    1014             :         }
    1015          11 :         if(dpth_release_all(dpth)) goto end;
    1016             : 
    1017          11 :         ret=0;
    1018             : end:
    1019          24 :         logp("End backup\n");
    1020          24 :         sbuf_free(&csb);
    1021          24 :         slist_free(&slist);
    1022          24 :         if(asfd) iobuf_free_content(asfd->rbuf);
    1023          24 :         if(chfd) iobuf_free_content(chfd->rbuf);
    1024          24 :         dpth_free(&dpth);
    1025          24 :         manios_close(&manios);
    1026          24 :         man_off_t_free(&p1pos);
    1027          24 :         blks_generate_free();
    1028          24 :         hash_delete_all();
    1029          24 :         return ret;
    1030             : }
    1031             : 
    1032           0 : int backup_phase2_server_protocol2(struct async *as, struct sdirs *sdirs,
    1033             :         int resume, struct conf **confs)
    1034             : {
    1035           0 :         int ret=-1;
    1036           0 :         struct asfd *chfd=NULL;
    1037           0 :         if(!(chfd=champ_chooser_connect(as, sdirs, confs, resume)))
    1038             :         {
    1039           0 :                 logp("problem connecting to champ chooser\n");
    1040           0 :                 goto end;
    1041             :         }
    1042           0 :         ret=do_backup_phase2_server_protocol2(as, chfd, sdirs, resume, confs);
    1043             : end:
    1044           0 :         if(chfd) as->asfd_remove(as, chfd);
    1045           0 :         asfd_free(&chfd);
    1046           0 :         return ret;
    1047             : }

Generated by: LCOV version 1.10