[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/cache/ -> PhabricatorKeyValueDatabaseCache.php (source)

   1  <?php
   2  
   3  final class PhabricatorKeyValueDatabaseCache
   4    extends PhutilKeyValueCache {
   5  
   6    const CACHE_FORMAT_RAW        = 'raw';
   7    const CACHE_FORMAT_DEFLATE    = 'deflate';
   8  
   9    public function setKeys(array $keys, $ttl = null) {
  10      if ($keys) {
  11        $map = $this->digestKeys(array_keys($keys));
  12        $conn_w = $this->establishConnection('w');
  13  
  14        $sql = array();
  15        foreach ($map as $key => $hash) {
  16          $value = $keys[$key];
  17  
  18          list($format, $storage_value) = $this->willWriteValue($key, $value);
  19  
  20          $sql[] = qsprintf(
  21            $conn_w,
  22            '(%s, %s, %s, %B, %d, %nd)',
  23            $hash,
  24            $key,
  25            $format,
  26            $storage_value,
  27            time(),
  28            $ttl ? (time() + $ttl) : null);
  29        }
  30  
  31        $guard = AphrontWriteGuard::beginScopedUnguardedWrites();
  32          foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {
  33              queryfx(
  34                $conn_w,
  35                'INSERT INTO %T
  36                  (cacheKeyHash, cacheKey, cacheFormat, cacheData,
  37                    cacheCreated, cacheExpires) VALUES %Q
  38                  ON DUPLICATE KEY UPDATE
  39                    cacheKey = VALUES(cacheKey),
  40                    cacheFormat = VALUES(cacheFormat),
  41                    cacheData = VALUES(cacheData),
  42                    cacheCreated = VALUES(cacheCreated),
  43                    cacheExpires = VALUES(cacheExpires)',
  44                $this->getTableName(),
  45                $chunk);
  46          }
  47        unset($guard);
  48      }
  49  
  50      return $this;
  51    }
  52  
  53    public function getKeys(array $keys) {
  54      $results = array();
  55      if ($keys) {
  56        $map = $this->digestKeys($keys);
  57  
  58        $rows = queryfx_all(
  59          $this->establishConnection('r'),
  60          'SELECT * FROM %T WHERE cacheKeyHash IN (%Ls)',
  61          $this->getTableName(),
  62          $map);
  63        $rows = ipull($rows, null, 'cacheKey');
  64  
  65        foreach ($keys as $key) {
  66          if (empty($rows[$key])) {
  67            continue;
  68          }
  69  
  70          $row = $rows[$key];
  71  
  72          if ($row['cacheExpires'] && ($row['cacheExpires'] < time())) {
  73            continue;
  74          }
  75  
  76          try {
  77            $results[$key] = $this->didReadValue(
  78              $row['cacheFormat'],
  79              $row['cacheData']);
  80          } catch (Exception $ex) {
  81            // Treat this as a cache miss.
  82            phlog($ex);
  83          }
  84        }
  85      }
  86  
  87      return $results;
  88    }
  89  
  90    public function deleteKeys(array $keys) {
  91      if ($keys) {
  92        $map = $this->digestKeys($keys);
  93        queryfx(
  94          $this->establishConnection('w'),
  95          'DELETE FROM %T WHERE cacheKeyHash IN (%Ls)',
  96          $this->getTableName(),
  97          $keys);
  98      }
  99  
 100      return $this;
 101    }
 102  
 103    public function destroyCache() {
 104      queryfx(
 105        $this->establishConnection('w'),
 106        'DELETE FROM %T',
 107        $this->getTableName());
 108      return $this;
 109    }
 110  
 111  
 112  /* -(  Raw Cache Access  )--------------------------------------------------- */
 113  
 114  
 115    public function establishConnection($mode) {
 116      // TODO: This is the only concrete table we have on the database right
 117      // now.
 118      return id(new PhabricatorMarkupCache())->establishConnection($mode);
 119    }
 120  
 121    public function getTableName() {
 122      return 'cache_general';
 123    }
 124  
 125  
 126  /* -(  Implementation  )----------------------------------------------------- */
 127  
 128  
 129    private function digestKeys(array $keys) {
 130      $map = array();
 131      foreach ($keys as $key) {
 132        $map[$key] = PhabricatorHash::digestForIndex($key);
 133      }
 134      return $map;
 135    }
 136  
 137    private function willWriteValue($key, $value) {
 138      if (!is_string($value)) {
 139        throw new Exception('Only strings may be written to the DB cache!');
 140      }
 141  
 142      static $can_deflate;
 143      if ($can_deflate === null) {
 144        $can_deflate = function_exists('gzdeflate') &&
 145                       PhabricatorEnv::getEnvConfig('cache.enable-deflate');
 146      }
 147  
 148      if ($can_deflate) {
 149        $deflated = PhabricatorCaches::maybeDeflateData($value);
 150        if ($deflated !== null) {
 151          return array(self::CACHE_FORMAT_DEFLATE, $deflated);
 152        }
 153      }
 154  
 155      return array(self::CACHE_FORMAT_RAW, $value);
 156    }
 157  
 158    private function didReadValue($format, $value) {
 159      switch ($format) {
 160        case self::CACHE_FORMAT_RAW:
 161          return $value;
 162        case self::CACHE_FORMAT_DEFLATE:
 163          return PhabricatorCaches::inflateData($value);
 164        default:
 165          throw new Exception('Unknown cache format.');
 166      }
 167    }
 168  
 169  
 170  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1