MediaWiki  master
HashBagOStuff.php
Go to the documentation of this file.
1 <?php
33  protected $bag = [];
35  protected $maxCacheKeys;
36 
38  private $token;
39 
41  private static $casCounter = 0;
42 
43  const KEY_VAL = 0;
44  const KEY_EXP = 1;
45  const KEY_CAS = 2;
46 
54  function __construct( $params = [] ) {
55  $params['segmentationSize'] = $params['segmentationSize'] ?? INF;
56  parent::__construct( $params );
57 
58  $this->token = microtime( true ) . ':' . mt_rand();
59  $this->maxCacheKeys = $params['maxKeys'] ?? INF;
60  if ( $this->maxCacheKeys <= 0 ) {
61  throw new InvalidArgumentException( '$maxKeys parameter must be above zero' );
62  }
63  }
64 
65  protected function doGet( $key, $flags = 0, &$casToken = null ) {
66  $casToken = null;
67 
68  if ( !$this->hasKey( $key ) || $this->expire( $key ) ) {
69  return false;
70  }
71 
72  // Refresh key position for maxCacheKeys eviction
73  $temp = $this->bag[$key];
74  unset( $this->bag[$key] );
75  $this->bag[$key] = $temp;
76 
77  $casToken = $this->bag[$key][self::KEY_CAS];
78 
79  return $this->bag[$key][self::KEY_VAL];
80  }
81 
82  protected function doSet( $key, $value, $exptime = 0, $flags = 0 ) {
83  // Refresh key position for maxCacheKeys eviction
84  unset( $this->bag[$key] );
85  $this->bag[$key] = [
86  self::KEY_VAL => $value,
87  self::KEY_EXP => $this->getExpirationAsTimestamp( $exptime ),
88  self::KEY_CAS => $this->token . ':' . ++self::$casCounter
89  ];
90 
91  if ( count( $this->bag ) > $this->maxCacheKeys ) {
92  reset( $this->bag );
93  $evictKey = key( $this->bag );
94  unset( $this->bag[$evictKey] );
95  }
96 
97  return true;
98  }
99 
100  protected function doAdd( $key, $value, $exptime = 0, $flags = 0 ) {
101  if ( $this->hasKey( $key ) && !$this->expire( $key ) ) {
102  return false; // key already set
103  }
104 
105  return $this->doSet( $key, $value, $exptime, $flags );
106  }
107 
108  protected function doDelete( $key, $flags = 0 ) {
109  unset( $this->bag[$key] );
110 
111  return true;
112  }
113 
114  public function incr( $key, $value = 1, $flags = 0 ) {
115  $n = $this->get( $key );
116  if ( $this->isInteger( $n ) ) {
117  $n = max( $n + (int)$value, 0 );
118  $this->bag[$key][self::KEY_VAL] = $n;
119 
120  return $n;
121  }
122 
123  return false;
124  }
125 
126  public function decr( $key, $value = 1, $flags = 0 ) {
127  return $this->incr( $key, -$value, $flags );
128  }
129 
133  public function clear() {
134  $this->bag = [];
135  }
136 
141  protected function expire( $key ) {
142  $et = $this->bag[$key][self::KEY_EXP];
143  if ( $et == self::TTL_INDEFINITE || $et > $this->getCurrentTime() ) {
144  return false;
145  }
146 
147  $this->doDelete( $key );
148 
149  return true;
150  }
151 
159  public function hasKey( $key ) {
160  return isset( $this->bag[$key] );
161  }
162 }
__construct( $params=[])
clear()
Clear all values in cache.
hasKey( $key)
Does this bag have a non-null value for the given key?
doDelete( $key, $flags=0)
getCurrentTime()
Definition: BagOStuff.php:523
doSet( $key, $value, $exptime=0, $flags=0)
decr( $key, $value=1, $flags=0)
static int $casCounter
CAS token counter.
doGet( $key, $flags=0, &$casToken=null)
Storage medium specific cache for storing items (e.g.
getExpirationAsTimestamp( $exptime)
Convert an optionally relative timestamp to an absolute time.
int $maxCacheKeys
Max entries allowed.
string $token
CAS token prefix for this instance.
isInteger( $value)
Check if a value is an integer.
doAdd( $key, $value, $exptime=0, $flags=0)
incr( $key, $value=1, $flags=0)