LCOV - code coverage report
Current view: top level - src/server/protocol2/champ_chooser - candidate.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 66 85 77.6 %
Date: 2017-05-01 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #include "../../../burp.h"
       2             : #include "../../../alloc.h"
       3             : #include "../../../log.h"
       4             : #include "../../../sbuf.h"
       5             : #include "../../../protocol2/blk.h"
       6             : #include "candidate.h"
       7             : #include "incoming.h"
       8             : #include "scores.h"
       9             : #include "sparse.h"
      10             : 
      11             : #include <assert.h>
      12             : 
      13             : struct candidate **candidates=NULL;
      14             : size_t candidates_len=0;
      15             : 
      16             : #ifndef UTEST
      17             : static
      18             : #endif
      19           6 : struct candidate *candidate_alloc(void)
      20             : {
      21          17 :         return (struct candidate *)
      22             :                 calloc_w(1, sizeof(struct candidate), __func__);
      23             : }
      24             : 
      25             : static void candidate_free_content(struct candidate *c)
      26             : {
      27          17 :         if(!c) return;
      28          17 :         free_w(&c->path);
      29             : }
      30             : 
      31             : #ifndef UTEST
      32             : static
      33             : #endif
      34          17 : void candidate_free(struct candidate **c)
      35             : {
      36          34 :         if(!c) return;
      37          17 :         candidate_free_content(*c);
      38          17 :         free_v((void **)c);
      39             : }
      40             : 
      41           1 : void candidates_free(void)
      42             : {
      43          11 :         for(size_t c=0; c<candidates_len; c++)
      44          10 :                 candidate_free(&(candidates[c]));
      45           1 :         free_v((void **)&candidates);
      46           1 : }
      47             : 
      48             : static void candidates_set_score_pointers(struct candidate **candidates,
      49             :         struct scores *scores)
      50             : {
      51             :         size_t a;
      52          10 :         for(a=0; candidates && a<candidates_len; a++)
      53          10 :                 candidates[a]->score=&(scores->scores[a]);
      54             : }
      55             : 
      56          11 : struct candidate *candidates_add_new(void)
      57             : {
      58             :         struct candidate *candidate;
      59             : 
      60          11 :         if(!(candidate=candidate_alloc())) return NULL;
      61             : 
      62          11 :         if(!(candidates=(struct candidate **)realloc_w(candidates,
      63             :                 (candidates_len+1)*sizeof(struct candidate *), __func__)))
      64             :                         return NULL;
      65          11 :         candidates[candidates_len++]=candidate;
      66          11 :         return candidate;
      67             : }
      68             : 
      69             : // This deals with reading in the sparse index, as well as actual candidate
      70             : // manifests.
      71           2 : enum cand_ret candidate_load(struct candidate *candidate, const char *path,
      72             :         struct scores *scores)
      73             : {
      74           2 :         enum cand_ret ret=CAND_RET_PERM;
      75           2 :         struct fzp *fzp=NULL;
      76           2 :         struct sbuf *sb=NULL;
      77           2 :         struct blk *blk=NULL;
      78             : 
      79           2 :         if(!(sb=sbuf_alloc(PROTO_2))
      80           2 :           || !(blk=blk_alloc()))
      81             :         {
      82             :                 ret=CAND_RET_PERM;
      83             :                 goto error;
      84             :         }
      85             :         
      86           2 :         if(!(fzp=fzp_gzopen(path, "rb")))
      87             :         {
      88             :                 ret=CAND_RET_TEMP;
      89             :                 goto error;
      90             :         }
      91         511 :         while(fzp)
      92             :         {
      93         511 :                 sbuf_free_content(sb);
      94         511 :                 switch(sbuf_fill_from_file(sb, fzp, blk, NULL))
      95             :                 {
      96             :                         case 1: goto end;
      97             :                         case -1:
      98           0 :                                 logp("Error reading %s in %s, pos %lld\n",
      99           0 :                                         path, __func__, (long long)fzp_tell(fzp));
     100           0 :                                 ret=CAND_RET_TEMP;
     101           0 :                                 goto error;
     102             :                 }
     103         510 :                 if(blk_fingerprint_is_hook(blk))
     104             :                 {
     105          33 :                         if(sparse_add_candidate(&blk->fingerprint, candidate))
     106             :                         {
     107             :                                 ret=CAND_RET_PERM;
     108             :                                 goto error;
     109             :                         }
     110             :                 }
     111         477 :                 else if(sb->path.cmd==CMD_MANIFEST)
     112             :                 {
     113          10 :                         if(!(candidate=candidates_add_new()))
     114             :                         {
     115             :                                 ret=CAND_RET_PERM;
     116             :                                 goto error;
     117             :                         }
     118          10 :                         candidate->path=sb->path.buf;
     119          10 :                         sb->path.buf=NULL;
     120             :                 }
     121         510 :                 blk->fingerprint=0;
     122             :         }
     123             : 
     124             : end:
     125           1 :         if(scores_grow(scores, candidates_len))
     126             :         {
     127             :                 ret=CAND_RET_PERM;
     128             :                 goto error;
     129             :         }
     130           1 :         candidates_set_score_pointers(candidates, scores);
     131           1 :         scores_reset(scores);
     132             :         //logp("Now have %d candidates\n", (int)candidates_len);
     133           1 :         ret=CAND_RET_OK;
     134             : error:
     135           2 :         fzp_close(&fzp);
     136           2 :         sbuf_free(&sb);
     137           2 :         blk_free(&blk);
     138           2 :         return ret;
     139             : }
     140             : 
     141             : // When a backup is ongoing, use this to add newly complete candidates.
     142           1 : int candidate_add_fresh(const char *path, const char *directory,
     143             :         struct scores *scores)
     144             : {
     145           1 :         const char *cp=NULL;
     146           1 :         struct candidate *candidate=NULL;
     147             : 
     148           1 :         if(!(candidate=candidates_add_new()))
     149             :                 goto error;
     150           1 :         cp=path+strlen(directory);
     151           1 :         while(cp && *cp=='/') cp++;
     152           1 :         if(!(candidate->path=strdup_w(cp, __func__)))
     153             :                 goto error;
     154             : 
     155           1 :         switch(candidate_load(candidate, path, scores))
     156             :         {
     157             :                 case CAND_RET_PERM:
     158             :                         goto error;
     159             :                 case CAND_RET_TEMP:
     160             :                         // Had an error - try to carry on. Errors can happen
     161             :                         // when loading a fresh candidate because the backup
     162             :                         // process can move to the next phase and rename the
     163             :                         // candidates.
     164           1 :                         logp("Removing candidate.\n");
     165           1 :                         candidates_len--;
     166           1 :                         sparse_delete_fresh_candidate(candidate);
     167           1 :                         candidate_free(&candidate);
     168             :                         // Fall through.
     169             :                 case CAND_RET_OK:
     170             :                         return 0;
     171             :         }
     172             : error:
     173           0 :         candidate_free(&candidate);
     174           0 :         return -1;
     175             : }
     176             : 
     177           1 : struct candidate *candidates_choose_champ(struct incoming *in,
     178             :         struct candidate *champ_last, struct scores *scores)
     179             : {
     180             :         static uint16_t i;
     181             :         static uint16_t s;
     182             :         static struct sparse *sparse;
     183             :         static struct candidate *best;
     184             :         static struct candidate *candidate;
     185             :         static uint16_t *score;
     186             : 
     187           1 :         best=NULL;
     188             : 
     189             :         //struct timespec tstart={0,0}, tend={0,0};
     190             :         //clock_gettime(CLOCK_MONOTONIC, &tstart);
     191             : 
     192           1 :         scores_reset(scores);
     193             : 
     194        4097 :         for(i=0; i<in->size; i++)
     195             :         {
     196        4096 :                 if(in->found[i]) continue;
     197             : 
     198        4096 :                 if(!(sparse=sparse_find(&in->fingerprints[i])))
     199        4096 :                         continue;
     200           0 :                 for(s=0; s<sparse->size; s++)
     201             :                 {
     202           0 :                         candidate=sparse->candidates[s];
     203           0 :                         if(candidate->deleted) continue;
     204           0 :                         if(candidate==champ_last)
     205             :                         {
     206             :                                 int t;
     207             :                                 // Want to exclude sparse entries that have
     208             :                                 // already been found.
     209           0 :                                 in->found[i]=1;
     210             :                                 // Need to go back up the list, subtracting
     211             :                                 // scores.
     212           0 :                                 for(t=s-1; t>=0; t--)
     213             :                                 {
     214           0 :                                         (*(sparse->candidates[t]->score))--;
     215             : //      printf("%d %s   fix: %d\n", i, candidate->path, *(sparse->candidates[t]->score));
     216             :                                 }
     217             :                                 break;
     218             :                         }
     219           0 :                         score=candidate->score;
     220           0 :                         (*score)++;
     221             : //                      printf("%d %s score: %d\n", i, candidate->path, *score);
     222           0 :                         assert(*score<=in->size);
     223           0 :                         if(!best
     224             :                         // Maybe should check for candidate!=best here too.
     225           0 :                           || *score>*(best->score))
     226             :                         {
     227           0 :                                 best=candidate;
     228             : /*
     229             :                                 printf("%s is now best:\n",
     230             :                                         best->path);
     231             :                                 printf("    score %p %d\n",
     232             :                                         best->score, *(best->score));
     233             : */
     234             :                         }
     235             :                         // FIX THIS: figure out a way of giving preference to
     236             :                         // newer candidates.
     237             :                 }
     238             :         }
     239             :         //clock_gettime(CLOCK_MONOTONIC, &tend);
     240             :         //printf("champ_chooser took about %.5f seconds\n",
     241             :         //      ((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - 
     242             :         //      ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec));
     243             : 
     244             : /*
     245             :         if(best)
     246             :                 printf("%s is choice:\nscore %p %d\n", best->path, best->score, *(best->score));
     247             :         else
     248             :                 printf("no choice\n");
     249             : */
     250           1 :         return best;
     251             : }

Generated by: LCOV version 1.10