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; }
/** * The Map::accessor here establishes a write lock, which means that other * threads, protected by read locks through Map::const_accessor, will not * read erased values from APC. * The ReadLock here is to sync with clear(), which only has a WriteLock, * not a specific accessor. */ bool ConcurrentTableSharedStore::eraseImpl(const String& key, bool expired, int64_t oldestLive) { if (key.isNull()) return false; ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree || m_lockingFlag); Map::accessor acc; if (m_vars.find(acc, tagStringData(key.get()))) { if (expired && !acc->second.expired()) { return false; } if (acc->second.inMem()) { if (expired && acc->second.expiry < oldestLive && acc->second.var->getUncounted()) { APCTypedValue::fromHandle(acc->second.var)->deleteUncounted(); } else { acc->second.var->unreferenceRoot(); } } else { assert(acc->second.inFile()); assert(acc->second.expiry == 0); } if (expired && acc->second.inFile()) { // a primed key expired, do not erase the table entry acc->second.var = nullptr; acc->second.size = 0; acc->second.expiry = 0; } else { eraseAcc(acc); } return true; } return false; }
/** * The Map::accessor here establishes a write lock, which means that other * threads, protected by read locks through Map::const_accessor, will not * read erased values from APC. * The ReadLock here is to sync with clear(), which only has a WriteLock, * not a specific accessor. */ bool ConcurrentTableSharedStore::eraseImpl(CStrRef key, bool expired) { if (key.isNull()) return false; ConditionalReadLock l(m_lock, !RuntimeOption::ApcConcurrentTableLockFree || m_lockingFlag); Map::accessor acc; if (m_vars.find(acc, key.data())) { if (expired && !acc->second.expired()) { return false; } if (acc->second.inMem()) { stats_on_delete(key.get(), &acc->second, expired); acc->second.var->decRef(); } else { assert(acc->second.inFile()); assert(acc->second.expiry == 0); } if (expired && acc->second.inFile()) { // a primed key expired, do not erase the table entry acc->second.var = NULL; acc->second.size = 0; acc->second.expiry = 0; } else { eraseAcc(acc); } return true; } return false; }
/* * The Map::accessor here establishes a write lock, which means that other * threads, protected by read locks through Map::const_accessor, will not * read erased values from APC. * * The ReadLock here is to sync with clear(), which only has a WriteLock, * not a specific accessor. */ bool ConcurrentTableSharedStore::eraseImpl(const char* key, bool expired, int64_t oldestLive) { assert(key); ReadLock l(m_lock); Map::accessor acc; if (!m_vars.find(acc, key)) { return false; } if (expired && !acc->second.expired()) { return false; } auto& storeVal = acc->second; storeVal.data.match( [&] (APCHandle* var) { APCStats::getAPCStats().removeAPCValue(storeVal.dataSize, var, storeVal.expire == 0, expired); if (expired && storeVal.expire < oldestLive && var->isUncounted()) { APCTypedValue::fromHandle(var)->deleteUncounted(); } else { var->unreferenceRoot(storeVal.dataSize); } eraseAcc(acc); }, [&] (char* file) { assert(!expired); // primed keys never say true to expired() eraseAcc(acc); } ); return true; }
/** * The Map::accessor here establishes a write lock, which means that other * threads, protected by read locks through Map::const_accessor, will not * read erased values from APC. * The ReadLock here is to sync with clear(), which only has a WriteLock, * not a specific accessor. */ bool ConcurrentTableSharedStore::eraseImpl(CStrRef key, bool expired) { if (key.isNull()) return false; ReadLock l(m_lock); Map::accessor acc; if (m_vars.find(acc, key.data())) { if (expired && !acc->second.expired()) { return false; } if (RuntimeOption::EnableAPCSizeStats) { SharedStoreStats::removeDirect(key.size(), acc->second.size); if (RuntimeOption::EnableAPCSizeGroup) { SharedStoreStats::onDelete(key.get(), acc->second.var, false); } } eraseAcc(acc); return true; } return false; }