SharedVariant* ConcurrentTableSharedStore::unserialize(CStrRef key, const StoreValue* sval) { try { VariableUnserializer::Type sType = RuntimeOption::EnableApcSerialize ? VariableUnserializer::APCSerialize : VariableUnserializer::Serialize; VariableUnserializer vu(sval->sAddr, sval->getSerializedSize(), sType); Variant v; v.unserialize(&vu); sval->var = SharedVariant::Create(v, sval->isSerializedObj()); stats_on_add(key.get(), sval, 0, true, true); // delayed prime return sval->var; } catch (Exception &e) { raise_notice("APC Primed fetch failed: key %s (%s).", key.c_str(), e.getMessage().c_str()); return NULL; } }
void ConcurrentTableSharedStore::prime(const std::vector<KeyValuePair> &vars) { ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree || m_lockingFlag); // we are priming, so we are not checking existence or expiration for (unsigned int i = 0; i < vars.size(); i++) { const KeyValuePair &item = vars[i]; Map::accessor acc; const char *copy = strdup(item.key); m_vars.insert(acc, copy); if (item.inMem()) { acc->second.set(item.value, 0); } else { acc->second.sAddr = item.sAddr; acc->second.sSize = item.sSize; continue; } if (RuntimeOption::APCSizeCountPrime) { String str(copy, CopyString); stats_on_add(str.get(), &acc->second, 0, true, false); } } }
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; }