int64 ConcurrentTableSharedStore::inc(CStrRef key, int64 step, bool &found) { found = false; int64 ret = 0; ReadLock l(m_lock); StoreValue *val; { Map::accessor acc; if (m_vars.find(acc, key.data())) { val = &acc->second; if (val->expired()) { eraseAcc(acc); } else { Variant v = val->var->toLocal(); ret = v.toInt64() + step; v = ret; SharedVariant *var = construct(key, v); val->var->decRef(); val->var = var; found = true; } } } if (RuntimeOption::EnableStats && RuntimeOption::EnableAPCStats) { ServerStats::Log("apc.inc", 1); } return ret; }
vector<PbMessagePtr> PairStoreDelegateRddPartition::getValue(const PbMessagePtr& key) const { vector<PbMessagePtr> value; StoreValue<google::protobuf::Message> storeValue; ResultCode rc = dataMap->get(key, storeValue); if (rc == RC_OK) { value.push_back(storeValue.get()); } return value; }
PbMessagePtr PairStoreDelegateRddPartition::get(const PbMessagePtr& key) const { PbMessagePtr value; StoreValue<google::protobuf::Message> storeValue; ResultCode rc = dataMap->get(key, storeValue); if (rc == RC_OK) { value = storeValue.get(); } return value; }
bool ConcurrentTableSharedStore::store(const String& key, const Variant& value, int64_t ttl, bool overwrite /* = true */, bool limit_ttl /* = true */) { StoreValue *sval; APCHandle* svar = construct(value); ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree || m_lockingFlag); const char *kcp = strdup(key.data()); bool present; time_t expiry = 0; bool overwritePrime = false; { Map::accessor acc; present = !m_vars.insert(acc, kcp); sval = &acc->second; if (present) { free((void *)kcp); if (overwrite || sval->expired()) { // if ApcTTLLimit is set, then only primed keys can have expiry == 0 overwritePrime = (sval->expiry == 0); if (sval->inMem()) { sval->var->unreferenceRoot(); } else { // mark the inFile copy invalid since we are updating the key sval->sAddr = nullptr; sval->sSize = 0; } } else { svar->unreferenceRoot(); return false; } } int64_t adjustedTtl = adjust_ttl(ttl, overwritePrime || !limit_ttl); if (check_noTTL(key.data(), key.size())) { adjustedTtl = 0; } sval->set(svar, adjustedTtl); expiry = sval->expiry; } if (expiry) { addToExpirationQueue(key.data(), expiry); } if (apcExtension::ExpireOnSets) { purgeExpired(); } return true; }
bool ConcurrentTableSharedStore::cas(const String& key, int64_t old, int64_t val) { bool success = false; ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree || m_lockingFlag); StoreValue *sval; { Map::accessor acc; if (m_vars.find(acc, tagStringData(key.get()))) { sval = &acc->second; if (!sval->expired() && get_int64_value(sval) == old) { APCHandle *var = construct(Variant(val)); sval->var->unreferenceRoot(); sval->var = var; success = true; } } } return success; }
bool ConcurrentTableSharedStore::cas(CStrRef key, int64 old, int64 val) { bool success = false; ConditionalReadLock l(m_lock, !RuntimeOption::ApcConcurrentTableLockFree || m_lockingFlag); StoreValue *sval; { Map::accessor acc; if (m_vars.find(acc, key.data())) { sval = &acc->second; if (!sval->expired() && get_int64_value(sval) == old) { SharedVariant *var = construct(Variant(val)); sval->var->decRef(); sval->var = var; success = true; log_apc(std_apc_cas); } } } return success; }
int64_t ConcurrentTableSharedStore::inc(const String& key, int64_t step, bool &found) { found = false; int64_t ret = 0; ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree || m_lockingFlag); StoreValue *sval; { Map::accessor acc; if (m_vars.find(acc, tagStringData(key.get()))) { sval = &acc->second; if (!sval->expired()) { ret = get_int64_value(sval) + step; APCHandle *svar = construct(Variant(ret)); sval->var->unreferenceRoot(); sval->var = svar; found = true; } } } return ret; }
int64 ConcurrentTableSharedStore::inc(CStrRef key, int64 step, bool &found) { found = false; int64 ret = 0; ConditionalReadLock l(m_lock, !RuntimeOption::ApcConcurrentTableLockFree || m_lockingFlag); StoreValue *sval; { Map::accessor acc; if (m_vars.find(acc, key.data())) { sval = &acc->second; if (!sval->expired()) { ret = get_int64_value(sval) + step; SharedVariant *svar = construct(Variant(ret)); sval->var->decRef(); sval->var = svar; found = true; log_apc(std_apc_hit); } } } return ret; }
bool ConcurrentTableSharedStore::storeImpl(const String& key, const Variant& value, int64_t ttl, bool overwrite, bool limit_ttl) { StoreValue *sval; auto svar = APCHandle::Create(value, false, APCHandleLevel::Outer, false); auto keyLen = key.size(); ReadLock l(m_lock); char* const kcp = strdup(key.data()); bool present; time_t expiry = 0; bool overwritePrime = false; { Map::accessor acc; APCHandle* current = nullptr; present = !m_vars.insert(acc, kcp); sval = &acc->second; if (present) { free(kcp); if (!overwrite && !sval->expired()) { svar.handle->unreferenceRoot(svar.size); return false; } sval->data.match( [&] (APCHandle* handle) { current = handle; // If ApcTTLLimit is set, then only primed keys can have // expire == 0. overwritePrime = sval->expire == 0; }, [&] (char*) { // Was inFile, but won't be anymore. sval->data = nullptr; sval->dataSize = 0; overwritePrime = true; } ); } else { APCStats::getAPCStats().addKey(keyLen); } int64_t adjustedTtl = adjust_ttl(ttl, overwritePrime || !limit_ttl); if (check_noTTL(key.data(), key.size())) { adjustedTtl = 0; } if (current) { if (sval->expire == 0 && adjustedTtl != 0) { APCStats::getAPCStats().removeAPCValue( sval->dataSize, current, true, sval->expired()); APCStats::getAPCStats().addAPCValue(svar.handle, svar.size, false); } else { APCStats::getAPCStats().updateAPCValue( svar.handle, svar.size, current, sval->dataSize, sval->expire == 0, sval->expired()); } current->unreferenceRoot(sval->dataSize); } else { APCStats::getAPCStats().addAPCValue(svar.handle, svar.size, present); } sval->set(svar.handle, adjustedTtl); sval->dataSize = svar.size; expiry = sval->expire; if (expiry) { auto ikey = intptr_t(acc->first); if (m_expMap.insert({ ikey, 0 })) { m_expQueue.push({ ikey, expiry }); } } } if (apcExtension::ExpireOnSets) { purgeExpired(); } return true; }
bool ConcurrentTableSharedStore::store(CStrRef key, CVarRef val, int64 ttl, bool overwrite /* = true */) { bool stats = RuntimeOption::EnableStats && RuntimeOption::EnableAPCStats; bool statsDetail = RuntimeOption::EnableAPCSizeStats && RuntimeOption::EnableAPCSizeGroup; StoreValue *sval; SharedVariant* var = construct(key, val); ReadLock l(m_lock); const char *kcp = strdup(key.data()); bool present; time_t expiry; { Map::accessor acc; present = !m_vars.insert(acc, kcp); sval = &acc->second; if (present) { free((void *)kcp); if (overwrite || sval->expired()) { if (statsDetail) { SharedStoreStats::onDelete(key.get(), sval->var, true); } sval->var->decRef(); if (RuntimeOption::EnableAPCSizeStats && !check_skip(key.data())) { int32 size = var->getSpaceUsage(); SharedStoreStats::updateDirect(sval->size, size); sval->size = size; } } else { var->decRef(); return false; } } else { if (RuntimeOption::EnableAPCSizeStats) { int32 size = var->getSpaceUsage(); SharedStoreStats::addDirect(key.size(), size); sval->size = size; } } sval->set(var, ttl); expiry = sval->expiry; if (statsDetail) { SharedStoreStats::onStore(key.get(), var, ttl, false); } } if (RuntimeOption::ApcExpireOnSets) { if (ttl) { addToExpirationQueue(key.data(), expiry); } purgeExpired(); } if (stats) { if (present) { ServerStats::Log("apc.update", 1); } else { ServerStats::Log("apc.new", 1); if (RuntimeOption::EnableStats && RuntimeOption::EnableAPCKeyStats) { string prefix = "apc.new."; prefix += GetSkeleton(key); ServerStats::Log(prefix, 1); } } } return true; }
bool ConcurrentTableSharedStore::store(CStrRef key, CVarRef value, int64 ttl, bool overwrite /* = true */) { StoreValue *sval; SharedVariant* svar = construct(value); ConditionalReadLock l(m_lock, !RuntimeOption::ApcConcurrentTableLockFree || m_lockingFlag); const char *kcp = strdup(key.data()); bool present; time_t expiry = 0; bool overwritePrime = false; { Map::accessor acc; present = !m_vars.insert(acc, kcp); sval = &acc->second; bool update = false; if (present) { free((void *)kcp); if (overwrite || sval->expired()) { // if ApcTTLLimit is set, then only primed keys can have expiry == 0 overwritePrime = (sval->expiry == 0); if (sval->inMem()) { stats_on_update(key.get(), sval, svar, adjust_ttl(ttl, overwritePrime)); sval->var->decRef(); update = true; } else { // mark the inFile copy invalid since we are updating the key sval->sAddr = NULL; sval->sSize = 0; } } else { svar->decRef(); return false; } } int64 adjustedTtl = adjust_ttl(ttl, overwritePrime); if (check_noTTL(key.data())) { adjustedTtl = 0; } sval->set(svar, adjustedTtl); expiry = sval->expiry; if (!update) { stats_on_add(key.get(), sval, adjustedTtl, false, false); } } if (expiry) { addToExpirationQueue(key.data(), expiry); } if (RuntimeOption::ApcExpireOnSets) { purgeExpired(); } if (present) { log_apc(std_apc_update); } else { log_apc(std_apc_new); if (RuntimeOption::EnableStats && RuntimeOption::EnableAPCKeyStats) { string prefix = "apc.new." + GetSkeleton(key); ServerStats::Log(prefix, 1); } } return true; }