1 | #define MODULE_LOG_PREFIX "cache"
|
---|
2 |
|
---|
3 | #include "globals.h"
|
---|
4 | #include "module-cacheex.h"
|
---|
5 | #include "module-cw-cycle-check.h"
|
---|
6 | #include "oscam-cache.h"
|
---|
7 | #include "oscam-chk.h"
|
---|
8 | #include "oscam-client.h"
|
---|
9 | #include "oscam-ecm.h"
|
---|
10 | #include "oscam-garbage.h"
|
---|
11 | #include "oscam-lock.h"
|
---|
12 | #include "oscam-net.h"
|
---|
13 | #include "oscam-string.h"
|
---|
14 | #include "oscam-time.h"
|
---|
15 | #include "oscam-hashtable.h"
|
---|
16 | #ifdef CS_CACHEEX_AIO
|
---|
17 | #include "oscam-log.h"
|
---|
18 | #endif
|
---|
19 |
|
---|
20 |
|
---|
21 | // CACHE functions **************************************************************+
|
---|
22 | struct s_pushclient
|
---|
23 | {
|
---|
24 | struct s_client *cl;
|
---|
25 | struct s_pushclient *next_push;
|
---|
26 | };
|
---|
27 |
|
---|
28 | typedef struct cw_t
|
---|
29 | {
|
---|
30 | uint8_t cw[16];
|
---|
31 | uint8_t odd_even; // odd/even byte (0x80 0x81)
|
---|
32 | uint8_t cwc_cycletime;
|
---|
33 | uint8_t cwc_next_cw_cycle;
|
---|
34 | uint8_t got_bad_cwc; // used by cycle check
|
---|
35 | uint16_t caid; // first caid received
|
---|
36 | uint32_t prid; // first prid received
|
---|
37 | uint16_t srvid; // first srvid received
|
---|
38 | struct s_reader *selected_reader; // first answering: reader
|
---|
39 | struct s_client *cacheex_src; // first answering: cacheex client
|
---|
40 | uint64_t grp; // updated grp
|
---|
41 | uint8_t csp; // updated if answer from csp
|
---|
42 | uint8_t cacheex; // updated if answer from cacheex
|
---|
43 | uint8_t localcards; // updated if answer from local cards (or proxy using localcards option)
|
---|
44 | uint8_t proxy; // updated if answer from local reader
|
---|
45 | uint32_t count; // count of same cws receved
|
---|
46 | #ifdef CS_CACHEEX_AIO
|
---|
47 | uint8_t localgenerated; // flag for local generated CWs
|
---|
48 | #endif
|
---|
49 | // for push out
|
---|
50 | pthread_rwlock_t pushout_client_lock;
|
---|
51 | struct s_pushclient *pushout_client; // list of clients that pushing cw
|
---|
52 | // end push out
|
---|
53 | node ht_node; // node for hash table
|
---|
54 | node ll_node; // node for linked list
|
---|
55 | } CW;
|
---|
56 |
|
---|
57 | typedef struct cache_t
|
---|
58 | {
|
---|
59 | hash_table ht_cw;
|
---|
60 | list ll_cw;
|
---|
61 | struct timeb upd_time; // updated time. Update time at each cw got
|
---|
62 | struct timeb first_recv_time; // time of first cw received
|
---|
63 | uint32_t csp_hash;
|
---|
64 | node ht_node; // node for hash table
|
---|
65 | node ll_node; // node for linked list
|
---|
66 | } ECMHASH;
|
---|
67 |
|
---|
68 | #ifdef CS_CACHEEX_AIO
|
---|
69 | typedef struct cw_cache_t
|
---|
70 | {
|
---|
71 | uint8_t cw[16];
|
---|
72 | uint16_t caid;
|
---|
73 | uint32_t prid;
|
---|
74 | uint16_t srvid;
|
---|
75 | struct timeb first_recv_time; // time of first cw received
|
---|
76 | struct timeb upd_time; // updated time. Update time at each cw got
|
---|
77 | node ht_node;
|
---|
78 | node ll_node;
|
---|
79 | } CW_CACHE;
|
---|
80 |
|
---|
81 | typedef struct cw_cache_setting_t
|
---|
82 | {
|
---|
83 | int8_t mode;
|
---|
84 | uint16_t timediff_old_cw;
|
---|
85 | } CW_CACHE_SETTING;
|
---|
86 | #endif
|
---|
87 |
|
---|
88 | static pthread_rwlock_t cache_lock;
|
---|
89 | #ifdef CS_CACHEEX_AIO
|
---|
90 | static pthread_rwlock_t cw_cache_lock;
|
---|
91 | #endif
|
---|
92 | static hash_table ht_cache;
|
---|
93 | #ifdef CS_CACHEEX_AIO
|
---|
94 | static hash_table ht_cw_cache;
|
---|
95 | #endif
|
---|
96 | static list ll_cache;
|
---|
97 | #ifdef CS_CACHEEX_AIO
|
---|
98 | static list ll_cw_cache;
|
---|
99 | #endif
|
---|
100 | static int8_t cache_init_done = 0;
|
---|
101 |
|
---|
102 | #ifdef CS_CACHEEX_AIO
|
---|
103 | static int8_t cw_cache_init_done = 0;
|
---|
104 | static uint32_t lg_cache_size = 0;
|
---|
105 |
|
---|
106 | void init_cw_cache(void)
|
---|
107 | {
|
---|
108 | #ifdef CS_CACHEEX
|
---|
109 | if(cfg.cw_cache_size > 0 || cfg.cw_cache_memory > 0)
|
---|
110 | {
|
---|
111 | init_hash_table(&ht_cw_cache, &ll_cw_cache);
|
---|
112 | if (pthread_rwlock_init(&cw_cache_lock,NULL) != 0)
|
---|
113 | { cs_log("Error creating lock cw_cache_lock!"); }
|
---|
114 | else
|
---|
115 | { cw_cache_init_done = 1; }
|
---|
116 | }
|
---|
117 | #endif
|
---|
118 | }
|
---|
119 | #endif
|
---|
120 |
|
---|
121 | void init_cache(void)
|
---|
122 | {
|
---|
123 | init_hash_table(&ht_cache, &ll_cache);
|
---|
124 | if (pthread_rwlock_init(&cache_lock,NULL) != 0)
|
---|
125 | { cs_log("Error creating lock cache_lock!"); }
|
---|
126 | else
|
---|
127 | { cache_init_done = 1; }
|
---|
128 | }
|
---|
129 |
|
---|
130 | void free_cache(void)
|
---|
131 | {
|
---|
132 | cleanup_cache(true);
|
---|
133 | #ifdef CS_CACHEEX_AIO
|
---|
134 | cw_cache_cleanup(true);
|
---|
135 | ecm_cache_cleanup(true);
|
---|
136 | cw_cache_init_done = 0;
|
---|
137 | deinitialize_hash_table(&ht_cw_cache);
|
---|
138 | pthread_rwlock_destroy(&cw_cache_lock);
|
---|
139 | #endif
|
---|
140 | cache_init_done = 0;
|
---|
141 | deinitialize_hash_table(&ht_cache);
|
---|
142 | pthread_rwlock_destroy(&cache_lock);
|
---|
143 | }
|
---|
144 |
|
---|
145 | #ifdef CS_CACHEEX_AIO
|
---|
146 | uint32_t cache_size_lg(void)
|
---|
147 | {
|
---|
148 | if(!cache_init_done)
|
---|
149 | { return 0; }
|
---|
150 |
|
---|
151 | return lg_cache_size;
|
---|
152 | }
|
---|
153 | #endif
|
---|
154 |
|
---|
155 | uint32_t cache_size(void)
|
---|
156 | {
|
---|
157 | if(!cache_init_done)
|
---|
158 | { return 0; }
|
---|
159 |
|
---|
160 | return count_hash_table(&ht_cache);
|
---|
161 | }
|
---|
162 |
|
---|
163 | static uint8_t count_sort(CW *a, CW *b)
|
---|
164 | {
|
---|
165 | if (a->count == b->count) return 0;
|
---|
166 | return (a->count > b->count) ? -1 : 1; // DESC order by count
|
---|
167 | }
|
---|
168 |
|
---|
169 | #ifdef CS_CACHEEX_AIO
|
---|
170 | static uint8_t time_sort(CW_CACHE *a, CW_CACHE *b)
|
---|
171 | {
|
---|
172 | if (((int64_t)(a->upd_time.time) * 1000ull + (int64_t) a->upd_time.millitm) == ((int64_t)(b->upd_time.time) * 1000ull + (int64_t) b->upd_time.millitm)) return 0;
|
---|
173 | return (((int64_t)(a->upd_time.time) * 1000ull + (int64_t) a->upd_time.millitm) > ((int64_t)(b->upd_time.time) * 1000ull + (int64_t) b->upd_time.millitm)) ? -1 : 1;
|
---|
174 | }
|
---|
175 | #endif
|
---|
176 |
|
---|
177 | uint8_t check_is_pushed(void *cwp, struct s_client *cl)
|
---|
178 | {
|
---|
179 | struct s_pushclient *cl_tmp;
|
---|
180 | CW* cw = (CW*)cwp;
|
---|
181 | bool pushed=false;
|
---|
182 |
|
---|
183 | SAFE_RWLOCK_RDLOCK(&cw->pushout_client_lock);
|
---|
184 | for (cl_tmp = cw->pushout_client; cl_tmp; cl_tmp = cl_tmp->next_push)
|
---|
185 | {
|
---|
186 | if(cl_tmp->cl==cl)
|
---|
187 | {
|
---|
188 | pushed=true;
|
---|
189 | break;
|
---|
190 | }
|
---|
191 | }
|
---|
192 |
|
---|
193 | if(!pushed)
|
---|
194 | {
|
---|
195 | SAFE_RWLOCK_UNLOCK(&cw->pushout_client_lock);
|
---|
196 | SAFE_RWLOCK_WRLOCK(&cw->pushout_client_lock);
|
---|
197 |
|
---|
198 | struct s_pushclient *new_push_client;
|
---|
199 | if(cs_malloc(&new_push_client, sizeof(struct s_pushclient)))
|
---|
200 | {
|
---|
201 | new_push_client->cl=cl;
|
---|
202 |
|
---|
203 | new_push_client->next_push=cw->pushout_client;
|
---|
204 | cw->pushout_client=new_push_client;
|
---|
205 | }
|
---|
206 |
|
---|
207 | SAFE_RWLOCK_UNLOCK(&cw->pushout_client_lock);
|
---|
208 | return 0;
|
---|
209 | }
|
---|
210 | else
|
---|
211 | {
|
---|
212 | SAFE_RWLOCK_UNLOCK(&cw->pushout_client_lock);
|
---|
213 | return 1;
|
---|
214 | }
|
---|
215 | }
|
---|
216 |
|
---|
217 | uint8_t get_odd_even(ECM_REQUEST *er)
|
---|
218 | {
|
---|
219 | return (er->ecm[0] != 0x80 && er->ecm[0] != 0x81 ? 0 : er->ecm[0]);
|
---|
220 | }
|
---|
221 |
|
---|
222 |
|
---|
223 | CW *get_first_cw(ECMHASH *ecmhash, ECM_REQUEST *er)
|
---|
224 | {
|
---|
225 | if(!ecmhash) return NULL;
|
---|
226 |
|
---|
227 | node *j;
|
---|
228 | CW *cw;
|
---|
229 |
|
---|
230 | j = get_first_node_list(&ecmhash->ll_cw);
|
---|
231 | while (j) {
|
---|
232 | cw = get_data_from_node(j);
|
---|
233 |
|
---|
234 | if(cw && cw->odd_even == get_odd_even(er) && !cw->got_bad_cwc)
|
---|
235 | return cw;
|
---|
236 |
|
---|
237 | j = j->next;
|
---|
238 | }
|
---|
239 |
|
---|
240 | return NULL;
|
---|
241 | }
|
---|
242 |
|
---|
243 | int compare_csp_hash(const void *arg, const void *obj)
|
---|
244 | {
|
---|
245 | uint32_t h = ((const ECMHASH*)obj)->csp_hash;
|
---|
246 | return memcmp(arg, &h, 4);
|
---|
247 | }
|
---|
248 |
|
---|
249 | static int compare_cw(const void *arg, const void *obj)
|
---|
250 | {
|
---|
251 | return memcmp(arg, ((const CW*)obj)->cw, 16);
|
---|
252 | }
|
---|
253 |
|
---|
254 | #ifdef CS_CACHEEX_AIO
|
---|
255 | static int compare_cw_cache(const void *arg, const void *obj)
|
---|
256 | {
|
---|
257 | return memcmp(arg, ((const CW_CACHE*)obj)->cw, 16);
|
---|
258 | }
|
---|
259 | #endif
|
---|
260 |
|
---|
261 | static bool cwcycle_check_cache(struct s_client *cl, ECM_REQUEST *er, CW *cw)
|
---|
262 | {
|
---|
263 | (void)cl; (void)er; (void)cw;
|
---|
264 |
|
---|
265 | #ifdef CW_CYCLE_CHECK
|
---|
266 | if(cw->got_bad_cwc)
|
---|
267 | return 0;
|
---|
268 |
|
---|
269 | uint8_t cwc_ct = cw->cwc_cycletime > 0 ? cw->cwc_cycletime : 0;
|
---|
270 | uint8_t cwc_ncwc = cw->cwc_next_cw_cycle < 2 ? cw->cwc_next_cw_cycle : 2;
|
---|
271 | if(checkcwcycle(cl, er, NULL, cw->cw, 0, cwc_ct, cwc_ncwc) != 0)
|
---|
272 | {
|
---|
273 | cs_log_dbg(D_CWC | D_LB, "{client %s, caid %04X, srvid %04X} [check_cache] cyclecheck passed ecm in INT. cache.", (cl ? cl->account->usr : "-"), er->caid, er->srvid);
|
---|
274 | }
|
---|
275 | else
|
---|
276 | {
|
---|
277 | #ifdef CS_CACHEEX_AIO
|
---|
278 | if(!er->localgenerated)
|
---|
279 | {
|
---|
280 | #endif
|
---|
281 | cs_log_dbg(D_CWC, "cyclecheck [BAD CW Cycle] from Int. Cache detected.. {client %s, caid %04X, srvid %04X} [check_cache] -> skip cache answer", (cl ? cl->account->usr : "-"), er->caid, er->srvid);
|
---|
282 | cw->got_bad_cwc = 1; // no need to check it again
|
---|
283 | return 0;
|
---|
284 | #ifdef CS_CACHEEX_AIO
|
---|
285 | }
|
---|
286 | else
|
---|
287 | {
|
---|
288 | cs_log_dbg(D_CWC, "cyclecheck [BAD CW Cycle] from Int. Cache detected.. {client %s, caid %04X, srvid %04X} [check_cache] -> lg-flagged CW -> do nothing", (cl ? cl->account->usr : "-"), er->caid, er->srvid);
|
---|
289 | }
|
---|
290 | #endif
|
---|
291 | }
|
---|
292 | #endif
|
---|
293 | return 1;
|
---|
294 | }
|
---|
295 |
|
---|
296 | /*
|
---|
297 | * This function returns cw (mostly received) in cache for er, or NULL if not found.
|
---|
298 | * IMPORTANT:
|
---|
299 | * - If found, DON'T forget to free returned ecm, because it is a copy useful to get data
|
---|
300 | * - If found, and cacheex_src client of returned ecm is not NULL, and we want to access it,
|
---|
301 | * remember to check for its validity (client structure is still existent)
|
---|
302 | * E.g.: if(ecm->cacheex_src && is_valid_client(ecm->cacheex_src) && !ecm->cacheex_src->kill)
|
---|
303 | * We don't want make this stuff here to avoid useless cpu time if outside function we would not access to it.
|
---|
304 | */
|
---|
305 | struct ecm_request_t *check_cache(ECM_REQUEST *er, struct s_client *cl)
|
---|
306 | {
|
---|
307 | if(!cache_init_done || !er->csp_hash) return NULL;
|
---|
308 |
|
---|
309 | ECM_REQUEST *ecm = NULL;
|
---|
310 | ECMHASH *result;
|
---|
311 | CW *cw;
|
---|
312 | uint64_t grp = cl?cl->grp:0;
|
---|
313 |
|
---|
314 | SAFE_RWLOCK_RDLOCK(&cache_lock);
|
---|
315 |
|
---|
316 | result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(uint32_t),&compare_csp_hash);
|
---|
317 | cw = get_first_cw(result, er);
|
---|
318 | if (!cw)
|
---|
319 | goto out_err;
|
---|
320 |
|
---|
321 | if(cw->csp // csp have no grp!
|
---|
322 | || !grp // csp client(no grp) searching for cache
|
---|
323 | || (grp && cw->grp // ecm group --> only when readers/ex-clients answer (e_found) it
|
---|
324 | && (grp & cw->grp)))
|
---|
325 | {
|
---|
326 | #ifdef CS_CACHEEX
|
---|
327 | //if preferlocalcards=2 for this ecm request, we can server ONLY cw from localcards readers until stage<3
|
---|
328 | if(er->preferlocalcards==2 && !cw->localcards && er->stage<3){
|
---|
329 | goto out_err;
|
---|
330 | }
|
---|
331 |
|
---|
332 | CWCHECK check_cw = get_cwcheck(er);
|
---|
333 |
|
---|
334 | if((!cw->proxy && !cw->localcards) // cw received from ONLY cacheex/csp peers
|
---|
335 | && check_cw.counter>1
|
---|
336 | && cw->count < check_cw.counter
|
---|
337 | && (check_cw.mode == 1 || !er->cacheex_wait_time_expired))
|
---|
338 | {
|
---|
339 | goto out_err;
|
---|
340 | }
|
---|
341 |
|
---|
342 | #ifdef CS_CACHEEX_AIO
|
---|
343 | // client
|
---|
344 | if( cl && !cw->localgenerated
|
---|
345 | && !(chk_srvid_localgenerated_only_exception(er)) // service-based exception
|
---|
346 | && (cl->account->cacheex.localgenerated_only
|
---|
347 | || (chk_lg_only(er, &cl->account->cacheex.lg_only_tab))
|
---|
348 | ) // only lg-flagged CWs
|
---|
349 | )
|
---|
350 | {
|
---|
351 | goto out_err;
|
---|
352 | }
|
---|
353 | #endif
|
---|
354 | #endif
|
---|
355 |
|
---|
356 | if (!cwcycle_check_cache(cl, er, cw))
|
---|
357 | goto out_err;
|
---|
358 |
|
---|
359 | if (cs_malloc(&ecm, sizeof(ECM_REQUEST)))
|
---|
360 | {
|
---|
361 | ecm->rc = E_FOUND;
|
---|
362 | ecm->rcEx = 0;
|
---|
363 | memcpy(ecm->cw, cw->cw, 16);
|
---|
364 | ecm->grp = cw->grp;
|
---|
365 | ecm->selected_reader = cw->selected_reader;
|
---|
366 | ecm->cwc_cycletime = cw->cwc_cycletime;
|
---|
367 | ecm->cwc_next_cw_cycle = cw->cwc_next_cw_cycle;
|
---|
368 | ecm->cacheex_src = cw->cacheex_src;
|
---|
369 | #ifdef CS_CACHEEX_AIO
|
---|
370 | ecm->localgenerated = (cw->localgenerated) ? 1:0;
|
---|
371 | #endif
|
---|
372 | ecm->cw_count = cw->count;
|
---|
373 | }
|
---|
374 | }
|
---|
375 |
|
---|
376 | out_err:
|
---|
377 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
378 | return ecm;
|
---|
379 | }
|
---|
380 |
|
---|
381 | #ifdef CS_CACHEEX_AIO
|
---|
382 | uint16_t get_cacheex_nopushafter(ECM_REQUEST *er)
|
---|
383 | {
|
---|
384 | return caidvaluetab_get_value(&cfg.cacheex_nopushafter_tab, er->caid, 0);
|
---|
385 | }
|
---|
386 | #endif
|
---|
387 |
|
---|
388 | static void cacheex_cache_add(ECM_REQUEST *er, ECMHASH *result, CW *cw, bool add_new_cw)
|
---|
389 | {
|
---|
390 | (void)er; (void)result; (void)cw; (void)add_new_cw;
|
---|
391 | #ifdef CS_CACHEEX
|
---|
392 | er->cw_cache = cw;
|
---|
393 | cacheex_cache_push(er);
|
---|
394 |
|
---|
395 | // cacheex debug log lines and cw diff stuff
|
---|
396 | if(!check_client(er->cacheex_src))
|
---|
397 | return;
|
---|
398 |
|
---|
399 | #ifdef CS_CACHEEX_AIO
|
---|
400 | if (D_CACHEEX & cs_dblevel)
|
---|
401 | {
|
---|
402 | uint8_t remotenodeid[8];
|
---|
403 | cacheex_get_srcnodeid(er, remotenodeid);
|
---|
404 |
|
---|
405 | if(!add_new_cw)
|
---|
406 | {
|
---|
407 | debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s - hop %i %s, src-nodeid %" PRIu64 "X", buf, er->from_csp ? "csp" : username(er->cacheex_src), ll_count(er->csp_lastnodes), er->localgenerated ? "(lg)" : "", cacheex_node_id(remotenodeid));
|
---|
408 | return;
|
---|
409 | }
|
---|
410 |
|
---|
411 | debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s - hop %i %s, src-nodeid %" PRIu64 "X", buf, er->from_csp ? "csp" : username(er->cacheex_src), ll_count(er->csp_lastnodes), er->localgenerated ? "(lg)" : "", cacheex_node_id(remotenodeid));
|
---|
412 | }
|
---|
413 | else
|
---|
414 | {
|
---|
415 | #endif
|
---|
416 | if(!add_new_cw)
|
---|
417 | {
|
---|
418 | #ifdef CS_CACHEEX_AIO
|
---|
419 | debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s - hop %i %s", buf, er->from_csp ? "csp" : username(er->cacheex_src), ll_count(er->csp_lastnodes), er->localgenerated ? "(lg)" : "");
|
---|
420 | #else
|
---|
421 | debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src));
|
---|
422 | #endif
|
---|
423 | return;
|
---|
424 | }
|
---|
425 |
|
---|
426 | #ifdef CS_CACHEEX_AIO
|
---|
427 | debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s - hop %i %s", buf, er->from_csp ? "csp" : username(er->cacheex_src), ll_count(er->csp_lastnodes), er->localgenerated ? "(lg)" : "");
|
---|
428 | #else
|
---|
429 | debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src));
|
---|
430 | #endif
|
---|
431 |
|
---|
432 | #ifdef CS_CACHEEX_AIO
|
---|
433 | }
|
---|
434 | #endif
|
---|
435 |
|
---|
436 | CW *cw_first = get_first_cw(result, er);
|
---|
437 | if(!cw_first)
|
---|
438 | return;
|
---|
439 |
|
---|
440 | // compare er cw with mostly counted cached cw
|
---|
441 | if(memcmp(er->cw, cw_first->cw, sizeof(er->cw)) != 0)
|
---|
442 | {
|
---|
443 | er->cacheex_src->cwcacheexerrcw++;
|
---|
444 | if (er->cacheex_src->account)
|
---|
445 | er->cacheex_src->account->cwcacheexerrcw++;
|
---|
446 |
|
---|
447 | if (((0x0200| 0x0800) & cs_dblevel)) // avoid useless operations if debug is not enabled
|
---|
448 | {
|
---|
449 | char cw1[16*3+2], cw2[16*3+2];
|
---|
450 | cs_hexdump(0, er->cw, 16, cw1, sizeof(cw1));
|
---|
451 | cs_hexdump(0, cw_first->cw, 16, cw2, sizeof(cw2));
|
---|
452 |
|
---|
453 | char ip1[20]="", ip2[20]="";
|
---|
454 | if (check_client(er->cacheex_src))
|
---|
455 | cs_strncpy(ip1, cs_inet_ntoa(er->cacheex_src->ip), sizeof(ip1));
|
---|
456 | if (check_client(cw_first->cacheex_src))
|
---|
457 | cs_strncpy(ip2, cs_inet_ntoa(cw_first->cacheex_src->ip), sizeof(ip2));
|
---|
458 | else if (cw_first->selected_reader && check_client(cw_first->selected_reader->client))
|
---|
459 | cs_strncpy(ip2, cs_inet_ntoa(cw_first->selected_reader->client->ip), sizeof(ip2));
|
---|
460 |
|
---|
461 | #ifdef CS_CACHEEX_AIO
|
---|
462 | uint8_t remotenodeid[8];
|
---|
463 | cacheex_get_srcnodeid(er, remotenodeid);
|
---|
464 |
|
---|
465 | uint8_t fakeF0 = 0, offset = 0;
|
---|
466 |
|
---|
467 | if(get_odd_even(er) == 0x81)
|
---|
468 | offset = 8;
|
---|
469 |
|
---|
470 | if(
|
---|
471 | (cw_first->cw[7+offset] != 0x00 && er->cw[7+offset] != 0x00)
|
---|
472 | && (cw_first->cw[7+offset] ^ 0xF0) == er->cw[7+offset]
|
---|
473 | )
|
---|
474 | {
|
---|
475 | fakeF0 = 1;
|
---|
476 | }
|
---|
477 |
|
---|
478 | debug_ecm(D_CACHEEX| D_CSP, "WARNING: Different CWs %s from %s(%s)<>%s(%s): %s<>%s lg: %i<>%i, hop:%02i, src-nodeid: %" PRIu64 "X%s", buf,
|
---|
479 | #else
|
---|
480 | debug_ecm(D_CACHEEX| D_CSP, "WARNING: Different CWs %s from %s(%s)<>%s(%s): %s<>%s ", buf,
|
---|
481 | #endif
|
---|
482 | er->from_csp ? "csp" : username(er->cacheex_src), ip1,
|
---|
483 | check_client(cw_first->cacheex_src)?username(cw_first->cacheex_src):(cw_first->selected_reader?cw_first->selected_reader->label:"unknown/csp"), ip2,
|
---|
484 | #ifdef CS_CACHEEX_AIO
|
---|
485 | cw1, cw2, er->localgenerated, cw_first->localgenerated, er->csp_lastnodes ? ll_count(er->csp_lastnodes) : 0, er->csp_lastnodes ? cacheex_node_id(remotenodeid): 0, fakeF0 ? " [last byte xor 0xF0]" : "");
|
---|
486 | #else
|
---|
487 | cw1, cw2);
|
---|
488 | #endif
|
---|
489 | #ifdef WITH_DEBUG
|
---|
490 | if(cs_dblevel & D_CACHEEX)
|
---|
491 | {
|
---|
492 | LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
|
---|
493 | uint8_t *nodeid;
|
---|
494 | uint8_t hops = 0;
|
---|
495 | while((nodeid = ll_li_next(li)))
|
---|
496 | {
|
---|
497 | cs_log_dbg(D_CACHEEX, "Different CW-nodelist hop%02u: %" PRIu64 "X", ++hops, cacheex_node_id(nodeid));
|
---|
498 | }
|
---|
499 | ll_li_destroy(li);
|
---|
500 | }
|
---|
501 | #endif
|
---|
502 | }
|
---|
503 | }
|
---|
504 | #endif
|
---|
505 | }
|
---|
506 |
|
---|
507 | #ifdef CS_CACHEEX_AIO
|
---|
508 | CW_CACHE_SETTING get_cw_cache(ECM_REQUEST *er)
|
---|
509 | {
|
---|
510 | int32_t i, timediff_old_cw = 0;
|
---|
511 | int8_t mode = 0;
|
---|
512 |
|
---|
513 | for(i = 0; i < cfg.cw_cache_settings.cwchecknum; i++)
|
---|
514 | {
|
---|
515 | CWCHECKTAB_DATA *d = &cfg.cw_cache_settings.cwcheckdata[i];
|
---|
516 |
|
---|
517 | if(i == 0 && d->caid <= 0)
|
---|
518 | {
|
---|
519 | mode = d->mode;
|
---|
520 | timediff_old_cw = d->counter;
|
---|
521 | continue; //check other, only valid for unset
|
---|
522 | }
|
---|
523 |
|
---|
524 | if(d->caid == er->caid || d->caid == er->caid >> 8 || ((d->cmask >= 0 && (er->caid & d->cmask) == d->caid) || d->caid == -1))
|
---|
525 | {
|
---|
526 | if((d->prid >= 0 && d->prid == (int32_t)er->prid) || d->prid == -1)
|
---|
527 | {
|
---|
528 | if((d->srvid >= 0 && d->srvid == er->srvid) || d->srvid == -1)
|
---|
529 | {
|
---|
530 | mode = d->mode;
|
---|
531 | timediff_old_cw = d->counter;
|
---|
532 | break;
|
---|
533 | }
|
---|
534 | }
|
---|
535 | }
|
---|
536 | }
|
---|
537 |
|
---|
538 | //check for correct values
|
---|
539 | if(mode>3 || mode<0) mode=0;
|
---|
540 | if(timediff_old_cw<1) timediff_old_cw=0;
|
---|
541 |
|
---|
542 | CW_CACHE_SETTING cw_cache_setting;
|
---|
543 | memset(&cw_cache_setting, 0, sizeof(CW_CACHE_SETTING));
|
---|
544 | cw_cache_setting.mode = mode;
|
---|
545 | cw_cache_setting.timediff_old_cw = timediff_old_cw;
|
---|
546 |
|
---|
547 | return cw_cache_setting;
|
---|
548 | }
|
---|
549 |
|
---|
550 | static bool cw_cache_check(ECM_REQUEST *er)
|
---|
551 | {
|
---|
552 | if(cw_cache_init_done)
|
---|
553 | {
|
---|
554 | CW_CACHE_SETTING cw_cache_setting = get_cw_cache(er);
|
---|
555 | if(cw_cache_setting.mode > 0)
|
---|
556 | {
|
---|
557 | CW_CACHE *cw_cache = NULL;
|
---|
558 | SAFE_RWLOCK_WRLOCK(&cw_cache_lock);
|
---|
559 | cw_cache = find_hash_table(&ht_cw_cache, &er->cw, sizeof(er->cw), &compare_cw_cache);
|
---|
560 | // add cw to ht_cw_cache if < cw_cache_size
|
---|
561 | if(!cw_cache)
|
---|
562 | {
|
---|
563 | // cw_cache-size(count/memory) pre-check
|
---|
564 | if(
|
---|
565 | (cfg.cw_cache_size && (cfg.cw_cache_size > tommy_hashlin_count(&ht_cw_cache)))
|
---|
566 | || (cfg.cw_cache_memory && (cfg.cw_cache_memory*1024*1024 > (2 * tommy_hashlin_memory_usage(&ht_cw_cache))))
|
---|
567 | )
|
---|
568 | {
|
---|
569 | if(cs_malloc(&cw_cache, sizeof(CW_CACHE)))
|
---|
570 | {
|
---|
571 | memcpy(cw_cache->cw, er->cw, sizeof(er->cw));
|
---|
572 | cw_cache->caid = er->caid;
|
---|
573 | cw_cache->prid = er->prid;
|
---|
574 | cw_cache->srvid = er->srvid;
|
---|
575 | cs_ftime(&cw_cache->first_recv_time);
|
---|
576 | cs_ftime(&cw_cache->upd_time);
|
---|
577 |
|
---|
578 | tommy_hashlin_insert(&ht_cw_cache, &cw_cache->ht_node, cw_cache, tommy_hash_u32(0, &er->cw, sizeof(er->cw)));
|
---|
579 | tommy_list_insert_tail(&ll_cw_cache, &cw_cache->ll_node, cw_cache);
|
---|
580 |
|
---|
581 | SAFE_RWLOCK_UNLOCK(&cw_cache_lock);
|
---|
582 | return true;
|
---|
583 | }
|
---|
584 | else
|
---|
585 | {
|
---|
586 | SAFE_RWLOCK_UNLOCK(&cw_cache_lock);
|
---|
587 | cs_log("[cw_cache] ERROR: NO added HASH to cw_cache!!");
|
---|
588 | return false;
|
---|
589 | }
|
---|
590 | }
|
---|
591 | else
|
---|
592 | {
|
---|
593 | // clean cache call;
|
---|
594 | SAFE_RWLOCK_UNLOCK(&cw_cache_lock);
|
---|
595 | cw_cache_cleanup(false);
|
---|
596 | return false;
|
---|
597 | }
|
---|
598 | }
|
---|
599 | // cw found
|
---|
600 | else
|
---|
601 | {
|
---|
602 | char cw1[16*3+2];
|
---|
603 | char cw2[16*3+2];
|
---|
604 | int8_t drop_cw = 0;
|
---|
605 | int64_t gone_diff = 0;
|
---|
606 |
|
---|
607 | gone_diff = comp_timeb(&er->tps, &cw_cache->first_recv_time);
|
---|
608 |
|
---|
609 | if(D_CW_CACHE & cs_dblevel)
|
---|
610 | {
|
---|
611 | cs_hexdump(0, cw_cache->cw, 16, cw1, sizeof(cw1));
|
---|
612 | cs_hexdump(0, er->cw, 16, cw2, sizeof(cw2));
|
---|
613 | }
|
---|
614 |
|
---|
615 | if(cw_cache_setting.timediff_old_cw > 0 && gone_diff > cw_cache_setting.timediff_old_cw) // late (>cw_cache_setting.timediff_old_cw) cw incoming
|
---|
616 | {
|
---|
617 | // log every dupe cw
|
---|
618 | if(cs_dblevel & D_CW_CACHE)
|
---|
619 | {
|
---|
620 | uint8_t remotenodeid[8];
|
---|
621 | cacheex_get_srcnodeid(er, remotenodeid);
|
---|
622 | cs_log_dbg(D_CW_CACHE,"[dupe CW] cache: %04X:%06X:%04X:%s | in: %04X:%06X:%04X:%s | diff(now): %"PRIi64" ms > %"PRIu16" - %s - hop %i%s, src-nodeid %" PRIu64 "X", cw_cache->caid, cw_cache->prid, cw_cache->srvid, cw1, er->caid, er->prid, er->srvid, cw2, gone_diff, cw_cache_setting.timediff_old_cw, (er->selected_reader && cs_strlen(er->selected_reader->label)) ? er->selected_reader->label : username(er->cacheex_src), ll_count(er->csp_lastnodes), (er->localgenerated) ? " (lg)" : "", er->csp_lastnodes ? cacheex_node_id(remotenodeid): 0);
|
---|
623 | }
|
---|
624 |
|
---|
625 | if(cw_cache->srvid == er->srvid && cw_cache->caid == er->caid) // same cw for same caid&srvid
|
---|
626 | {
|
---|
627 | cs_ftime(&cw_cache->upd_time);
|
---|
628 | cs_log_dbg(D_CW_CACHE,"[late CW] cache: %04X:%06X:%04X:%s | in: %04X:%06X:%04X:%s | diff(now): %"PRIi64" ms > %"PRIu16" - %s - hop %i%s", cw_cache->caid, cw_cache->prid, cw_cache->srvid, cw1, er->caid, er->prid, er->srvid, cw2, gone_diff, cw_cache_setting.timediff_old_cw, (er->selected_reader && cs_strlen(er->selected_reader->label)) ? er->selected_reader->label : username(er->cacheex_src), ll_count(er->csp_lastnodes), (er->localgenerated) ? " (lg)" : "");
|
---|
629 | drop_cw=1;
|
---|
630 |
|
---|
631 | }
|
---|
632 | else if(cw_cache->srvid != er->srvid) // same cw for different srvid & late
|
---|
633 | {
|
---|
634 | cs_ftime(&cw_cache->upd_time);
|
---|
635 | cs_log_dbg(D_CW_CACHE,"[dupe&late CW] cache: %04X:%06X:%04X:%s | in: %04X:%06X:%04X:%s| diff(now): %"PRIi64" ms - %s - hop %i%s", cw_cache->caid, cw_cache->prid, cw_cache->srvid, cw1, er->caid, er->prid, er->srvid, cw2, gone_diff, (er->selected_reader && cs_strlen(er->selected_reader->label)) ? er->selected_reader->label : username(er->cacheex_src), ll_count(er->csp_lastnodes), (er->localgenerated) ? " (lg)" : "");
|
---|
636 | drop_cw = 1;
|
---|
637 | }
|
---|
638 | else if(gone_diff > 15000) // same cw later as 15 secs
|
---|
639 | {
|
---|
640 | #ifdef WITH_DEBUG
|
---|
641 | if(cs_dblevel & D_CW_CACHE)
|
---|
642 | {
|
---|
643 | uint8_t remotenodeid[8];
|
---|
644 | cacheex_get_srcnodeid(er, remotenodeid);
|
---|
645 | cs_log_dbg(D_CW_CACHE,"[late-15sec+ CW] cache: %04X:%06X:%04X:%s | in: %04X:%06X:%04X:%s | diff(now): %"PRIi64" ms > %"PRIu16" - %s - hop %i%s, src-nodeid %" PRIu64 "X", cw_cache->caid, cw_cache->prid, cw_cache->srvid, cw1, er->caid, er->prid, er->srvid, cw2, gone_diff, cw_cache_setting.timediff_old_cw, (er->selected_reader && cs_strlen(er->selected_reader->label)) ? er->selected_reader->label : username(er->cacheex_src), ll_count(er->csp_lastnodes), (er->localgenerated) ? " (lg)" : "", er->csp_lastnodes ? cacheex_node_id(remotenodeid): 0);
|
---|
646 | }
|
---|
647 | #endif
|
---|
648 | drop_cw = 1;
|
---|
649 | }
|
---|
650 |
|
---|
651 | if(cw_cache_setting.mode > 1 && drop_cw)
|
---|
652 | {
|
---|
653 | // cw_cache->drop_count++;
|
---|
654 | cs_log_dbg(D_CW_CACHE,"incoming CW dropped - current cw_cache_size: %i - cw_cache-mem-size: %iMiB", count_hash_table(&ht_cw_cache), 2*(int)tommy_hashlin_memory_usage(&ht_cw_cache)/1024/1024);
|
---|
655 | SAFE_RWLOCK_UNLOCK(&cw_cache_lock);
|
---|
656 | return false;
|
---|
657 | }
|
---|
658 | }
|
---|
659 | }
|
---|
660 |
|
---|
661 | SAFE_RWLOCK_UNLOCK(&cw_cache_lock);
|
---|
662 | return true;
|
---|
663 | }
|
---|
664 | }
|
---|
665 | else
|
---|
666 | {
|
---|
667 | cs_log_dbg(D_CW_CACHE,"[cw_cache] cw_cache_init_done %i cfg.cw_cache_size: %u cfg.cw_cache_memory %u", cw_cache_init_done, cfg.cw_cache_size, cfg.cw_cache_memory);
|
---|
668 | return true;
|
---|
669 | }
|
---|
670 | return true;
|
---|
671 | }
|
---|
672 | #endif
|
---|
673 |
|
---|
674 | void add_cache(ECM_REQUEST *er)
|
---|
675 | {
|
---|
676 | if(!cache_init_done || !er->csp_hash) return;
|
---|
677 | #ifdef CS_CACHEEX_AIO
|
---|
678 | // cw_cache_check
|
---|
679 | if(!cw_cache_check(er))
|
---|
680 | {
|
---|
681 | return;
|
---|
682 | }
|
---|
683 | #endif
|
---|
684 | ECMHASH *result = NULL;
|
---|
685 | CW *cw = NULL;
|
---|
686 | bool add_new_cw=false;
|
---|
687 |
|
---|
688 | SAFE_RWLOCK_WRLOCK(&cache_lock);
|
---|
689 |
|
---|
690 | // add csp_hash to cache
|
---|
691 | result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(uint32_t), &compare_csp_hash);
|
---|
692 | if(!result)
|
---|
693 | {
|
---|
694 | if(cs_malloc(&result, sizeof(ECMHASH)))
|
---|
695 | {
|
---|
696 | result->csp_hash = er->csp_hash;
|
---|
697 | init_hash_table(&result->ht_cw, &result->ll_cw);
|
---|
698 | cs_ftime(&result->first_recv_time);
|
---|
699 | add_hash_table(&ht_cache, &result->ht_node, &ll_cache, &result->ll_node, result, &result->csp_hash, sizeof(uint32_t));
|
---|
700 | }
|
---|
701 | else
|
---|
702 | {
|
---|
703 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
704 | cs_log("ERROR: NO added HASH to cache!!");
|
---|
705 | return;
|
---|
706 | }
|
---|
707 | }
|
---|
708 |
|
---|
709 | cs_ftime(&result->upd_time); // need to be updated at each cw! We use it for deleting this hash when no more cws arrive inside max_cache_time!
|
---|
710 |
|
---|
711 | //add cw to this csp hash
|
---|
712 | cw = find_hash_table(&result->ht_cw, er->cw, sizeof(er->cw), &compare_cw);
|
---|
713 |
|
---|
714 | if(!cw)
|
---|
715 | {
|
---|
716 | if(count_hash_table(&result->ht_cw) >= 10) // max 10 different cws stored
|
---|
717 | {
|
---|
718 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
719 | return;
|
---|
720 | }
|
---|
721 |
|
---|
722 | while(1)
|
---|
723 | {
|
---|
724 | if(cs_malloc(&cw, sizeof(CW)))
|
---|
725 | {
|
---|
726 | memcpy(cw->cw, er->cw, sizeof(er->cw));
|
---|
727 | cw->odd_even = get_odd_even(er);
|
---|
728 | cw->cwc_cycletime = er->cwc_cycletime;
|
---|
729 | cw->cwc_next_cw_cycle = er->cwc_next_cw_cycle;
|
---|
730 | cw->count= 0;
|
---|
731 | cw->csp = 0;
|
---|
732 | cw->cacheex = 0;
|
---|
733 | cw->localcards=0;
|
---|
734 | cw->proxy=0;
|
---|
735 | cw->grp = 0;
|
---|
736 | cw->caid = er->caid;
|
---|
737 | cw->prid = er->prid;
|
---|
738 | cw->srvid = er->srvid;
|
---|
739 | cw->selected_reader=er->selected_reader;
|
---|
740 | cw->cacheex_src=er->cacheex_src;
|
---|
741 | cw->pushout_client = NULL;
|
---|
742 |
|
---|
743 | while(1)
|
---|
744 | {
|
---|
745 | if (pthread_rwlock_init(&cw->pushout_client_lock, NULL) == 0)
|
---|
746 | break;
|
---|
747 |
|
---|
748 | cs_log("Error creating lock pushout_client_lock!");
|
---|
749 | cs_sleepms(1);
|
---|
750 | }
|
---|
751 |
|
---|
752 | add_hash_table(&result->ht_cw, &cw->ht_node, &result->ll_cw, &cw->ll_node, cw, cw->cw, sizeof(er->cw));
|
---|
753 | add_new_cw=true;
|
---|
754 | break;
|
---|
755 | }
|
---|
756 |
|
---|
757 | cs_log("ERROR: NO added CW to cache!! Re-trying...");
|
---|
758 | cs_sleepms(1);
|
---|
759 | }
|
---|
760 | }
|
---|
761 |
|
---|
762 | // update if answered from csp/cacheex/local_proxy
|
---|
763 | if(er->from_cacheex) cw->cacheex = 1;
|
---|
764 | if(er->from_csp) cw->csp = 1;
|
---|
765 | if(!er->cacheex_src)
|
---|
766 | {
|
---|
767 | if(is_localreader(er->selected_reader, er)) cw->localcards=1;
|
---|
768 | else cw->proxy = 1;
|
---|
769 | }
|
---|
770 |
|
---|
771 | #ifdef CS_CACHEEX_AIO
|
---|
772 | // copy flag for local generated CW
|
---|
773 | if(er->localgenerated || (er->selected_reader && !is_network_reader(er->selected_reader)))
|
---|
774 | {
|
---|
775 | cw->localgenerated = 1;
|
---|
776 | er->localgenerated = 1;
|
---|
777 | // to favorite CWs with this flag while sorting
|
---|
778 | if(cw->count < 0x0F000000)
|
---|
779 | {
|
---|
780 | cw->count |= 0x0F000000;
|
---|
781 | lg_cache_size++;
|
---|
782 | }
|
---|
783 | }
|
---|
784 | else
|
---|
785 | {
|
---|
786 | cw->localgenerated = 0;
|
---|
787 | }
|
---|
788 | #endif
|
---|
789 |
|
---|
790 | // always update group and counter
|
---|
791 | cw->grp |= er->grp;
|
---|
792 | cw->count++;
|
---|
793 |
|
---|
794 | #ifdef CS_CACHEEX_AIO
|
---|
795 | // add count to er for checking @ cacheex_push
|
---|
796 | er->cw_count += cw->count;
|
---|
797 | #endif
|
---|
798 | // sort cw_list by counter (DESC order)
|
---|
799 | if(cw->count>1)
|
---|
800 | sort_list(&result->ll_cw, count_sort);
|
---|
801 |
|
---|
802 | #ifdef CS_CACHEEX_AIO
|
---|
803 | // dont push not flagged CWs - global
|
---|
804 | if(!er->localgenerated &&
|
---|
805 | (
|
---|
806 | !chk_srvid_localgenerated_only_exception(er)
|
---|
807 | && (cfg.cacheex_localgenerated_only || chk_lg_only(er, &cfg.cacheex_lg_only_tab))
|
---|
808 | ) )
|
---|
809 | {
|
---|
810 | cs_log_dbg(D_CACHEEX, "cacheex: push denied, cacheex_localgenerated_only->global");
|
---|
811 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
812 | return;
|
---|
813 | }
|
---|
814 |
|
---|
815 | // dont push CW if time for caid > x && from local reader | proxy
|
---|
816 | if(er->rc < 3 && er->ecm_time && get_cacheex_nopushafter(er) != 0 &&(get_cacheex_nopushafter(er) < er->ecm_time ))
|
---|
817 | {
|
---|
818 | cs_log_dbg(D_CACHEEX, "cacheex: push denied, cacheex_nopushafter %04X:%u < %i, reader: %s", er->caid, get_cacheex_nopushafter(er), er->ecm_time, er->selected_reader->label);
|
---|
819 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
820 | return;
|
---|
821 | }
|
---|
822 |
|
---|
823 | // no cacheex-push on diff-cw's if no localgenerated flag exist
|
---|
824 | if(cfg.cacheex_dropdiffs && (count_hash_table(&result->ht_cw) > 1) && !er->localgenerated)
|
---|
825 | {
|
---|
826 | cs_log_dbg(D_CACHEEX,"cacheex: diff CW - cacheex push denied src: %s", er->selected_reader->label);
|
---|
827 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
828 | return;
|
---|
829 | }
|
---|
830 | #endif
|
---|
831 |
|
---|
832 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
833 |
|
---|
834 | cacheex_cache_add(er, result, cw, add_new_cw);
|
---|
835 | }
|
---|
836 |
|
---|
837 | #ifdef CS_CACHEEX_AIO
|
---|
838 | void cw_cache_cleanup(bool force)
|
---|
839 | {
|
---|
840 | if(!cw_cache_init_done)
|
---|
841 | { return; }
|
---|
842 |
|
---|
843 | SAFE_RWLOCK_WRLOCK(&cw_cache_lock);
|
---|
844 |
|
---|
845 | CW_CACHE *cw_cache;
|
---|
846 | node *i, *i_next;
|
---|
847 |
|
---|
848 | uint32_t ll_c = 0;
|
---|
849 | uint32_t ll_ten_percent = (uint)tommy_list_count(&ll_cw_cache)*0.1; // 10 percent of cache
|
---|
850 |
|
---|
851 | if(!force)
|
---|
852 | sort_list(&ll_cw_cache, time_sort);
|
---|
853 |
|
---|
854 | i = get_first_node_list(&ll_cw_cache);
|
---|
855 | while(i)
|
---|
856 | {
|
---|
857 | i_next = i->next;
|
---|
858 |
|
---|
859 | cw_cache = get_data_from_node(i);
|
---|
860 |
|
---|
861 | if(!cw_cache)
|
---|
862 | {
|
---|
863 | i = i_next;
|
---|
864 | continue;
|
---|
865 | }
|
---|
866 | if(!force)
|
---|
867 | {
|
---|
868 | ++ll_c;
|
---|
869 |
|
---|
870 | if(ll_c < ll_ten_percent)
|
---|
871 | {
|
---|
872 | remove_elem_list(&ll_cw_cache, &cw_cache->ll_node);
|
---|
873 | remove_elem_hash_table(&ht_cw_cache, &cw_cache->ht_node);
|
---|
874 | NULLFREE(cw_cache);
|
---|
875 | }
|
---|
876 | else{
|
---|
877 | break;
|
---|
878 | }
|
---|
879 | }
|
---|
880 | else
|
---|
881 | {
|
---|
882 | remove_elem_list(&ll_cw_cache, &cw_cache->ll_node);
|
---|
883 | remove_elem_hash_table(&ht_cw_cache, &cw_cache->ht_node);
|
---|
884 | NULLFREE(cw_cache);
|
---|
885 | }
|
---|
886 |
|
---|
887 | i = i_next;
|
---|
888 | }
|
---|
889 |
|
---|
890 | SAFE_RWLOCK_UNLOCK(&cw_cache_lock);
|
---|
891 | }
|
---|
892 | #endif
|
---|
893 |
|
---|
894 | void cleanup_cache(bool force)
|
---|
895 | {
|
---|
896 | ECMHASH *ecmhash;
|
---|
897 | CW *cw;
|
---|
898 | struct s_pushclient *pc, *nxt;
|
---|
899 | node *i,*i_next,*j,*j_next;
|
---|
900 |
|
---|
901 | struct timeb now;
|
---|
902 | int64_t gone_first, gone_upd;
|
---|
903 |
|
---|
904 | if(!cache_init_done)
|
---|
905 | { return; }
|
---|
906 |
|
---|
907 | SAFE_RWLOCK_WRLOCK(&cache_lock);
|
---|
908 |
|
---|
909 | i = get_first_node_list(&ll_cache);
|
---|
910 | while(i)
|
---|
911 | {
|
---|
912 | i_next = i->next;
|
---|
913 | ecmhash = get_data_from_node(i);
|
---|
914 |
|
---|
915 | if(!ecmhash)
|
---|
916 | {
|
---|
917 | i = i_next;
|
---|
918 | continue;
|
---|
919 | }
|
---|
920 |
|
---|
921 | cs_ftime(&now);
|
---|
922 | gone_first = comp_timeb(&now, &ecmhash->first_recv_time);
|
---|
923 | gone_upd = comp_timeb(&now, &ecmhash->upd_time);
|
---|
924 |
|
---|
925 | if(!force && gone_first<=(cfg.max_cache_time*1000)) // not continue, useless check for nexts one!
|
---|
926 | {
|
---|
927 | break;
|
---|
928 | }
|
---|
929 |
|
---|
930 | if(force || gone_upd>(cfg.max_cache_time*1000))
|
---|
931 | {
|
---|
932 | j = get_first_node_list(&ecmhash->ll_cw);
|
---|
933 | while(j)
|
---|
934 | {
|
---|
935 | j_next = j->next;
|
---|
936 | cw = get_data_from_node(j);
|
---|
937 | if(cw)
|
---|
938 | {
|
---|
939 | pthread_rwlock_destroy(&cw->pushout_client_lock);
|
---|
940 | pc = cw->pushout_client;
|
---|
941 | cw->pushout_client=NULL;
|
---|
942 | while(pc)
|
---|
943 | {
|
---|
944 | nxt = pc->next_push;
|
---|
945 | NULLFREE(pc);
|
---|
946 | pc = nxt;
|
---|
947 | }
|
---|
948 | #ifdef CS_CACHEEX_AIO
|
---|
949 | if(cw->count >= 0x0F000000)
|
---|
950 | {
|
---|
951 | lg_cache_size--;
|
---|
952 | }
|
---|
953 | #endif
|
---|
954 | remove_elem_list(&ecmhash->ll_cw, &cw->ll_node);
|
---|
955 | remove_elem_hash_table(&ecmhash->ht_cw, &cw->ht_node);
|
---|
956 | NULLFREE(cw);
|
---|
957 | }
|
---|
958 | j = j_next;
|
---|
959 | }
|
---|
960 |
|
---|
961 | deinitialize_hash_table(&ecmhash->ht_cw);
|
---|
962 | remove_elem_list(&ll_cache, &ecmhash->ll_node);
|
---|
963 | remove_elem_hash_table(&ht_cache, &ecmhash->ht_node);
|
---|
964 | NULLFREE(ecmhash);
|
---|
965 | }
|
---|
966 | i = i_next;
|
---|
967 | }
|
---|
968 | SAFE_RWLOCK_UNLOCK(&cache_lock);
|
---|
969 | }
|
---|
970 |
|
---|
971 | #ifdef CS_CACHEEX_AIO
|
---|
972 | void cacheex_get_srcnodeid(ECM_REQUEST *er, uint8_t *remotenodeid)
|
---|
973 | {
|
---|
974 | uint8_t *data;
|
---|
975 | data = ll_last_element(er->csp_lastnodes);
|
---|
976 | if(data)
|
---|
977 | {
|
---|
978 | memcpy(remotenodeid, data, 8);
|
---|
979 | }
|
---|
980 | else
|
---|
981 | {
|
---|
982 | memset(remotenodeid, 0 , 8);
|
---|
983 | }
|
---|
984 | }
|
---|
985 | #endif
|
---|