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: 0 423 0.0 %
Date: 2015-11-30 Functions: 0 26 0.0 %

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

Generated by: LCOV version 1.10