diff --git a/include/query_cache.hpp b/include/query_cache.hpp index 8d0539ac9..fc01f2d9f 100644 --- a/include/query_cache.hpp +++ b/include/query_cache.hpp @@ -24,8 +24,8 @@ struct __QC_entry_t { QC_entry_t *self; // pointer to itself uint32_t klen; // length of the key : FIXME: not sure if still relevant uint32_t length; // length of the value - time_t expire; // when the entry will expire: FIXME: should have a millisecond granularity - time_t access; // when the entry was read last: FIXME: should have a millisecond granularity + unsigned long long expire_ms; // when the entry will expire, monotonic , millisecond granularity + unsigned long long access_ms; // when the entry was read last , monotonic , millisecond granularity uint32_t ref_count; // reference counter }; @@ -46,7 +46,7 @@ class KV_BtreeArray { KV_BtreeArray(); ~KV_BtreeArray(); uint64_t get_data_size(); - void purge_some(time_t QCnow); + void purge_some(unsigned long long); int cnt(); bool replace(uint64_t key, QC_entry_t *entry); QC_entry_t *lookup(uint64_t key); @@ -62,7 +62,7 @@ class Query_Cache { void * purgeHash_thread(void *); int size; int shutdown; - time_t QCnow; + unsigned long long QCnow_ms; pthread_t purge_thread_id; unsigned int purge_loop_time; unsigned int purge_total_time; @@ -72,8 +72,8 @@ class Query_Cache { Query_Cache(); ~Query_Cache(); void print_version(); - bool set(uint64_t , const unsigned char *, uint32_t, unsigned char *, uint32_t, time_t); - unsigned char * get(uint64_t , const unsigned char *, const uint32_t, uint32_t *); + bool set(uint64_t , const unsigned char *, uint32_t, unsigned char *, uint32_t, unsigned long long, unsigned long long); + unsigned char * get(uint64_t , const unsigned char *, const uint32_t, uint32_t *, unsigned long long); uint64_t flush(); }; #endif /* __CLASS_QUERY_CACHE_H */ diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index a363210b4..6a176bdd2 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -1638,7 +1638,13 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C } if (qpo->cache_ttl>0) { uint32_t resbuf=0; - unsigned char *aa=GloQC->get( client_myds->myconn->userinfo->hash, (const unsigned char *)client_myds->mysql_real_query.QueryPtr , client_myds->mysql_real_query.QuerySize , &resbuf); + unsigned char *aa=GloQC->get( + client_myds->myconn->userinfo->hash, + (const unsigned char *)client_myds->mysql_real_query.QueryPtr , + client_myds->mysql_real_query.QuerySize , + &resbuf , + thread->curtime/1000 + ); if (aa) { l_free(pkt->size,pkt->ptr); client_myds->buffer2resultset(aa,resbuf); @@ -1794,7 +1800,15 @@ void MySQL_Session::MySQL_Result_to_MySQL_wire(MYSQL *mysql, MySQL_ResultSet *My client_myds->resultset_length=MyRS->resultset_size; unsigned char *aa=client_myds->resultset2buffer(false); while (client_myds->resultset->len) client_myds->resultset->remove_index(client_myds->resultset->len-1,NULL); - GloQC->set( client_myds->myconn->userinfo->hash , (const unsigned char *)client_myds->mysql_real_query.QueryPtr , client_myds->mysql_real_query.QuerySize , aa,client_myds->resultset_length,qpo->cache_ttl); + GloQC->set( + client_myds->myconn->userinfo->hash , + (const unsigned char *)client_myds->mysql_real_query.QueryPtr , + client_myds->mysql_real_query.QuerySize , + aa , + client_myds->resultset_length , + thread->curtime/1000 , + thread->curtime/1000 + qpo->cache_ttl*1000 + ); l_free(client_myds->resultset_length,aa); client_myds->resultset_length=0; } diff --git a/lib/Query_Cache.cpp b/lib/Query_Cache.cpp index 2748317da..f747a7f7d 100644 --- a/lib/Query_Cache.cpp +++ b/lib/Query_Cache.cpp @@ -100,13 +100,13 @@ uint64_t KV_BtreeArray::get_data_size() { return r; }; -void KV_BtreeArray::purge_some(time_t QCnow) { +void KV_BtreeArray::purge_some(unsigned long long QCnow_ms) { uint64_t ret=0, i, _size=0; QC_entry_t *qce; spin_rdlock(&lock); for (i=0; ilen;i++) { qce=(QC_entry_t *)ptrArray->index(i); - if (qce->expire==EXPIRE_DROPIT || qce->expireexpire_ms==EXPIRE_DROPIT || qce->expire_mslength; } @@ -119,7 +119,7 @@ void KV_BtreeArray::purge_some(time_t QCnow) { spin_wrlock(&lock); for (i=0; ilen;i++) { qce=(QC_entry_t *)ptrArray->index(i); - if ((qce->expire==EXPIRE_DROPIT || qce->expireref_count,0)<=1)) { + if ((qce->expire_ms==EXPIRE_DROPIT || qce->expire_msref_count,0)<=1)) { qce=(QC_entry_t *)ptrArray->remove_index_fast(i); btree::btree_map::iterator lookup; @@ -162,7 +162,7 @@ bool KV_BtreeArray::replace(uint64_t key, QC_entry_t *entry) { btree::btree_map::iterator lookup; lookup = bt_map.find(key); if (lookup != bt_map.end()) { - lookup->second->expire=EXPIRE_DROPIT; + lookup->second->expire_ms=EXPIRE_DROPIT; __sync_fetch_and_sub(&lookup->second->ref_count,1); bt_map.erase(lookup); } @@ -195,7 +195,7 @@ void KV_BtreeArray::empty() { while (bt_map.size()) { lookup = bt_map.begin(); if ( lookup != bt_map.end() ) { - lookup->second->expire=EXPIRE_DROPIT; + lookup->second->expire_ms=EXPIRE_DROPIT; //const char *f=lookup->first; bt_map.erase(lookup); } @@ -236,7 +236,7 @@ Query_Cache::Query_Cache() { perror("Incompatible debagging version"); exit(EXIT_FAILURE); } - QCnow=time(NULL); + QCnow_ms=monotonic_time()/1000; size=SHARED_QUERY_CACHE_HASH_TABLES; shutdown=0; purge_loop_time=DEFAULT_purge_loop_time; @@ -259,7 +259,7 @@ Query_Cache::~Query_Cache() { -unsigned char * Query_Cache::get(uint64_t user_hash, const unsigned char *kp, const uint32_t kl, uint32_t *lv) { +unsigned char * Query_Cache::get(uint64_t user_hash, const unsigned char *kp, const uint32_t kl, uint32_t *lv, unsigned long long curtime_ms) { unsigned char *result=NULL; uint64_t hk=SpookyHash::Hash64(kp, kl, user_hash); @@ -268,19 +268,19 @@ unsigned char * Query_Cache::get(uint64_t user_hash, const unsigned char *kp, co QC_entry_t *entry=KVs[i].lookup(hk); if (entry!=NULL) { - time_t t=QCnow; - if (entry->expire > t) { + unsigned long long t=curtime_ms; + if (entry->expire_ms > t) { result=(unsigned char *)malloc(entry->length); memcpy(result,entry->value,entry->length); *lv=entry->length; - if (t > entry->access) entry->access=t; + if (t > entry->access_ms) entry->access_ms=t; } __sync_fetch_and_sub(&entry->ref_count,1); } return result; } -bool Query_Cache::set(uint64_t user_hash, const unsigned char *kp, uint32_t kl, unsigned char *vp, uint32_t vl, time_t expire) { +bool Query_Cache::set(uint64_t user_hash, const unsigned char *kp, uint32_t kl, unsigned char *vp, uint32_t vl, unsigned long long curtime_ms, unsigned long long expire_ms) { QC_entry_t *entry = (QC_entry_t *)malloc(sizeof(QC_entry_t)); entry->klen=kl; entry->length=vl; @@ -289,12 +289,8 @@ bool Query_Cache::set(uint64_t user_hash, const unsigned char *kp, uint32_t kl, entry->value=(char *)malloc(vl); memcpy(entry->value,vp,vl); entry->self=entry; - entry->access=QCnow; - if (expire > HASH_EXPIRE_MAX) { - entry->expire=expire; // expire is a unix timestamp - } else { - entry->expire=QCnow+expire; // expire is seconds - } + entry->access_ms=curtime_ms; + entry->expire_ms=expire_ms; uint64_t hk=SpookyHash::Hash64(kp, kl, user_hash); unsigned char i=hk%SHARED_QUERY_CACHE_HASH_TABLES; entry->key=hk; @@ -318,12 +314,12 @@ void * Query_Cache::purgeHash_thread(void *) { unsigned int i; while (shutdown==0) { usleep(purge_loop_time); - time_t t=time(NULL); - QCnow=t; + unsigned long long t=monotonic_time()/1000; + QCnow_ms=t; if (current_used_memory_pct() < purge_threshold_pct_min ) continue; for (i=0; i