bool ConcurrentTableSharedStore::store(CStrRef key, CVarRef val, int64 ttl,
                                       bool overwrite /* = true */) {
  bool stats = RuntimeOption::EnableStats && RuntimeOption::EnableAPCStats;
  bool statsDetail = RuntimeOption::EnableAPCSizeStats &&
                     RuntimeOption::EnableAPCSizeGroup;
  StoreValue *sval;
  SharedVariant* var = construct(key, val);
  ReadLock l(m_lock);

  const char *kcp = strdup(key.data());
  bool present;
  time_t expiry;
  {
    Map::accessor acc;
    present = !m_vars.insert(acc, kcp);
    sval = &acc->second;
    if (present) {
      free((void *)kcp);
      if (overwrite || sval->expired()) {
        if (statsDetail) {
          SharedStoreStats::onDelete(key.get(), sval->var, true);
        }
        sval->var->decRef();
        if (RuntimeOption::EnableAPCSizeStats && !check_skip(key.data())) {
          int32 size = var->getSpaceUsage();
          SharedStoreStats::updateDirect(sval->size, size);
          sval->size = size;
        }
      } else {
        var->decRef();
        return false;
      }
    } else {
      if (RuntimeOption::EnableAPCSizeStats) {
        int32 size = var->getSpaceUsage();
        SharedStoreStats::addDirect(key.size(), size);
        sval->size = size;
      }
    }
    sval->set(var, ttl);
    expiry = sval->expiry;
    if (statsDetail) {
      SharedStoreStats::onStore(key.get(), var, ttl, false);
    }
  }
  if (RuntimeOption::ApcExpireOnSets) {
    if (ttl) {
      addToExpirationQueue(key.data(), expiry);
    }
    purgeExpired();
  }
  if (stats) {
    if (present) {
      ServerStats::Log("apc.update", 1);
    } else {
      ServerStats::Log("apc.new", 1);
      if (RuntimeOption::EnableStats && RuntimeOption::EnableAPCKeyStats) {
        string prefix = "apc.new.";
        prefix += GetSkeleton(key);
        ServerStats::Log(prefix, 1);
      }
    }
  }

  return true;
}
bool ConcurrentTableSharedStore::get(CStrRef key, Variant &value) {
  bool stats = RuntimeOption::EnableStats && RuntimeOption::EnableAPCStats;
  bool statsFetch = RuntimeOption::EnableAPCSizeStats &&
                    RuntimeOption::EnableAPCFetchStats;
  const StoreValue *val;
  SharedVariant *svar = NULL;
  ReadLock l(m_lock);
  bool expired = false;
  {
    Map::const_accessor acc;
    if (!m_vars.find(acc, key.data())) {
      if (stats) ServerStats::Log("apc.miss", 1);
      return false;
    } else {
      val = &acc->second;
      if (val->expired()) {
        // Because it only has a read lock on the data, deletion from
        // expiration has to happen after the lock is released
        expired = true;
      } else {
        svar = val->var;
        if (RuntimeOption::ApcAllowObj) {
          // Hold ref here
          svar->incRef();
        }
        value = svar->toLocal();
        if (statsFetch) {
          SharedStoreStats::onGet(key.get(), svar);
        }
      }
    }
  }
  if (expired) {
    if (stats) {
      ServerStats::Log("apc.miss", 1);
    }
    eraseImpl(key, true);
    return false;
  }
  if (stats) {
    ServerStats::Log("apc.hit", 1);
  }

  if (RuntimeOption::ApcAllowObj)  {
    bool statsDetail = RuntimeOption::EnableAPCSizeStats &&
                       RuntimeOption::EnableAPCSizeGroup;
    SharedVariant *converted = svar->convertObj(value);
    if (converted) {
      Map::accessor acc;
      m_vars.find(acc, key.data()); // start a write lock
      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->isUnserializedObj()) {
        if (statsDetail) {
          SharedStoreStats::onDelete(key.get(), sv, true);
        }
        sval->var = converted;
        sv->decRef();
        if (RuntimeOption::EnableAPCSizeStats) {
          int32 newSize = converted->getSpaceUsage();
          SharedStoreStats::updateDirect(sval->size, newSize);
          sval->size = newSize;
        }
        if (statsDetail) {
          int64 ttl = sval->expiry ? sval->expiry - time(NULL) : 0;
          SharedStoreStats::onStore(key.get(), converted, ttl, false);
        }
      } else {
        converted->decRef();
      }
    }
    // release the extra ref
    svar->decRef();
  }
  return true;
}