static void cacheex_del_hitcache(struct s_client *cl, ECM_REQUEST *er) { HIT_KEY search; CACHE_HIT *result; memset(&search, 0, sizeof(HIT_KEY)); search.caid = er->caid; search.prid = er->prid; search.srvid = er->srvid; if(cl && cl->grp) { result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey); while(result) { result->grp &= ~cl->grp; result->grp_last_max_hitcache_time &= ~cl->grp; result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey); } } SAFE_RWLOCK_WRLOCK(&hitcache_lock); search_remove_elem_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey); SAFE_RWLOCK_UNLOCK(&hitcache_lock); }
/* this function shouldn't be called from irq */ u32 hash_entry_find(int hashd, u32 hash_key) { struct hash_table_s *hash_table_ptr; struct hash_entry_s *hash_entry; u32 pseudo_key = 0; int loops; spin_lock(&hash_table_ptr->hash_lock); hash_table_ptr = find_hash_table(hashd); if (!hash_table_ptr->max_entries) return -1; hash_entry = hash_table_ptr->hash_entry; pseudo_key = hash_math_pseudo(hash_table_ptr, hash_key) % hash_table_ptr->max_entries; loops = 0; do { if (hash_entry[pseudo_key].hash_key != hash_key) pseudo_key = (pseudo_key + 1) % hash_table_ptr->max_entries; else { spin_unlock(&hash_table_ptr->hash_lock); return hash_entry[pseudo_key].hash_addr; } loops++; } while(loops < hash_table_ptr->max_entries); spin_unlock(&hash_table_ptr->hash_lock); return 0; }
static int32_t cacheex_check_hitcache(ECM_REQUEST *er, struct s_client *cl) { CACHE_HIT *result; HIT_KEY search; memset(&search, 0, sizeof(HIT_KEY)); search.caid = er->caid; search.prid = er->prid; search.srvid = er->srvid; SAFE_RWLOCK_RDLOCK(&hitcache_lock); result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey); if(result){ struct timeb now; cs_ftime(&now); int64_t gone = comp_timeb(&now, &result->time); uint64_t grp = cl?cl->grp:0; if( gone <= (cfg.max_hitcache_time*1000) && (!grp || !result->grp || (grp & result->grp)) ) { SAFE_RWLOCK_UNLOCK(&hitcache_lock); return 1; } } SAFE_RWLOCK_UNLOCK(&hitcache_lock); return 0; }
void hash_count_entries(int hashd) { struct hash_table_s *hash_table_ptr; hash_table_ptr = find_hash_table(hashd); printk("hash_ptr %x\n", hash_table_ptr); printk("hash_max_entries %x\n", hash_table_ptr->max_entries); printk("hash_cur_entries %x\n", hash_table_ptr->cur_entries); }
int unregister_hash_table(int hashd) { struct hash_table_s *hash_table_ptr; hash_table_ptr = find_hash_table(hashd); if (hash_table_ptr) { put_free_pages((u32)hash_table_ptr->hash_entry, (u8)(hash_table_ptr->page_order)); put_free_pages((u32)hash_table_ptr, 0); } return 0; }
static void cacheex_add_hitcache(struct s_client *cl, ECM_REQUEST *er) { if (!cfg.max_hitcache_time) // we don't want check/save hitcache return; if (!cfg.cacheex_wait_timetab.cevnum) return; uint32_t cacheex_wait_time = get_cacheex_wait_time(er,NULL); if (!cacheex_wait_time) return; CACHE_HIT *result; HIT_KEY search; memset(&search, 0, sizeof(HIT_KEY)); search.caid = er->caid; search.prid = er->prid; search.srvid = er->srvid; SAFE_RWLOCK_WRLOCK(&hitcache_lock); result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey); if(!result) // not found, add it! { if(cs_malloc(&result, sizeof(CACHE_HIT))) { memset(result, 0, sizeof(CACHE_HIT)); result->key.caid = er->caid; result->key.prid = er->prid; result->key.srvid = er->srvid; cs_ftime(&result->max_hitcache_time); add_hash_table(&ht_hitcache, &result->ht_node, &ll_hitcache, &result->ll_node, result, &result->key, sizeof(HIT_KEY)); } } if(result) { if(cl) { result->grp |= cl->grp; result->grp_last_max_hitcache_time |= cl->grp; } cs_ftime(&result->time); //always update time; } SAFE_RWLOCK_UNLOCK(&hitcache_lock); }
void add_hitcache(struct s_client *cl, ECM_REQUEST *er) { if (!cfg.max_hitcache_time) //we don't want check/save hitcache return; if (!cfg.cacheex_wait_timetab.n) return; uint32_t cacheex_wait_time = get_cacheex_wait_time(er,NULL); if (!cacheex_wait_time) return; CACHE_HIT *result; HIT_KEY search; memset(&search, 0, sizeof(HIT_KEY)); search.caid = er->caid; search.prid = er->prid; search.srvid = er->srvid; pthread_rwlock_wrlock(&hitcache_lock); result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &compare_hitkey); if(!result){ //not found, add it! if(cs_malloc(&result, sizeof(CACHE_HIT))){ memset(result, 0, sizeof(CACHE_HIT)); result->key.caid = er->caid; result->key.prid = er->prid; result->key.srvid = er->srvid; add_hash_table(&ht_hitcache, &result->ht_node, &ll_hitcache, &result->ll_node, result, &result->key, sizeof(HIT_KEY)); } } if(result){ if(cl) result->grp |= cl->grp; cs_ftime(&result->time); //always update time; } pthread_rwlock_unlock(&hitcache_lock); }
int hash_entry_add(int hashd, u32 hash_key, u32 hash_addr) { struct hash_table_s *hash_table_ptr; struct hash_entry_s *hash_entry; u32 pseudo_key = 0; int loops; spin_lock(&hash_table_ptr->hash_lock); hash_table_ptr = find_hash_table(hashd); if (!hash_table_ptr->max_entries) return -1; hash_entry = hash_table_ptr->hash_entry; pseudo_key = hash_math_pseudo(hash_table_ptr, hash_key) % hash_table_ptr->max_entries; loops = 0; do { if (hash_entry[pseudo_key].hash_key != FREE_PSEUDO_KEY) { pseudo_key = (pseudo_key + 1) % hash_table_ptr->max_entries; } else { hash_entry[pseudo_key].hash_key = hash_key; hash_entry[pseudo_key].hash_addr = hash_addr; hash_table_ptr->cur_entries++; spin_unlock(&hash_table_ptr->hash_lock); return 0; } loops++; } while(loops < hash_table_ptr->max_entries); spin_unlock(&hash_table_ptr->hash_lock); return -1; }
void add_cache(ECM_REQUEST *er){ if(!er->csp_hash) return; ECMHASH *result = NULL; CW *cw = NULL; #ifdef CS_CACHEEX bool add_new_cw=false; #endif pthread_rwlock_wrlock(&cache_lock); //add csp_hash to cache result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t), &compare_csp_hash); if(!result){ if(cs_malloc(&result, sizeof(ECMHASH))){ result->csp_hash = er->csp_hash; init_hash_table(&result->ht_cw, &result->ll_cw); cs_ftime(&result->first_recv_time); add_hash_table(&ht_cache, &result->ht_node, &ll_cache, &result->ll_node, result, &result->csp_hash, sizeof(int32_t)); }else{ pthread_rwlock_unlock(&cache_lock); cs_log("ERROR: NO added HASH to cache!!"); return; } } 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! //add cw to this csp hash cw = find_hash_table(&result->ht_cw, er->cw, sizeof(er->cw), &compare_cw); if(!cw){ if(count_hash_table(&result->ht_cw)>=10){ //max 10 different cws stored pthread_rwlock_unlock(&cache_lock); return; } while(1){ if(cs_malloc(&cw, sizeof(CW))){ memcpy(cw->cw, er->cw, sizeof(er->cw)); cw->odd_even = get_odd_even(er); cw->cwc_cycletime = er->cwc_cycletime; cw->cwc_next_cw_cycle = er->cwc_next_cw_cycle; cw->count= 0; cw->csp = 0; cw->cacheex = 0; cw->localcards=0; cw->proxy=0; cw->grp = 0; cw->caid = er->caid; cw->prid = er->prid; cw->srvid = er->srvid; cw->selected_reader=er->selected_reader; #ifdef CS_CACHEEX cw->cacheex_src=er->cacheex_src; #endif cw->pushout_client = NULL; while(1){ if (pthread_rwlock_init(&cw->pushout_client_lock, NULL) == 0) break; cs_log("Error creating lock pushout_client_lock!"); cs_sleepms(1); } add_hash_table(&result->ht_cw, &cw->ht_node, &result->ll_cw, &cw->ll_node, cw, cw->cw, sizeof(er->cw)); #ifdef CS_CACHEEX add_new_cw=true; #endif break; } cs_log("ERROR: NO added CW to cache!! Re-trying..."); cs_sleepms(1); } } //update if answered from csp/cacheex/local_proxy if(er->from_cacheex) cw->cacheex = 1; if(er->from_csp) cw->csp = 1; #ifdef CS_CACHEEX if(!er->cacheex_src){ #endif if(is_localreader(er->selected_reader, er)) cw->localcards=1; else cw->proxy = 1; #ifdef CS_CACHEEX } #endif //always update group and counter cw->grp |= er->grp; cw->count++; //sort cw_list by counter (DESC order) if(cw->count>1) sort_list(&result->ll_cw, count_sort); pthread_rwlock_unlock(&cache_lock); #ifdef CS_CACHEEX er->cw_cache=cw; cacheex_cache_push(er); //cacheex debug log lines and cw diff stuff if(check_client(er->cacheex_src)){ if(add_new_cw){ debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src)); CW *cw_first = get_first_cw(result, er); if(er && cw_first){ //compare er cw with mostly counted cached cw if(memcmp(er->cw, cw_first->cw, sizeof(er->cw)) != 0) { er->cacheex_src->cwcacheexerrcw++; if (er->cacheex_src->account) er->cacheex_src->account->cwcacheexerrcw++; if (((0x0200| 0x0800) & cs_dblevel)) { //avoid useless operations if debug is not enabled char cw1[16*3+2], cw2[16*3+2]; cs_hexdump(0, er->cw, 16, cw1, sizeof(cw1)); cs_hexdump(0, cw_first->cw, 16, cw2, sizeof(cw2)); char ip1[20]="", ip2[20]=""; if (check_client(er->cacheex_src)) cs_strncpy(ip1, cs_inet_ntoa(er->cacheex_src->ip), sizeof(ip1)); if (check_client(cw_first->cacheex_src)) cs_strncpy(ip2, cs_inet_ntoa(cw_first->cacheex_src->ip), sizeof(ip2)); else if (cw_first->selected_reader && check_client(cw_first->selected_reader->client)) cs_strncpy(ip2, cs_inet_ntoa(cw_first->selected_reader->client->ip), sizeof(ip2)); debug_ecm(D_CACHEEX| D_CSP, "WARNING: Different CWs %s from %s(%s)<>%s(%s): %s<>%s ", buf, er->from_csp ? "csp" : username(er->cacheex_src), ip1, check_client(cw_first->cacheex_src)?username(cw_first->cacheex_src):(cw_first->selected_reader?cw_first->selected_reader->label:"unknown/csp"), ip2, cw1, cw2); } } } }else debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src)); } #endif }
/* * This function returns cw (mostly received) in cache for er, or NULL if not found. * IMPORTANT: * - If found, DON'T forget to free returned ecm, because it is a copy useful to get data * - If found, and cacheex_src client of returned ecm is not NULL, and we want to access it, * remember to check for its validity (client structure is still existent) * E.g.: if(ecm->cacheex_src && is_valid_client(ecm->cacheex_src) && !ecm->cacheex_src->kill) * We don't want make this stuff here to avoid useless cpu time if outside function we would not access to it. */ struct ecm_request_t *check_cache(ECM_REQUEST *er, struct s_client *cl) { if(!er->csp_hash) return NULL; ECM_REQUEST *ecm = NULL; ECMHASH *result; CW *cw; uint64_t grp = cl?cl->grp:0; pthread_rwlock_rdlock(&cache_lock); result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t),&compare_csp_hash); cw = get_first_cw(result, er); if( cw && ( cw->csp //csp have no grp! || !grp //csp client(no grp) searching for cache || ( grp && cw->grp //ecm group --> only when readers/ex-clients answer (e_found) it && (grp & cw->grp) ) ) ){ #ifdef CS_CACHEEX //if preferlocalcards=2 for this ecm request, we can server ONLY cw from localcards readers until stage<3 if(er->preferlocalcards==2 && !cw->localcards && er->stage<3){ pthread_rwlock_unlock(&cache_lock); return NULL; } CWCHECK check_cw = get_cwcheck(er); if((!cw->proxy && !cw->localcards) //cw received from ONLY cacheex/csp peers && check_cw.counter>1 && cw->count < check_cw.counter && (check_cw.mode || !er->cacheex_wait_time_expired) ){ pthread_rwlock_unlock(&cache_lock); return NULL; } #endif #ifdef CW_CYCLE_CHECK uint8_t cwc_ct = cw->cwc_cycletime > 0 ? cw->cwc_cycletime : 0; uint8_t cwc_ncwc = cw->cwc_next_cw_cycle < 2 ? cw->cwc_next_cw_cycle : 2; if(cw->got_bad_cwc) { pthread_rwlock_unlock(&cache_lock); return NULL; } if(checkcwcycle(cl, er, NULL, cw->cw, 0, cwc_ct, cwc_ncwc) != 0){ cs_debug_mask(D_CWC | D_LB, "{client %s, caid %04X, srvid %04X} [check_cache] cyclecheck passed ecm in INT. cache, ecm->rc %d", (cl ? cl->account->usr : "******"), er->caid, er->srvid, ecm ? ecm->rc : -1); }else{ cs_debug_mask(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); cw->got_bad_cwc = 1; // no need to check it again pthread_rwlock_unlock(&cache_lock); return NULL; } #endif if (cs_malloc(&ecm, sizeof(ECM_REQUEST))){ ecm->rc = E_FOUND; ecm->rcEx = 0; memcpy(ecm->cw, cw->cw, 16); ecm->grp = cw->grp; ecm->selected_reader = cw->selected_reader; ecm->cwc_cycletime = cw->cwc_cycletime; ecm->cwc_next_cw_cycle = cw->cwc_next_cw_cycle; #ifdef CS_CACHEEX ecm->cacheex_src = cw->cacheex_src; #endif ecm->cw_count = cw->count; } } pthread_rwlock_unlock(&cache_lock); return ecm; }