Esempio n. 1
0
bool ConcurrentTableSharedStore::handlePromoteObj(const String& key,
                                                  APCHandle* svar,
                                                  const Variant& value) {
  APCHandle *converted = APCObject::MakeAPCObject(svar, value);
  if (converted) {
    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();
      return false;
    }
    // A write lock was acquired during find
    StoreValue *sval = &acc->second;
    APCHandle *sv = sval->var;
    // sv may not be same as svar here because some other thread may have
    // updated it already, check before updating
    if (sv == svar && !sv->getIsObj()) {
      sval->var = converted;
      sv->unreferenceRoot();
      return true;
    }
    converted->unreferenceRoot();
  }
  return false;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}