Something went wrong. Try again.
@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
Something went wrong. Try again.
3.5 kB · 153 lines
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154<?php
/** * @task memcache Managing Memcache */final class PhutilMemcacheKeyValueCache extends PhutilKeyValueCache {
private $servers = array(); private $connections = array();
/* -( Key-Value Cache Implementation )------------------------------------- */
public function isAvailable() { return function_exists('memcache_pconnect'); }
public function getKeys(array $keys) { $buckets = $this->bucketKeys($keys); $results = array();
foreach ($buckets as $bucket => $bucket_keys) { $conn = $this->getConnection($bucket); $result = $conn->get($bucket_keys); if (!$result) { // If the call fails, treat it as a miss on all keys. $result = array(); }
$results += $result; }
return $results; }
public function setKeys(array $keys, $ttl = null) { $buckets = $this->bucketKeys(array_keys($keys));
// Memcache interprets TTLs as: // // - Seconds from now, for values from 1 to 2592000 (30 days). // - Epoch timestamp, for values larger than 2592000. // // We support only relative TTLs, so convert excessively large relative // TTLs into epoch TTLs. if ($ttl > 2592000) { $effective_ttl = time() + $ttl; } else { $effective_ttl = $ttl; }
foreach ($buckets as $bucket => $bucket_keys) { $conn = $this->getConnection($bucket);
foreach ($bucket_keys as $key) { $conn->set($key, $keys[$key], 0, $effective_ttl); } }
return $this; }
public function deleteKeys(array $keys) { $buckets = $this->bucketKeys($keys);
foreach ($buckets as $bucket => $bucket_keys) { $conn = $this->getConnection($bucket); foreach ($bucket_keys as $key) { $conn->delete($key); } }
return $this; }
public function destroyCache() { foreach ($this->servers as $key => $spec) { $this->getConnection($key)->flush(); } return $this; }
/* -( Managing Memcache )-------------------------------------------------- */
/** * Set available memcache servers. For example: * * $cache->setServers( * array( * array( * 'host' => '10.0.0.20', * 'port' => 11211, * ), * array( * 'host' => '10.0.0.21', * 'port' => 11211, * ), * )); * * @param array $servers List of server specifications. * @return $this * @task memcache */ public function setServers(array $servers) { $this->servers = array_values($servers); return $this; }
private function bucketKeys(array $keys) { $buckets = array(); $n = count($this->servers);
if (!$n) { throw new PhutilInvalidStateException('setServers'); }
foreach ($keys as $key) { $bucket = (int)((crc32($key) & 0x7FFFFFFF) % $n); $buckets[$bucket][] = $key; }
return $buckets; }
/** * @phutil-external-symbol function memcache_pconnect */ private function getConnection($server) { if (empty($this->connections[$server])) { $spec = $this->servers[$server]; $host = $spec['host']; $port = $spec['port'];
$conn = memcache_pconnect($host, $spec['port']);
if (!$conn) { throw new Exception( pht( 'Unable to connect to memcache server (%s:%d)!', $host, $port)); }
$this->connections[$server] = $conn; } return $this->connections[$server]; }
}