<?php
/**
- * Object caching using PHP arrays.
+ * Per-process memory cache for storing items.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
/**
- * This is a test of the interface, mainly. It stores things in an associative
- * array, which is not going to persist between program runs.
+ * Simple store for keeping values in an associative array for the current process.
+ *
+ * Data will not persist and is not shared with other processes.
*
* @ingroup Cache
*/
class HashBagOStuff extends BagOStuff {
- /** @var array */
- protected $bag;
+ /** @var mixed[] */
+ protected $bag = [];
+ /** @var int Max entries allowed */
+ protected $maxCacheKeys;
+
+ const KEY_VAL = 0;
+ const KEY_EXP = 1;
- function __construct( $params = array() ) {
+ /**
+ * @param array $params Additional parameters include:
+ * - maxKeys : only allow this many keys (using oldest-first eviction)
+ */
+ function __construct( $params = [] ) {
parent::__construct( $params );
- $this->bag = array();
+
+ $this->maxCacheKeys = isset( $params['maxKeys'] ) ? $params['maxKeys'] : INF;
+ if ( $this->maxCacheKeys <= 0 ) {
+ throw new InvalidArgumentException( '$maxKeys parameter must be above zero' );
+ }
}
protected function expire( $key ) {
- $et = $this->bag[$key][1];
-
- if ( ( $et == 0 ) || ( $et > time() ) ) {
+ $et = $this->bag[$key][self::KEY_EXP];
+ if ( $et == self::TTL_INDEFINITE || $et > time() ) {
return false;
}
return true;
}
+ /**
+ * Does this bag have a non-null value for the given key?
+ *
+ * @param string $key
+ * @return bool
+ * @since 1.27
+ */
+ protected function hasKey( $key ) {
+ return isset( $this->bag[$key] );
+ }
+
protected function doGet( $key, $flags = 0 ) {
- if ( !isset( $this->bag[$key] ) ) {
+ if ( !$this->hasKey( $key ) ) {
return false;
}
return false;
}
- return $this->bag[$key][0];
+ // Refresh key position for maxCacheKeys eviction
+ $temp = $this->bag[$key];
+ unset( $this->bag[$key] );
+ $this->bag[$key] = $temp;
+
+ return $this->bag[$key][self::KEY_VAL];
}
public function set( $key, $value, $exptime = 0, $flags = 0 ) {
- $this->bag[$key] = array( $value, $this->convertExpiry( $exptime ) );
+ // Refresh key position for maxCacheKeys eviction
+ unset( $this->bag[$key] );
+ $this->bag[$key] = [
+ self::KEY_VAL => $value,
+ self::KEY_EXP => $this->convertExpiry( $exptime )
+ ];
+
+ if ( count( $this->bag ) > $this->maxCacheKeys ) {
+ reset( $this->bag );
+ $evictKey = key( $this->bag );
+ unset( $this->bag[$evictKey] );
+ }
+
return true;
}
- function delete( $key ) {
+ public function delete( $key ) {
unset( $this->bag[$key] );
return true;
}
+
+ public function clear() {
+ $this->bag = [];
+ }
}