void constant_insert(long ins, long get) { long t; int ret; alignhash_t(myhash) *my = alignhash_init(myhash); if (my == NULL) { fprintf(stderr, "alloc failed\n"); return; } for (t = 0; t < ins; t++) { ah_iter_t itr = alignhash_set(myhash, my, myrand(), &ret); if (alignhash_end(my) != itr) alignhash_value(my, itr) = t; counter++; } printf("insertion done\n"); for (t = 0; t < get; t++) { alignhash_get(myhash, my, myrand()); counter++; } alignhash_destroy(myhash, my); printf("all done\n"); }
nxweb_result nxweb_cache_try(nxweb_http_server_connection* conn, nxweb_http_response* resp, const char* key, time_t if_modified_since, time_t revalidated_mtime) { if (*key==' ' || *key=='*') return NXWEB_MISS; // not implemented yet nxe_time_t loop_time=nxweb_get_loop_time(conn); ah_iter_t ci; //nxweb_log_error("trying cache for %s", fpath); pthread_mutex_lock(&_nxweb_cache_mutex); if ((ci=alignhash_get(nxweb_cache, _nxweb_cache, key))!=alignhash_end(_nxweb_cache)) { nxweb_cache_rec* rec=alignhash_value(_nxweb_cache, ci); if (rec->last_modified==revalidated_mtime) { rec->expires_time=loop_time+NXWEB_DEFAULT_CACHED_TIME; nxweb_log_info("revalidated %s in memcache", key); } if (loop_time <= rec->expires_time) { if (rec!=_nxweb_cache_head) { cache_rec_unlink(rec); cache_rec_link(rec); // relink to head } if (if_modified_since && rec->last_modified<=if_modified_since) { pthread_mutex_unlock(&_nxweb_cache_mutex); resp->status_code=304; resp->status="Not Modified"; return NXWEB_OK; } rec->ref_count++; // this must be within mutex-protected section pthread_mutex_unlock(&_nxweb_cache_mutex); resp->content_length=rec->content_length; resp->content=rec->content; resp->content_type=rec->content_type; resp->content_charset=rec->content_charset; resp->last_modified=rec->last_modified; resp->gzip_encoded=rec->gzip_encoded; conn->hsp.req_data=rec; conn->hsp.req_finalize=cache_rec_unref; return NXWEB_OK; } else if (!revalidated_mtime) { pthread_mutex_unlock(&_nxweb_cache_mutex); return NXWEB_REVALIDATE; } alignhash_del(nxweb_cache, _nxweb_cache, ci); cache_rec_unlink(rec); if (!rec->ref_count) { nx_free(rec); } else { // this is normal; just notification nxweb_log_error("removed %s [%p] from cache while its ref_count=%d", key, rec, rec->ref_count); } } pthread_mutex_unlock(&_nxweb_cache_mutex); return NXWEB_MISS; }
static inline void cache_check_size() { while (alignhash_size(_nxweb_cache)>NXWEB_MAX_CACHED_ITEMS) { nxweb_cache_rec* rec=_nxweb_cache_tail; while (rec && rec->ref_count) rec=rec->prev; if (rec) { const char* fpath=rec->content+rec->content_length+1; ah_iter_t ci=alignhash_get(nxweb_cache, _nxweb_cache, fpath); if (ci!=alignhash_end(_nxweb_cache)) { assert(rec==alignhash_value(_nxweb_cache, ci)); cache_rec_unlink(rec); alignhash_del(nxweb_cache, _nxweb_cache, ci); nx_free(rec); } } else { break; } } }
static void cache_rec_unref(nxd_http_server_proto* hsp, void* req_data) { pthread_mutex_lock(&_nxweb_cache_mutex); nxweb_cache_rec* rec=req_data; assert(rec->ref_count>0); if (!--rec->ref_count) { nxe_time_t loop_time=_nxweb_net_thread_data->loop->current_time; if (loop_time > rec->expires_time || !IS_LINKED(rec)) { const char* fpath=rec->content+rec->content_length+1; ah_iter_t ci=alignhash_get(nxweb_cache, _nxweb_cache, fpath); if (ci!=alignhash_end(_nxweb_cache) && rec==alignhash_value(_nxweb_cache, ci)) { alignhash_del(nxweb_cache, _nxweb_cache, ci); cache_rec_unlink(rec); } else { nxweb_log_error("freed previously removed cache entry %s [%p]", fpath, rec); } nx_free(rec); } } cache_check_size(); pthread_mutex_unlock(&_nxweb_cache_mutex); }