Ejemplo n.º 1
0
 public function limitRate($key)
 {
     $cas = null;
     do {
         $info = $this->client->get($key, null, $cas);
         if (!$info) {
             return false;
         }
         $info['calls']++;
         $this->client->cas($cas, $key, $info);
     } while ($this->client->getResultCode() != \Memcached::RES_SUCCESS);
     return $this->getRateInfo($key);
 }
 /**
  * Performs a "check and set" to store data.
  *
  * The set will be successful only if the no other request has updated the value since it was fetched since
  * this request.
  *
  * @link    http://www.php.net/manual/en/memcached.cas.php
  *
  * @param   float       $cas_token      Unique value associated with the existing item. Generated by memcached.
  * @param   string      $key            The key under which to store the value.
  * @param   mixed       $value          The value to store.
  * @param   string      $group          The group value appended to the $key.
  * @param   int         $expiration     The expiration time, defaults to 0.
  * @param   string      $server_key     The key identifying the server to store the value on.
  * @param   bool        $byKey          True to store in internal cache by key; false to not store by key
  * @return  bool                        Returns TRUE on success or FALSE on failure.
  */
 public function cas($cas_token, $key, $value, $group = 'default', $expiration = 0, $server_key = '', $byKey = false)
 {
     $derived_key = $this->buildKey($key, $group);
     $expiration = $this->sanitize_expiration($expiration);
     /**
      * If group is a non-Memcached group, save to runtime cache, not Memcached. Note
      * that since check and set cannot be emulated in the run time cache, this value
      * operation is treated as a normal "add" for no_mc_groups.
      */
     if (in_array($group, $this->no_mc_groups)) {
         $this->add_to_internal_cache($derived_key, $value);
         return true;
     }
     // Save to Memcached
     if (false !== $byKey) {
         $result = $this->mc->casByKey($cas_token, $server_key, $derived_key, $value, $expiration);
     } else {
         $result = $this->mc->cas($cas_token, $derived_key, $value, $expiration);
     }
     // Store in runtime cache if cas was successful
     if (Memcached::RES_SUCCESS === $this->getResultCode()) {
         $this->add_to_internal_cache($derived_key, $value);
     }
     return $result;
 }
Ejemplo n.º 3
0
 /**
  * Check and set item
  *
  * @param  float  $token
  * @param  string $key
  * @param  mixed  $value
  * @param  array  $options
  * @return bool
  */
 public function checkAndSetItem($token, $key, $value, array $options = array())
 {
     $baseOptions = $this->getOptions();
     if (!$baseOptions->getWritable()) {
         return false;
     }
     $this->normalizeOptions($options);
     $this->normalizeKey($key);
     $args = new ArrayObject(array('token' => &$token, 'key' => &$key, 'value' => &$value, 'options' => &$options));
     try {
         $eventRs = $this->triggerPre(__FUNCTION__, $args);
         if ($eventRs->stopped()) {
             return $eventRs->last();
         }
         $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']);
         $expiration = $this->expirationTime($options['ttl']);
         $result = $this->memcached->cas($token, $key, $value, $expiration);
         if ($result === false) {
             $rsCode = $this->memcached->getResultCode();
             if ($rsCode !== 0 && $rsCode != MemcachedResource::RES_DATA_EXISTS) {
                 throw $this->getExceptionByResultCode($rsCode);
             }
         }
         return $this->triggerPost(__FUNCTION__, $args, $result);
     } catch (\Exception $e) {
         return $this->triggerException(__FUNCTION__, $args, $e);
     }
 }
Ejemplo n.º 4
0
 /**
  * cas
  * @param $key
  * @param $val
  * @param $expireTime
  * @param $cas_token
  * @return bool
  */
 public function cas($key, $val, $expireTime, &$cas_token)
 {
     $ret = $this->dbh->cas($cas_token, $key, $val, $expireTime);
     if ($ret === false) {
         $this->error('cas', $key);
     }
     return true;
 }
