- <?php
- /**
- * Perforce Swarm
- *
- * @copyright 2013 Perforce Software. All rights reserved.
- * @license Please see LICENSE.txt in top-level folder of this distribution.
- * @version <release>/<patch>
- */
- namespace Record\Cache;
-
- /**
- * Memory efficient iterator for arrays that have been written AND indexed by ArrayWriter
- */
- class ArrayReader implements \ArrayAccess, \Iterator
- {
- protected $file = null;
- protected $handle = null;
- protected $index = null;
-
- /**
- * Setup a new array reader
- *
- * @param string $file the file to read array from
- */
- public function __construct($file)
- {
- $this->file = $file;
- }
-
- public function openFile()
- {
- $file = $this->file;
- $indexFile = $file . ArrayWriter::INDEX_SUFFIX;
- if (!is_string($file) || !file_exists($file)) {
- throw new \RuntimeException("Cannot open file '" . $file . "'. File does not exist.");
- }
-
- $this->handle = @fopen($file, 'r');
- if ($this->handle === false) {
- throw new \RuntimeException("Unable to open file ('" . $file . "') for reading.");
- }
-
- // if anything goes wrong past this point, make sure we close/unlock our file
- try {
- // wait for a read lock to ensure file is not being actively written to
- $locked = flock($this->handle, LOCK_SH);
- if ($locked === false) {
- throw new \RuntimeException("Unable to lock file ('" . $file . "') for reading.");
- }
-
- if (!file_exists($indexFile)) {
- throw new \RuntimeException("Cannot open index file '" . $indexFile . "'. File does not exist.");
- }
-
- // read the entire index into memory (impractical to stream)
- $this->index = unserialize(file_get_contents($indexFile));
- if ($this->index === false) {
- throw new \RuntimeException("Cannot unserialize index file ('" . $indexFile . "').");
- }
- } catch (\Exception $e) {
- $this->closeFile();
- throw $e;
- }
-
- return $this;
- }
-
- public function closeFile()
- {
- if (!is_resource($this->handle)) {
- throw new \RuntimeException("Cannot close file. File is not open.");
- }
-
- flock($this->handle, LOCK_UN);
- fclose($this->handle);
-
- return $this;
- }
-
- /**
- * Do a case-insensitive lookup for the given key - first match wins
- *
- * @param mixed $key the array key to look for
- * @return mixed the matching key (in original case) or false if no match
- */
- public function noCaseLookup($key)
- {
- // note we make a local-scope (lazy) copy to avoid mucking the cursor
- $index = $this->index;
- foreach ($index as $candidate => $value) {
- if (strcasecmp($key, $candidate) === 0) {
- return $candidate;
- }
- }
-
- return false;
- }
-
- public function offsetExists($key)
- {
- // attempt to match PHP's key casting behavior
- // http://php.net/manual/en/language.types.array.php
- if (is_object($key) || is_array($key)) {
- return false;
- }
- if (is_null($key)) {
- $key = "";
- }
- if (!is_string($key) && !is_int($key)) {
- $key = (int) $key;
- }
- return array_key_exists($key, $this->index);
- }
-
- public function offsetGet($key)
- {
- if (!$this->offsetExists($key)) {
- return null;
- }
-
- $offset = $this->index[$key][0];
- $length = $this->index[$key][1];
- fseek($this->handle, $offset);
-
- // need to wrap serialized key/value in array format 'a:1{...}'
- // so that it will unserialize correctly into key/value
- $entry = unserialize('a:1:{' . fread($this->handle, $length) . '}');
- return $entry ? current($entry) : false;
- }
-
- public function offsetSet($key, $value)
- {
- throw new \BadMethodCallException("Cannot set element. Array is read-only.");
- }
-
- public function offsetUnset($offset)
- {
- throw new \BadMethodCallException("Cannot unset element. Array is read-only.");
- }
-
- public function current()
- {
- return $this->offsetGet(key($this->index));
- }
-
- public function key()
- {
- return key($this->index);
- }
-
- public function next()
- {
- next($this->index);
- }
-
- public function rewind()
- {
- reset($this->index);
- }
-
- public function valid()
- {
- return key($this->index) !== null;
- }
- }
# |
Change |
User |
Description |
Committed |
|
#1
|
18334 |
Liz Lam |
initial add of jambox |
9 years ago
|
|