MatthiasMullie\Scrapbook\Buffered\Utils\Defer::cas PHP Метод

cas() публичный Метод

public cas ( mixed $originalValue, string $key, mixed $value, integer $expire )
$originalValue mixed No real CAS token, but the original value for this key
$key string
$value mixed
$expire integer
    public function cas($originalValue, $key, $value, $expire)
    {
        /*
         * If we made it here, we're sure that logically, the CAS applies with
         * respect to other operations in this transaction. That means we don't
         * have to verify the token here: whatever has already been set/add/
         * replace/cas will have taken care of that and we already know this one
         * applies on top op that change. We can just fold it in there & update
         * the value we set initially.
         */
        if (isset($this->keys[$key]) && in_array($this->keys[$key][0], array('set', 'add', 'replace', 'cas'))) {
            $this->keys[$key][2]['value'] = $value;
            $this->keys[$key][2]['expire'] = $expire;
            return;
        }
        /*
         * @param mixed $originalValue
         * @param string $key
         * @param mixed $value
         * @param int $expire
         * @return bool
         */
        $cache = $this->cache;
        $callback = function ($originalValue, $key, $value, $expire) use($cache) {
            // check if given (local) CAS token was known
            if ($originalValue === null) {
                return false;
            }
            // fetch data from real cache, getting new valid CAS token
            $current = $cache->get($key, $token);
            // check if the value we just read from real cache is still the same
            // as the one we saved when doing the original fetch
            if (serialize($current) === $originalValue) {
                // everything still checked out, CAS the value for real now
                return $cache->cas($token, $key, $value, $expire);
            }
            return false;
        };
        $args = array('token' => $originalValue, 'key' => $key, 'value' => $value, 'expire' => $expire);
        $this->keys[$key] = array(__FUNCTION__, $callback, $args);
    }

Usage Example

Пример #1
0
 /**
  * Since our CAS is deferred, the CAS token we got from our original
  * get() will likely not be valid by the time we want to store it to
  * the real cache. Imagine this scenario:
  * * a value is fetched from (real) cache
  * * an new value key is CAS'ed (into temp cache - real CAS is deferred)
  * * this key's value is fetched again (this time from temp cache)
  * * and a new value is CAS'ed again (into temp cache...).
  *
  * In this scenario, when we finally want to replay the write actions
  * onto the real cache, the first 3 actions would likely work fine.
  * The last (second CAS) however would not, since it never got a real
  * updated $token from the real cache.
  *
  * To work around this problem, all get() calls will return a unique
  * CAS token and store the value-at-that-time associated with that
  * token. All we have to do when we want to write the data to real cache
  * is, right before was CAS for real, get the value & (real) cas token
  * from storage & compare that value to the one we had stored. If that
  * checks out, we can safely resume the CAS with the real token we just
  * received.
  *
  * {@inheritdoc}
  */
 public function cas($token, $key, $value, $expire = 0)
 {
     $originalValue = isset($this->tokens[$token]) ? $this->tokens[$token] : null;
     // value is no longer the same as what we used for token
     if (serialize($this->get($key)) !== $originalValue) {
         return false;
     }
     // "CAS" value to local cache/memory
     $success = $this->local->set($key, $value, $expire);
     if ($success === false) {
         return false;
     }
     // only schedule the CAS to be performed on real cache if it was OK on
     // local cache
     $this->defer->cas($originalValue, $key, $value, $expire);
     return true;
 }