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 17 : if(!c) return;
37 34 : 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))
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 2 : 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 : }
|