Ejemplo n.º 5
0
 public function set($key, $value)
 {
     $this->get($key);
     if (!$value) {
         throw new StorageException('[STORAGE] Given value for "' . $this->getStorageName() . '::set" not valid! Key: ' . $key);
     }
     if ($this->memcachedObj->getResultCode() == \Memcached::RES_NOTFOUND) {
         $this->memcachedObj->add($key, $value);
         unset($this->casArray[$key]);
     } else {
         $this->memcachedObj->cas($this->casArray[$key], $key, $value);
     }
     $resultCode = $this->memcachedObj->getResultCode();
     if ($resultCode != \Memcached::RES_SUCCESS) {
         throw new StorageException('[STORAGE] "' . $this->getStorageName() . '::set" failed!' . ' StorageRespCode: ' . $resultCode . ', Key: ' . $key . ', Cas: ' . (isset($this->casArray[$key]) ? $this->casArray[$key] : 'null'));
     }
     return $resultCode;
 }
Ejemplo n.º 6
0
 /**
  * Internal method to set an item only if token matches
  *
  * @param  mixed  $token
  * @param  string $normalizedKey
  * @param  mixed  $value
  * @return boolean
  * @throws Exception\ExceptionInterface
  * @see    getItem()
  * @see    setItem()
  */
 protected function internalCheckAndSetItem(&$token, &$normalizedKey, &$value)
 {
     $expiration = $this->expirationTime();
     $result = $this->memcached->cas($token, $normalizedKey, $value, $expiration);
     if ($result === false) {
         $rsCode = $this->memcached->getResultCode();
         if ($rsCode !== 0 && $rsCode != MemcachedResource::RES_DATA_EXISTS) {
             throw $this->getExceptionByResultCode($rsCode);
         }
     }
     return $result;
 }
Ejemplo n.º 7
0
 public function cas($key, $value)
 {
     if (($rValue = $this->memcached->get($key, null, $token)) !== false) {
         return $rValue;
     }
     if ($this->memcached->getResultCode() === Memcached::RES_NOTFOUND) {
         $this->memcached->add($key, $value);
     } else {
         $this->memcached->cas($token, $key, $value);
     }
     return $value;
 }
Ejemplo n.º 8
0
 /**
  * Internal method to set an item only if token matches
  *
  * Options:
  *  - ttl <float>
  *    - The time-to-life
  *  - namespace <string>
  *    - The namespace to use
  *  - tags <array>
  *    - An array of tags
  *
  * @param  mixed  $token
  * @param  string $normalizedKey
  * @param  mixed  $value
  * @param  array  $normalizedOptions
  * @return boolean
  * @throws Exception\ExceptionInterface
  * @see    getItem()
  * @see    setItem()
  */
 protected function internalCheckAndSetItem(&$token, &$normalizedKey, &$value, array &$normalizedOptions)
 {
     $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']);
     $expiration = $this->expirationTime($normalizedOptions['ttl']);
     $result = $this->memcached->cas($token, $normalizedKey, $value, $expiration);
     if ($result === false) {
         $rsCode = $this->memcached->getResultCode();
         if ($rsCode !== 0 && $rsCode != MemcachedResource::RES_DATA_EXISTS) {
             throw $this->getExceptionByResultCode($rsCode);
         }
     }
     return $result;
 }
Ejemplo n.º 9
0
 /**
  * Shared between increment/decrement: both have mostly the same logic
  * (decrement just increments a negative value), but need their validation
  * split up (increment won't accept negative values).
  *
  * @param string $key
  * @param int    $offset
  * @param int    $initial
  * @param int    $expire
  *
  * @return int|bool
  */
 protected function doIncrement($key, $offset, $initial, $expire)
 {
     $value = $this->get($key, $token);
     if ($value === false) {
         $this->set($key, $initial, $expire);
         return $initial;
     }
     if (!is_numeric($value) || $value < 0) {
         return false;
     }
     $value += $offset;
     // value can never be lower than 0
     $value = max(0, $value);
     $success = $this->client->cas($token, $key, $value, $expire);
     return $success ? $value : false;
 }
