bool ConcurrentTableSharedStore::handlePromoteObj(const String& key, APCHandle* svar, const Variant& value) { auto const pair = APCObject::MakeAPCObject(svar, value); if (!pair.handle) return false; auto const converted = pair.handle; auto const size = pair.size; Map::accessor acc; if (!m_vars.find(acc, tagStringData(key.get()))) { // There is a chance another thread deletes the key when this thread is // converting the object. In that case, we just bail converted->unreferenceRoot(size); return false; } // Our handle may not be same as `svar' here because some other thread may // have updated it already, check before updating. auto& sval = acc->second; auto const handle = sval.data.left(); if (handle == svar && handle->kind() == APCKind::SerializedObject) { sval.data = converted; APCStats::getAPCStats().updateAPCValue( converted, size, handle, sval.dataSize, sval.expire == 0, false); handle->unreferenceRoot(sval.dataSize); sval.dataSize = size; return true; } converted->unreferenceRoot(size); return false; }
bool ConcurrentTableSharedStore::cas(const String& key, int64_t old, int64_t val) { ReadLock l(m_lock); Map::accessor acc; if (!m_vars.find(acc, tagStringData(key.get()))) { return false; } auto& sval = acc->second; if (sval.expired()) return false; auto const oldHandle = sval.data.match( [&] (APCHandle* h) { return h; }, [&] (char* file) { return unserialize(key, &sval); } ); if (!oldHandle || oldHandle->toLocal().toInt64() != old) { return false; } auto const pair = APCHandle::Create(Variant(val), false, APCHandleLevel::Outer, false); APCStats::getAPCStats().updateAPCValue(pair.handle, pair.size, oldHandle, sval.dataSize, sval.expire == 0, false); oldHandle->unreferenceRoot(sval.dataSize); sval.data = pair.handle; sval.dataSize = pair.size; return true; }
int64_t ConcurrentTableSharedStore::inc(const String& key, int64_t step, bool& found) { found = false; ReadLock l(m_lock); Map::accessor acc; if (!m_vars.find(acc, tagStringData(key.get()))) { return 0; } auto& sval = acc->second; if (sval.expired()) return 0; /* * Inc only works on KindOfDouble or KindOfInt64, which are never kept in * file-backed storage from priming. So we don't need to try to deserialize * anything or handle the case that sval.data is file-backed. */ auto const oldHandle = sval.data.left(); if (oldHandle == nullptr) return 0; if (oldHandle->type() != KindOfInt64 && oldHandle->type() != KindOfDouble) { return 0; } auto const ret = oldHandle->toLocal().toInt64() + step; auto const pair = APCHandle::Create(Variant(ret), false); APCStats::getAPCStats().updateAPCValue(pair.handle, pair.size, oldHandle, sval.dataSize, sval.expire == 0, false); oldHandle->unreferenceRoot(sval.dataSize); sval.data = pair.handle; sval.dataSize = pair.size; found = true; return ret; }