int64 ConcurrentTableSharedStore::inc(CStrRef key, int64 step, bool &found) {
  found = false;
  int64 ret = 0;
  ReadLock l(m_lock);
  StoreValue *val;
  {
    Map::accessor acc;
    if (m_vars.find(acc, key.data())) {
      val = &acc->second;
      if (val->expired()) {
        eraseAcc(acc);
      } else {
        Variant v = val->var->toLocal();
        ret = v.toInt64() + step;
        v = ret;
        SharedVariant *var = construct(key, v);
        val->var->decRef();
        val->var = var;
        found = true;
      }
    }
  }

  if (RuntimeOption::EnableStats && RuntimeOption::EnableAPCStats) {
    ServerStats::Log("apc.inc", 1);
  }
  return ret;
}
Esempio n. 2
0
/**
 * The Map::accessor here establishes a write lock, which means that other
 * threads, protected by read locks through Map::const_accessor, will not
 * read erased values from APC.
 * The ReadLock here is to sync with clear(), which only has a WriteLock,
 * not a specific accessor.
 */
bool ConcurrentTableSharedStore::eraseImpl(const String& key,
                                           bool expired,
                                           int64_t oldestLive) {
  if (key.isNull()) return false;
  ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree ||
                                m_lockingFlag);
  Map::accessor acc;
  if (m_vars.find(acc, tagStringData(key.get()))) {
    if (expired && !acc->second.expired()) {
      return false;
    }
    if (acc->second.inMem()) {
      if (expired && acc->second.expiry < oldestLive &&
          acc->second.var->getUncounted()) {
        APCTypedValue::fromHandle(acc->second.var)->deleteUncounted();
      } else {
        acc->second.var->unreferenceRoot();
      }
    } else {
      assert(acc->second.inFile());
      assert(acc->second.expiry == 0);
    }
    if (expired && acc->second.inFile()) {
      // a primed key expired, do not erase the table entry
      acc->second.var = nullptr;
      acc->second.size = 0;
      acc->second.expiry = 0;
    } else {
      eraseAcc(acc);
    }
    return true;
  }
  return false;
}
/**
 * The Map::accessor here establishes a write lock, which means that other
 * threads, protected by read locks through Map::const_accessor, will not
 * read erased values from APC.
 * The ReadLock here is to sync with clear(), which only has a WriteLock,
 * not a specific accessor.
 */
bool ConcurrentTableSharedStore::eraseImpl(CStrRef key, bool expired) {
  if (key.isNull()) return false;
  ConditionalReadLock l(m_lock, !RuntimeOption::ApcConcurrentTableLockFree ||
                                m_lockingFlag);
  Map::accessor acc;
  if (m_vars.find(acc, key.data())) {
    if (expired && !acc->second.expired()) {
      return false;
    }
    if (acc->second.inMem()) {
      stats_on_delete(key.get(), &acc->second, expired);
      acc->second.var->decRef();
    } else {
      assert(acc->second.inFile());
      assert(acc->second.expiry == 0);
    }
    if (expired && acc->second.inFile()) {
      // a primed key expired, do not erase the table entry
      acc->second.var = NULL;
      acc->second.size = 0;
      acc->second.expiry = 0;
    } else {
      eraseAcc(acc);
    }
    return true;
  }
  return false;
}
Esempio n. 4
0
/*
 * The Map::accessor here establishes a write lock, which means that other
 * threads, protected by read locks through Map::const_accessor, will not
 * read erased values from APC.
 *
 * The ReadLock here is to sync with clear(), which only has a WriteLock,
 * not a specific accessor.
 */
bool ConcurrentTableSharedStore::eraseImpl(const char* key,
                                           bool expired,
                                           int64_t oldestLive) {
  assert(key);

  ReadLock l(m_lock);
  Map::accessor acc;
  if (!m_vars.find(acc, key)) {
    return false;
  }
  if (expired && !acc->second.expired()) {
    return false;
  }

  auto& storeVal = acc->second;

  storeVal.data.match(
    [&] (APCHandle* var) {
      APCStats::getAPCStats().removeAPCValue(storeVal.dataSize, var,
        storeVal.expire == 0, expired);
      if (expired && storeVal.expire < oldestLive && var->isUncounted()) {
        APCTypedValue::fromHandle(var)->deleteUncounted();
      } else {
        var->unreferenceRoot(storeVal.dataSize);
      }

      eraseAcc(acc);
    },
    [&] (char* file) {
      assert(!expired);  // primed keys never say true to expired()
      eraseAcc(acc);
    }
  );

  return true;
}
/**
 * The Map::accessor here establishes a write lock, which means that other
 * threads, protected by read locks through Map::const_accessor, will not
 * read erased values from APC.
 * The ReadLock here is to sync with clear(), which only has a WriteLock,
 * not a specific accessor.
 */
bool ConcurrentTableSharedStore::eraseImpl(CStrRef key, bool expired) {
  if (key.isNull()) return false;
  ReadLock l(m_lock);
  Map::accessor acc;
  if (m_vars.find(acc, key.data())) {
    if (expired && !acc->second.expired()) {
      return false;
    }
    if (RuntimeOption::EnableAPCSizeStats) {
      SharedStoreStats::removeDirect(key.size(), acc->second.size);
      if (RuntimeOption::EnableAPCSizeGroup) {
        SharedStoreStats::onDelete(key.get(), acc->second.var, false);
      }
    }
    eraseAcc(acc);
    return true;
  }
  return false;
}