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

Generated by: LCOV version 1.10