2020-07-11 21:23:48 +00:00
|
|
|
#include "server.h"
|
|
|
|
|
2021-03-04 07:41:06 +00:00
|
|
|
uint64_t hashPassthrough(const void *hash) {
|
|
|
|
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(hash));
|
|
|
|
}
|
|
|
|
|
|
|
|
int hashCompare(void *, const void *key1, const void *key2) {
|
|
|
|
auto diff = (reinterpret_cast<uintptr_t>(key1) - reinterpret_cast<uintptr_t>(key2));
|
|
|
|
return !diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
dictType dbStorageCacheType = {
|
|
|
|
hashPassthrough, /* hash function */
|
|
|
|
NULL, /* key dup */
|
|
|
|
NULL, /* val dup */
|
|
|
|
hashCompare, /* key compare */
|
|
|
|
NULL, /* key destructor */
|
|
|
|
NULL /* val destructor */
|
|
|
|
};
|
|
|
|
|
2021-03-05 00:54:11 +00:00
|
|
|
StorageCache::StorageCache(IStorage *storage, bool fCache)
|
2021-03-04 07:41:06 +00:00
|
|
|
: m_spstorage(storage)
|
|
|
|
{
|
2021-03-05 00:54:11 +00:00
|
|
|
if (fCache)
|
|
|
|
m_pdict = dictCreate(&dbStorageCacheType, nullptr);
|
2021-03-04 07:41:06 +00:00
|
|
|
}
|
|
|
|
|
2020-07-11 21:23:48 +00:00
|
|
|
void StorageCache::clear()
|
|
|
|
{
|
2020-08-09 23:36:20 +00:00
|
|
|
std::unique_lock<fastlock> ul(m_lock);
|
2021-03-04 07:41:06 +00:00
|
|
|
if (m_pdict != nullptr)
|
|
|
|
dictEmpty(m_pdict, nullptr);
|
2020-07-11 21:23:48 +00:00
|
|
|
m_spstorage->clear();
|
2021-03-04 07:41:06 +00:00
|
|
|
m_collisionCount = 0;
|
2020-07-11 21:23:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StorageCache::cacheKey(sds key)
|
|
|
|
{
|
2021-03-04 07:41:06 +00:00
|
|
|
if (m_pdict == nullptr)
|
2020-07-11 21:23:48 +00:00
|
|
|
return;
|
2021-03-04 07:41:06 +00:00
|
|
|
uintptr_t hash = dictSdsHash(key);
|
|
|
|
if (dictAdd(m_pdict, reinterpret_cast<void*>(hash), (void*)1) != DICT_OK) {
|
|
|
|
dictEntry *de = dictFind(m_pdict, reinterpret_cast<void*>(hash));
|
|
|
|
serverAssert(de != nullptr);
|
|
|
|
de->v.s64++;
|
|
|
|
m_collisionCount++;
|
|
|
|
}
|
2020-07-11 21:23:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StorageCache::cacheKey(const char *rgch, size_t cch)
|
|
|
|
{
|
2021-03-04 07:41:06 +00:00
|
|
|
if (m_pdict == nullptr)
|
2020-07-11 21:23:48 +00:00
|
|
|
return;
|
2021-03-04 07:41:06 +00:00
|
|
|
uintptr_t hash = dictGenHashFunction(rgch, (int)cch);
|
|
|
|
if (dictAdd(m_pdict, reinterpret_cast<void*>(hash), (void*)1) != DICT_OK) {
|
|
|
|
dictEntry *de = dictFind(m_pdict, reinterpret_cast<void*>(hash));
|
|
|
|
serverAssert(de != nullptr);
|
|
|
|
de->v.s64++;
|
|
|
|
m_collisionCount++;
|
|
|
|
}
|
2020-07-11 21:23:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageCache::erase(sds key)
|
|
|
|
{
|
|
|
|
bool result = m_spstorage->erase(key, sdslen(key));
|
2020-08-09 23:36:20 +00:00
|
|
|
std::unique_lock<fastlock> ul(m_lock);
|
2021-03-04 07:41:06 +00:00
|
|
|
if (result && m_pdict != nullptr)
|
2020-07-11 21:23:48 +00:00
|
|
|
{
|
2021-03-04 07:41:06 +00:00
|
|
|
uint64_t hash = dictSdsHash(key);
|
|
|
|
dictEntry *de = dictFind(m_pdict, reinterpret_cast<void*>(hash));
|
|
|
|
serverAssert(de != nullptr);
|
|
|
|
de->v.s64--;
|
|
|
|
serverAssert(de->v.s64 >= 0);
|
|
|
|
if (de->v.s64 == 0) {
|
|
|
|
dictDelete(m_pdict, reinterpret_cast<void*>(hash));
|
|
|
|
} else {
|
|
|
|
m_collisionCount--;
|
|
|
|
}
|
2020-07-11 21:23:48 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageCache::insert(sds key, const void *data, size_t cbdata, bool fOverwrite)
|
|
|
|
{
|
2020-08-09 23:36:20 +00:00
|
|
|
std::unique_lock<fastlock> ul(m_lock);
|
2021-03-04 07:41:06 +00:00
|
|
|
if (!fOverwrite && m_pdict != nullptr)
|
2020-07-11 21:23:48 +00:00
|
|
|
{
|
|
|
|
cacheKey(key);
|
|
|
|
}
|
2020-08-09 23:36:20 +00:00
|
|
|
ul.unlock();
|
2020-07-11 21:23:48 +00:00
|
|
|
m_spstorage->insert(key, sdslen(key), (void*)data, cbdata, fOverwrite);
|
|
|
|
}
|
|
|
|
|
|
|
|
const StorageCache *StorageCache::clone()
|
|
|
|
{
|
2020-08-09 23:36:20 +00:00
|
|
|
std::unique_lock<fastlock> ul(m_lock);
|
2020-07-11 21:23:48 +00:00
|
|
|
// Clones never clone the cache
|
2021-03-05 00:54:11 +00:00
|
|
|
StorageCache *cacheNew = new StorageCache(const_cast<IStorage*>(m_spstorage->clone()), false /*fCache*/);
|
2020-07-11 21:23:48 +00:00
|
|
|
return cacheNew;
|
|
|
|
}
|
|
|
|
|
2021-03-04 07:41:06 +00:00
|
|
|
void StorageCache::retrieve(sds key, IStorage::callbackSingle fn) const
|
2020-07-11 21:23:48 +00:00
|
|
|
{
|
2020-08-09 23:36:20 +00:00
|
|
|
std::unique_lock<fastlock> ul(m_lock);
|
2021-03-04 07:41:06 +00:00
|
|
|
if (m_pdict != nullptr)
|
2020-07-11 21:23:48 +00:00
|
|
|
{
|
2021-03-04 07:41:06 +00:00
|
|
|
uint64_t hash = dictSdsHash(key);
|
|
|
|
dictEntry *de = dictFind(m_pdict, reinterpret_cast<void*>(hash));
|
|
|
|
|
|
|
|
if (de == nullptr)
|
2020-07-11 21:23:48 +00:00
|
|
|
return; // Not found
|
|
|
|
}
|
2020-08-09 23:36:20 +00:00
|
|
|
ul.unlock();
|
2020-07-11 21:23:48 +00:00
|
|
|
m_spstorage->retrieve(key, sdslen(key), fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t StorageCache::count() const
|
|
|
|
{
|
2020-08-09 23:36:20 +00:00
|
|
|
std::unique_lock<fastlock> ul(m_lock);
|
2020-07-11 21:23:48 +00:00
|
|
|
size_t count = m_spstorage->count();
|
2021-03-04 07:41:06 +00:00
|
|
|
if (m_pdict != nullptr) {
|
|
|
|
serverAssert(count == (dictSize(m_pdict) + m_collisionCount));
|
|
|
|
}
|
2020-07-11 21:23:48 +00:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageCache::beginWriteBatch() {
|
|
|
|
serverAssert(GlobalLocksAcquired()); // Otherwise we deadlock
|
|
|
|
m_spstorage->beginWriteBatch();
|
|
|
|
}
|