示例#1
0
bool ConcurrentTableSharedStore::get(const String& key, Variant& value) {
    const StoreValue *sval;
    APCHandle *svar = nullptr;
    ReadLock l(m_lock);
    bool expired = false;
    bool promoteObj = false;
    {
        Map::const_accessor acc;
        if (!m_vars.find(acc, tagStringData(key.get()))) {
            return false;
        } else {
            sval = &acc->second;
            if (sval->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 {
                if (auto const handle = sval->data.left()) {
                    svar = handle;
                } else {
                    std::lock_guard<SmallLock> sval_lock(sval->lock);

                    if (auto const handle = sval->data.left()) {
                        svar = handle;
                    } else {
                        /*
                         * Note that unserialize can run arbitrary php code via a __wakeup
                         * routine, which could try to access this same key, and we're
                         * holding various locks here.  This is only for promoting primed
                         * values to in-memory values, so it's basically not a real
                         * problem, but ... :)
                         */
                        svar = unserialize(key, const_cast<StoreValue*>(sval));
                        if (!svar) return false;
                    }
                }

                if (apcExtension::AllowObj && svar->type() == KindOfObject &&
                        !svar->objAttempted()) {
                    // Hold ref here for later promoting the object
                    svar->reference();
                    promoteObj = true;
                }
                value = svar->toLocal();
            }
        }
    }
    if (expired) {
        eraseImpl(key, true, apcExtension::UseUncounted ?
                  HPHP::Treadmill::getOldestStartTime() : 0);
        return false;
    }

    if (promoteObj)  {
        handlePromoteObj(key, svar, value);
        // release the extra ref
        svar->unreference();
    }
    return true;
}
示例#2
0
bool ConcurrentTableSharedStore::get(const String& key, Variant &value) {
  const StoreValue *sval;
  APCHandle *svar = nullptr;
  ConditionalReadLock l(m_lock, !apcExtension::ConcurrentTableLockFree ||
                                m_lockingFlag);
  bool expired = false;
  bool promoteObj = false;
  {
    Map::const_accessor acc;
    if (!m_vars.find(acc, tagStringData(key.get()))) {
      log_apc(std_apc_miss);
      return false;
    } else {
      sval = &acc->second;
      if (sval->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 {
        if (!sval->inMem()) {
          std::lock_guard<SmallLock> sval_lock(sval->lock);

          if (!sval->inMem()) {
            svar = unserialize(key, sval);
            if (!svar) return false;
          } else {
            svar = sval->var;
          }
        } else {
          svar = sval->var;
        }

        if (apcExtension::AllowObj && svar->is(KindOfObject) &&
            !svar->getObjAttempted()) {
          // Hold ref here for later promoting the object
          svar->incRef();
          promoteObj = true;
        }
        value = svar->toLocal();
        stats_on_get(key.get(), svar);
      }
    }
  }
  if (expired) {
    log_apc(std_apc_miss);
    eraseImpl(key, true);
    return false;
  }
  log_apc(std_apc_hit);

  if (promoteObj)  {
    handlePromoteObj(key, svar, value);
    // release the extra ref
    svar->decRef();
  }
  return true;
}