Line data Source code
1 : #include "../../burp.h"
2 : #include "../../alloc.h"
3 : #include "../../cmd.h"
4 : #include "../../fzp.h"
5 : #include "../../hexmap.h"
6 : #include "../../iobuf.h"
7 : #include "../../log.h"
8 : #include "../../prepend.h"
9 : #include "../../protocol2/blk.h"
10 : #include "rblk.h"
11 :
12 : static ssize_t rblk_mem=0;
13 : static ssize_t rblk_mem_max=0;
14 :
15 : // For retrieving stored data.
16 : struct rblk
17 : {
18 : uint64_t hash_key;
19 : struct iobuf readbuf[DATA_FILE_SIG_MAX];
20 : uint16_t rlen;
21 : struct fzp *fzp;
22 : UT_hash_handle hh;
23 : };
24 :
25 56 : static void rblk_free_content(struct rblk *rblk)
26 : {
27 372 : for(int j=0; j<rblk->rlen; j++)
28 : {
29 316 : rblk_mem-=rblk->readbuf[j].len;
30 316 : iobuf_free_content(&rblk->readbuf[j]);
31 : }
32 56 : fzp_close(&rblk->fzp);
33 56 : }
34 :
35 56 : static void rblk_free(struct rblk **rblk)
36 : {
37 : /*
38 : uint16_t datno;
39 : char *x;
40 : x=uint64_to_savepathstr_with_sig_uint((*rblk)->hash_key, &datno);
41 : logp("close: %s\n", x);
42 : */
43 56 : rblk_free_content(*rblk);
44 56 : rblk_mem-=sizeof(struct rblk);
45 56 : free_v((void **)rblk);
46 56 : }
47 :
48 : static struct rblk *rblk_hash=NULL;
49 :
50 316 : static struct rblk *rblk_hash_find(uint64_t savepath)
51 : {
52 : struct rblk *rblk;
53 316 : HASH_FIND_INT(rblk_hash, &savepath, rblk);
54 316 : return rblk;
55 : }
56 :
57 56 : static void rblk_hash_add(struct rblk *rblk)
58 : {
59 56 : HASH_ADD_INT(rblk_hash, hash_key, rblk);
60 56 : }
61 :
62 56 : static struct rblk *rblk_alloc(void)
63 : {
64 : struct rblk *rblk;
65 56 : rblk=(struct rblk *)calloc_w(1, sizeof(struct rblk), __func__);
66 56 : if(rblk)
67 56 : rblk_mem+=sizeof(struct rblk);
68 56 : return rblk;
69 : }
70 :
71 6 : void rblks_init(ssize_t rblk_memory_max)
72 : {
73 6 : rblk_mem_max=rblk_memory_max;
74 6 : }
75 :
76 7 : void rblks_free(void)
77 : {
78 : struct rblk *tmp;
79 : struct rblk *rblk;
80 :
81 63 : HASH_ITER(hh, rblk_hash, rblk, tmp)
82 : {
83 56 : HASH_DEL(rblk_hash, rblk);
84 56 : rblk_free(&rblk);
85 : }
86 7 : rblk_hash=NULL;
87 7 : }
88 :
89 0 : static int rblks_free_one_except(struct rblk *keep)
90 : {
91 0 : uint64_t before=rblk_mem;
92 : struct rblk *tmp;
93 : struct rblk *rblk;
94 :
95 0 : HASH_ITER(hh, rblk_hash, rblk, tmp)
96 : {
97 0 : if(rblk==keep)
98 0 : continue;
99 0 : HASH_DEL(rblk_hash, rblk);
100 0 : rblk_free(&rblk);
101 0 : break;
102 : }
103 0 : if(before!=rblk_mem)
104 : return 0;
105 0 : return -1;
106 : }
107 :
108 56 : static int rblk_init(struct rblk *rblk, struct blk *blk,
109 : uint64_t hash_key, const char *datpath, const char *savepathstr)
110 : {
111 56 : int ret=-1;
112 56 : char *fulldatpath=NULL;
113 :
114 56 : rblk->hash_key=hash_key;
115 56 : if(!(fulldatpath=prepend_s(datpath, savepathstr)))
116 : goto end;
117 56 : logp("open: %s\n", savepathstr);
118 56 : if(!(rblk->fzp=fzp_open(fulldatpath, "rb")))
119 : goto end;
120 56 : ret=0;
121 : end:
122 56 : free_w(&fulldatpath);
123 56 : return ret;
124 : }
125 :
126 316 : static int rblk_load_more_chunks(struct rblk *rblk, uint16_t datno_target)
127 : {
128 316 : int ret=-1;
129 316 : int done=0;
130 : struct iobuf rbuf;
131 :
132 316 : iobuf_init(&rbuf);
133 :
134 948 : for(
135 : ;
136 1264 : rblk->rlen<DATA_FILE_SIG_MAX && rblk->rlen<=datno_target;
137 316 : rblk->rlen++
138 : ) {
139 316 : switch(iobuf_fill_from_fzp_data(&rbuf, rblk->fzp))
140 : {
141 : case 0:
142 316 : if(rbuf.cmd!=CMD_DATA)
143 : {
144 0 : logp("unknown cmd in %s: %c\n",
145 : __func__, rbuf.cmd);
146 0 : goto end;
147 : }
148 316 : iobuf_move(&rblk->readbuf[rblk->rlen], &rbuf);
149 316 : rblk_mem+=rblk->readbuf[rblk->rlen].len;
150 316 : continue;
151 : case 1:
152 : done++;
153 : break;
154 : default:
155 : goto end;
156 : }
157 : if(done)
158 : break;
159 : }
160 : ret=0;
161 : end:
162 316 : return ret;
163 : }
164 :
165 316 : int rblk_retrieve_data(struct asfd *asfd, struct cntr *cntr,
166 : struct blk *blk, const char *datpath)
167 : {
168 316 : uint16_t datno=0;
169 : uint64_t hash_key;
170 : char *savepathstr;
171 316 : struct rblk *rblk=NULL;
172 :
173 316 : hash_key=uint64_to_savepath_hash_key(blk->savepath);
174 316 : savepathstr=uint64_to_savepathstr_with_sig_uint(blk->savepath, &datno);
175 :
176 316 : if(!(rblk=rblk_hash_find(hash_key)))
177 : {
178 56 : if(!(rblk=rblk_alloc())
179 56 : || rblk_init(rblk, blk, hash_key, datpath, savepathstr))
180 : {
181 0 : rblk_free(&rblk);
182 0 : return -1;
183 : }
184 56 : rblk_hash_add(rblk);
185 : }
186 :
187 316 : if(datno>=rblk->rlen)
188 : {
189 : // Need to load more from this data file.
190 316 : if(rblk_load_more_chunks(rblk, datno))
191 : return -1;
192 : }
193 :
194 316 : while(rblk_mem>rblk_mem_max)
195 : {
196 0 : if(rblks_free_one_except(rblk))
197 : {
198 0 : logw(asfd, cntr, "rblk_memory_max is too low!\n");
199 0 : break;
200 : }
201 : }
202 :
203 : // printf("lookup: %s (%u)\n", savepathstr, datno);
204 316 : if(datno>=rblk->rlen)
205 : {
206 0 : logp("datno %d is greater than rlen: %d\n",
207 : datno, rblk->rlen);
208 0 : return -1;
209 : }
210 316 : blk->data=rblk->readbuf[datno].buf;
211 316 : blk->length=rblk->readbuf[datno].len;
212 : // printf("length: %d\n", blk->length);
213 :
214 316 : return 0;
215 : }
|