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