LCOV - code coverage report
Current view: top level - src/server/protocol2/champ_chooser - champ_server.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 15 158 9.5 %
Date: 2016-07-02 Functions: 2 7 28.6 %

          Line data    Source code
       1             : #include "../../../burp.h"
       2             : #include "../../../alloc.h"
       3             : #include "../../../asfd.h"
       4             : #include "../../../async.h"
       5             : #include "../../../cmd.h"
       6             : #include "../../../conf.h"
       7             : #include "../../../conffile.h"
       8             : #include "../../../fsops.h"
       9             : #include "../../../handy.h"
      10             : #include "../../../iobuf.h"
      11             : #include "../../../lock.h"
      12             : #include "../../../log.h"
      13             : #include "../../../protocol2/blist.h"
      14             : #include "../../../protocol2/blk.h"
      15             : #include "../../sdirs.h"
      16             : #include "candidate.h"
      17             : #include "champ_chooser.h"
      18             : #include "champ_server.h"
      19             : #include "dindex.h"
      20             : #include "incoming.h"
      21             : #include "scores.h"
      22             : 
      23             : #include <sys/un.h>
      24             : 
      25           0 : static int champ_chooser_new_client(struct async *as, struct conf **confs)
      26             : {
      27           0 :         int fd=-1;
      28             :         socklen_t t;
      29           0 :         struct asfd *newfd=NULL;
      30             :         struct sockaddr_un remote;
      31           0 :         struct blist *blist=NULL;
      32             : 
      33           0 :         t=sizeof(remote);
      34           0 :         if((fd=accept(as->asfd->fd, (struct sockaddr *)&remote, &t))<0)
      35             :         {
      36           0 :                 logp("accept error in %s: %s\n", __func__, strerror(errno));
      37             :                 goto error;
      38             :         }
      39             : 
      40           0 :         if(!(blist=blist_alloc())
      41           0 :           || !(newfd=setup_asfd(as, "(unknown)", &fd)))
      42             :                 goto error;
      43           0 :         newfd->blist=blist;
      44             : 
      45           0 :         logp("Connected to fd %d\n", newfd->fd);
      46             : 
      47             :         return 0;
      48             : error:
      49           0 :         close_fd(&fd);
      50           0 :         blist_free(&blist);
      51             :         return -1;
      52             : }
      53             : 
      54           0 : static int results_to_fd(struct asfd *asfd)
      55             : {
      56             :         static struct iobuf wbuf;
      57             :         struct blk *b;
      58             :         struct blk *l;
      59             : 
      60           0 :         if(!asfd->blist->last_index) return 0;
      61             : 
      62             :         // Need to start writing the results down the fd.
      63           0 :         for(b=asfd->blist->head; b && b!=asfd->blist->blk_to_dedup; b=l)
      64             :         {
      65           0 :                 if(b->got==BLK_GOT)
      66             :                 {
      67             :                         // Need to write to fd.
      68           0 :                         blk_to_iobuf_index_and_savepath(b, &wbuf);
      69             : 
      70           0 :                         switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
      71             :                         {
      72             :                                 case APPEND_OK: break;
      73             :                                 case APPEND_BLOCKED:
      74           0 :                                         asfd->blist->head=b;
      75           0 :                                         return 0; // Try again later.
      76             :                                 default: return -1;
      77             :                         }
      78             :                 }
      79             :                 else
      80             :                 {
      81             :                         // If the last in the sequence is BLK_NOT_GOT,
      82             :                         // Send a 'wrap_up' message.
      83           0 :                         if(!b->next || b->next==asfd->blist->blk_to_dedup)
      84             :                         {
      85           0 :                                 blk_to_iobuf_wrap_up(b, &wbuf);
      86           0 :                                 switch(asfd->append_all_to_write_buffer(asfd,
      87             :                                         &wbuf))
      88             :                                 {
      89             :                                         case APPEND_OK: break;
      90             :                                         case APPEND_BLOCKED:
      91           0 :                                                 asfd->blist->head=b;
      92           0 :                                                 return 0; // Try again later.
      93             :                                         default: return -1;
      94             :                                 }
      95             :                         }
      96             :                 }
      97           0 :                 l=b->next;
      98           0 :                 blk_free(&b);
      99             :         }
     100             : 
     101           0 :         asfd->blist->head=b;
     102           0 :         if(!b) asfd->blist->tail=NULL;
     103             :         return 0;
     104             : }
     105             : 
     106        4096 : static int deduplicate_maybe(struct asfd *asfd,
     107             :         struct blk *blk, const char *directory, struct scores *scores)
     108             : {
     109        4096 :         if(!asfd->in && !(asfd->in=incoming_alloc()))
     110             :                 return -1;
     111             : 
     112        4096 :         if(blk_fingerprint_is_hook(blk))
     113             :         {
     114        4096 :                 if(incoming_grow_maybe(asfd->in))
     115             :                         return -1;
     116        4096 :                 asfd->in->fingerprints[asfd->in->size-1]=blk->fingerprint;
     117             :         }
     118        4096 :         if(++(asfd->blkcnt)<MANIFEST_SIG_MAX)
     119             :                 return 0;
     120           1 :         asfd->blkcnt=0;
     121             : 
     122           1 :         if(deduplicate(asfd, directory, scores)<0)
     123             :                 return -1;
     124             : 
     125           1 :         return 0;
     126             : }
     127             : 
     128             : #ifndef UTEST
     129             : static
     130             : #endif
     131        4097 : int champ_server_deal_with_rbuf_sig(struct asfd *asfd,
     132             :         const char *directory, struct scores *scores)
     133             : {
     134             :         struct blk *blk;
     135        4097 :         if(!(blk=blk_alloc())) return -1;
     136             : 
     137        4097 :         blist_add_blk(asfd->blist, blk);
     138             : 
     139        4097 :         if(!asfd->blist->blk_to_dedup)
     140           0 :                 asfd->blist->blk_to_dedup=blk;
     141             : 
     142        4097 :         if(blk_set_from_iobuf_sig(blk, asfd->rbuf))
     143             :                 return -1;
     144             : 
     145             :         //logp("Got fingerprint from %d: %lu - %lu\n",
     146             :         //      asfd->fd, blk->index, blk->fingerprint);
     147             : 
     148        4096 :         return deduplicate_maybe(asfd, blk, directory, scores);
     149             : }
     150             : 
     151           0 : static int deal_with_client_rbuf(struct asfd *asfd, const char *directory,
     152             :         struct scores *scores)
     153             : {
     154           0 :         if(asfd->rbuf->cmd==CMD_GEN)
     155             :         {
     156           0 :                 if(!strncmp_w(asfd->rbuf->buf, "cname:"))
     157             :                 {
     158             :                         struct iobuf wbuf;
     159           0 :                         free_w(&asfd->desc);
     160           0 :                         if(!(asfd->desc=strdup_w(asfd->rbuf->buf
     161           0 :                                 +strlen("cname:"), __func__)))
     162             :                                         goto error;
     163           0 :                         logp("%s: fd %d\n", asfd->desc, asfd->fd);
     164             :                         iobuf_set(&wbuf, CMD_GEN,
     165           0 :                                 (char *)"cname ok", strlen("cname ok"));
     166             : 
     167           0 :                         if(asfd->write(asfd, &wbuf))
     168             :                                 goto error;
     169             :                 }
     170           0 :                 else if(!strncmp_w(asfd->rbuf->buf, "sigs_end"))
     171             :                 {
     172             :                         //printf("Was told no more sigs\n");
     173           0 :                         if(deduplicate(asfd, directory, scores)<0)
     174             :                                 goto error;
     175             :                 }
     176             :                 else
     177             :                 {
     178           0 :                         iobuf_log_unexpected(asfd->rbuf, __func__);
     179           0 :                         goto error;
     180             :                 }
     181             :         }
     182           0 :         else if(asfd->rbuf->cmd==CMD_SIG)
     183             :         {
     184           0 :                 if(champ_server_deal_with_rbuf_sig(asfd, directory, scores))
     185             :                         goto error;
     186             :         }
     187           0 :         else if(asfd->rbuf->cmd==CMD_MANIFEST)
     188             :         {
     189             :                 // Client has completed a manifest file. Want to start using
     190             :                 // it as a dedup candidate now.
     191           0 :                 if(candidate_add_fresh(asfd->rbuf->buf, directory, scores))
     192             :                         goto error;
     193             :         }
     194             :         else
     195             :         {
     196           0 :                 iobuf_log_unexpected(asfd->rbuf, __func__);
     197           0 :                 goto error;
     198             :         }
     199           0 :         iobuf_free_content(asfd->rbuf);
     200           0 :         return 0;
     201             : error:
     202           0 :         iobuf_free_content(asfd->rbuf);
     203           0 :         return -1;
     204             : }
     205             : 
     206           0 : int champ_chooser_server(struct sdirs *sdirs, struct conf **confs,
     207             :         int resume)
     208             : {
     209             :         int s;
     210           0 :         int ret=-1;
     211             :         int len;
     212           0 :         struct asfd *asfd=NULL;
     213             :         struct sockaddr_un local;
     214           0 :         struct lock *lock=NULL;
     215           0 :         struct async *as=NULL;
     216           0 :         int started=0;
     217           0 :         struct scores *scores=NULL;
     218           0 :         const char *directory=get_string(confs[OPT_DIRECTORY]);
     219             : 
     220           0 :         if(!(lock=lock_alloc_and_init(sdirs->champlock))
     221           0 :           || build_path_w(sdirs->champlock))
     222             :                 goto end;
     223           0 :         lock_get(lock);
     224           0 :         switch(lock->status)
     225             :         {
     226             :                 case GET_LOCK_GOT:
     227           0 :                         log_fzp_set(sdirs->champlog, confs);
     228             :                         logp("Got champ lock for dedup_group: %s\n",
     229           0 :                                 get_string(confs[OPT_DEDUP_GROUP]));
     230             :                         break;
     231             :                 case GET_LOCK_NOT_GOT:
     232             :                 case GET_LOCK_ERROR:
     233             :                 default:
     234             :                         //logp("Did not get champ lock\n");
     235             :                         goto end;
     236             :         }
     237             : 
     238           0 :         if((s=socket(AF_UNIX, SOCK_STREAM, 0))<0)
     239             :         {
     240           0 :                 logp("socket error in %s: %s\n", __func__, strerror(errno));
     241           0 :                 goto end;
     242             :         }
     243             : 
     244             :         memset(&local, 0, sizeof(struct sockaddr_un));
     245           0 :         local.sun_family=AF_UNIX;
     246             :         snprintf(local.sun_path, sizeof(local.sun_path),
     247           0 :                 "%s", sdirs->champsock);
     248           0 :         len=strlen(local.sun_path)+sizeof(local.sun_family)+1;
     249           0 :         unlink(sdirs->champsock);
     250           0 :         if(bind(s, (struct sockaddr *)&local, len)<0)
     251             :         {
     252           0 :                 logp("bind error in %s: %s\n", __func__, strerror(errno));
     253           0 :                 goto end;
     254             :         }
     255             : 
     256           0 :         if(listen(s, 5)<0)
     257             :         {
     258           0 :                 logp("listen error in %s: %s\n", __func__, strerror(errno));
     259           0 :                 goto end;
     260             :         }
     261             : 
     262           0 :         if(!(as=async_alloc())
     263           0 :           || as->init(as, 0)
     264           0 :           || !(asfd=setup_asfd(as, "champ chooser main socket", &s)))
     265             :                 goto end;
     266           0 :         asfd->fdtype=ASFD_FD_SERVER_LISTEN_MAIN;
     267           0 :         asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT]));
     268             : 
     269             :         // I think that this is probably the best point at which to run a
     270             :         // cleanup job to delete unused data files, because no other process
     271             :         // can fiddle with the dedup_group at this point.
     272             :         // Cannot do it on a resume, or it will delete files that are
     273             :         // referenced in the backup we are resuming.
     274           0 :         if(delete_unused_data_files(sdirs, resume))
     275             :                 goto end;
     276             : 
     277             :         // Load the sparse indexes for this dedup group.
     278           0 :         if(!(scores=champ_chooser_init(sdirs->data)))
     279             :                 goto end;
     280             : 
     281             :         while(1)
     282             :         {
     283           0 :                 for(asfd=as->asfd->next; asfd; asfd=asfd->next)
     284             :                 {
     285           0 :                         if(!asfd->blist->head
     286           0 :                           || asfd->blist->head->got==BLK_INCOMING) continue;
     287           0 :                         if(results_to_fd(asfd)) goto end;
     288             :                 }
     289             : 
     290           0 :                 switch(as->read_write(as))
     291             :                 {
     292             :                         case 0:
     293             :                                 // Check the main socket last, as it might add
     294             :                                 // a new client to the list.
     295           0 :                                 for(asfd=as->asfd->next; asfd; asfd=asfd->next)
     296             :                                 {
     297           0 :                                         while(asfd->rbuf->buf)
     298             :                                         {
     299           0 :                                                 if(deal_with_client_rbuf(asfd,
     300           0 :                                                         directory, scores))
     301             :                                                                 goto end;
     302             :                                                 // Get as much out of the
     303             :                                                 // readbuf as possible.
     304           0 :                                                 if(asfd->parse_readbuf(asfd))
     305             :                                                         goto end;
     306             :                                         }
     307             :                                 }
     308           0 :                                 if(as->asfd->new_client)
     309             :                                 {
     310             :                                         // Incoming client.
     311           0 :                                         as->asfd->new_client=0;
     312           0 :                                         if(champ_chooser_new_client(as, confs))
     313             :                                                 goto end;
     314             :                                         started=1;
     315             :                                 }
     316             :                                 break;
     317             :                         default:
     318           0 :                                 int removed=0;
     319             :                                 // Maybe one of the fds had a problem.
     320             :                                 // Find and remove it and carry on if possible.
     321           0 :                                 for(asfd=as->asfd->next; asfd; )
     322             :                                 {
     323             :                                         struct asfd *a;
     324           0 :                                         if(!asfd->want_to_remove)
     325             :                                         {
     326           0 :                                                 asfd=asfd->next;
     327           0 :                                                 continue;
     328             :                                         }
     329           0 :                                         as->asfd_remove(as, asfd);
     330             :                                         logp("%s: disconnected fd %d\n",
     331           0 :                                                 asfd->desc, asfd->fd);
     332           0 :                                         a=asfd->next;
     333           0 :                                         asfd_free(&asfd);
     334           0 :                                         asfd=a;
     335           0 :                                         removed++;
     336             :                                 }
     337           0 :                                 if(removed) break;
     338             :                                 // If we got here, there was no fd to remove.
     339             :                                 // It is a fatal error.
     340             :                                 goto end;
     341             :                 }
     342             :                                 
     343           0 :                 if(started && !as->asfd->next)
     344             :                 {
     345           0 :                         logp("All clients disconnected.\n");
     346           0 :                         ret=0;
     347           0 :                         break;
     348             :                 }
     349             :         }
     350             : 
     351             : end:
     352           0 :         logp("champ chooser exiting: %d\n", ret);
     353           0 :         champ_chooser_free(&scores);
     354           0 :         log_fzp_set(NULL, confs);
     355           0 :         async_free(&as);
     356           0 :         asfd_free(&asfd); // This closes s for us.
     357           0 :         close_fd(&s);
     358           0 :         unlink(sdirs->champsock);
     359             : // FIX THIS: free asfds.
     360           0 :         lock_release(lock);
     361           0 :         lock_free(&lock);
     362           0 :         return ret;
     363             : }
     364             : 
     365             : // The return code of this is the return code of the standalone process.
     366           0 : int champ_chooser_server_standalone(struct conf **globalcs)
     367             : {
     368           0 :         int ret=1;
     369           0 :         struct sdirs *sdirs=NULL;
     370           0 :         struct conf **cconfs=NULL;
     371           0 :         const char *orig_client=get_string(globalcs[OPT_ORIG_CLIENT]);
     372             : 
     373           0 :         if(!(cconfs=confs_alloc()))
     374             :                 goto end;
     375           0 :         confs_init(cconfs);
     376             :         // We need to be given a client name and load the relevant server side
     377             :         // clientconfdir file, because various settings may be overridden
     378             :         // there.
     379           0 :         if(set_string(cconfs[OPT_CNAME], orig_client)
     380           0 :           || conf_load_clientconfdir(globalcs, cconfs)
     381           0 :           || !(sdirs=sdirs_alloc())
     382           0 :           || sdirs_init_from_confs(sdirs, cconfs)
     383           0 :           || champ_chooser_server(sdirs, cconfs, 0 /* resume */))
     384             :                 goto end;
     385           0 :         ret=0;
     386             : end:
     387           0 :         confs_free(&cconfs);
     388           0 :         sdirs_free(&sdirs);
     389           0 :         return ret;
     390             : }

Generated by: LCOV version 1.10