bool ConcurrentTableSharedStore::handlePromoteObj(CStrRef key,
                                                  SharedVariant* svar,
                                                  CVarRef value) {
  SharedVariant *converted = svar->convertObj(value);
  if (converted) {
    Map::accessor acc;
    if (!m_vars.find(acc, key.data())) {
      // There is a chance another thread deletes the key when this thread is
      // converting the object. In that case, we just bail
      converted->decRef();
      return false;
    }
    // A write lock was acquired during find
    StoreValue *sval = &acc->second;
    SharedVariant *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->isUnserializedObj()) {
      int64 ttl = sval->expiry ? sval->expiry - time(NULL) : 0;
      stats_on_update(key.get(), sval, converted, ttl);
      sval->var = converted;
      sv->decRef();
      return true;
    }
    converted->decRef();
  }
  return false;
}
示例#2
0
bool ConcurrentTableSharedStore::handlePromoteObj(const String& key,
                                                  APCHandle* svar,
                                                  CVarRef 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->decRef();
      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()) {
      int64_t ttl = sval->expiry ? sval->expiry - time(nullptr) : 0;
      stats_on_update(key.get(), sval, converted, ttl);
      sval->var = converted;
      sv->decRef();
      return true;
    }
    converted->decRef();
  }
  return 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;
}