Ejemplo n.º 10
0
 /**
  * Set|update cache key.
  *
  * @since 151216 Memcached utilities.
  *
  * @param string     $primary_key   Primary key.
  * @param string|int $sub_key       Sub-key to set.
  * @param string     $value         Value to cache (1MB max).
  * @param int        $expires_after Expires after (in seconds).
  *
  * @return bool True on success.
  */
 public function set(string $primary_key, $sub_key, $value, int $expires_after = 0) : bool
 {
     if (!$this->Pool) {
         return false;
         // Not possible.
     }
     $time = time();
     $expires_after = max(0, $expires_after);
     $expires = $expires_after ? $time + $expires_after : 0;
     if (!($key = $this->key($primary_key, $sub_key))) {
         return false;
         // Fail; e.g., race condition.
     } elseif ($value === null || is_resource($value)) {
         throw $this->c::issue('Incompatible data type.');
     }
     do {
         // Avoid race issues with a loop.
         $attempts = $attempts ?? 0;
         ++$attempts;
         // Counter.
         $this->Pool->get($key, null, $cas);
         if ($this->Pool->getResultCode() === \Memcached::RES_NOTFOUND) {
             if ($this->Pool->add($key, $value, $expires)) {
                 return true;
                 // All good; stop here.
             }
         } elseif ($this->Pool->cas($cas, $key, $value, $expires)) {
             return true;
             // All good; stop here.
         }
         $result_code = $this->Pool->getResultCode();
         //
     } while ($attempts < $this::MAX_WRITE_ATTEMPTS && ($result_code === \Memcached::RES_NOTSTORED || $result_code === \Memcached::RES_DATA_EXISTS));
     return false;
     // Fail; e.g., race condition or unexpected error.
 }
Ejemplo n.º 11
0
 public function testCasFailure()
 {
     $request = new MemcacheSetRequest();
     $item = $request->addItem();
     $item->setKey("widgets_float");
     $item->setValue("2");
     $item->setFlags(6);
     // float
     $item->setCasId(12345);
     $item->setSetPolicy(SetPolicy::CAS);
     $item->setExpirationTime(30);
     $response = new MemcacheSetResponse();
     $response->addSetStatus(SetStatusCode::EXISTS);
     $this->apiProxyMock->expectCall('memcache', 'Set', $request, $response);
     $memcached = new Memcached();
     $memcached->setOption(Memcached::OPT_PREFIX_KEY, "widgets_");
     $this->assertFalse($memcached->cas(12345, "float", 2.0, 30));
     $this->assertEquals($memcached->getResultCode(), Memcached::RES_DATA_EXISTS);
     $this->apiProxyMock->verify();
 }
Ejemplo n.º 12
0
<?php

$m = new Memcached();
$m->addServer('127.0.0.1', 11211);
do {
    $ips = $m->get('ips', null, $cas);
    if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
        $ips = array($_SERVER['REMOTE_ADDR']);
        $m->add('ips', $ips);
    } else {
        $ips[] = $_SERVER['REMOTE_ADDR'];
        $m->cas($cas, 'ips', $ips);
    }
} while ($m->getResultCode() != Memcached::RES_SUCCESS);
Ejemplo n.º 13
0
 protected function cas($casToken, $key, $value, $exptime = 0)
 {
     return $this->client->cas($casToken, $this->validateKeyEncoding($key), $value, $this->fixExpiry($exptime));
 }
Ejemplo n.º 14
0
<?php

$memc = new Memcached();
$memc->addServer('localhost', '11211');
$key = 'cas_test';
var_dump($memc->set($key, 10, 60));
var_dump($memc->get($key, null, $cas));
var_dump(is_double($cas));
var_dump($memc->cas($cas, $key, 11, 60));
var_dump($memc->get($key));
var_dump($memc->cas($cas, $key, 12, 60));
var_dump($memc->get($key));
Ejemplo n.º 15
0
 /**
  * Sets the value for this key only if the value hasn't changed in the cache
  * since it was originally pulled
  *
  * @param \r8\Cache\Result $result A result object that was returned by
  *      the getForUpdate method
  * @param mixed $value The value to set
  * @param Integer $expire The lifespan of this cache value, in seconds
  * @return \r8\iface\Cache Returns a self reference
  */
 public function setIfSame(\r8\Cache\Result $result, $value, $expire = 0)
 {
     $this->memcached->cas($result->getHash(), $this->prepareKey($result->getKey()), $value, $this->prepareExpire($expire));
     $this->handleErrors();
     return $this;
 }
 /**
  * @inheritdoc
  */
 public function cas($cas_token, $key, $value, $expiration = null)
 {
     $key = $this->prefix . $key;
     return parent::cas($cas_token, $key, $value, $expiration);
 }