Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}