Support igbinary for object cache serialization
Support igbinary for object cache serialization

--- a/include/cache/Cache_File.class.php
+++ b/include/cache/Cache_File.class.php
@@ -10,6 +10,20 @@
 class GitPHP_Cache_File implements GitPHP_CacheStrategy_Interface
 {
 	/**
+	 * Gzipped cache
+	 *
+	 * @var int
+	 */
+	const CacheTypeGzip = 1;
+
+	/**
+	 * Igbinary cache
+	 *
+	 * @var int
+	 */
+	const CacheTypeIgbinary = 2;
+
+	/**
 	 * Cache file directory
 	 *
 	 * @var string
@@ -22,14 +36,22 @@
 	 * @var int
 	 */
 	protected $compressThreshold = 0;
+
+	/**
+	 * Enable igbinary
+	 *
+	 * @var boolean
+	 */
+	protected $igbinary = false;
 
 	/**
 	 * Constructor
 	 *
 	 * @param string $cacheDir cache dir
 	 * @param int $compressThreshold threshold to start compressing data at
-	 */
-	public function __construct($cacheDir, $compressThreshold = 0)
+	 * @param boolean $igbinary whether to use igbinary, null to autodetect
+	 */
+	public function __construct($cacheDir, $compressThreshold = 0, $igbinary = null)
 	{
 		if (file_exists($cacheDir)) {
 			if (!is_dir($cacheDir)) {
@@ -50,6 +72,14 @@
 		}
 
 		$this->compressThreshold = $compressThreshold;
+
+		if ($igbinary === null) {
+			$this->igbinary = function_exists('igbinary_serialize');
+		} else if ($igbinary) {
+			if (!function_exists('igbinary_serialize'))
+				throw new Exception('Igbinary is not present');
+			$this->igbinary = $igbinary;
+		}
 	}
 
 	/**
@@ -63,11 +93,7 @@
 		if (empty($key))
 			return false;
 
-		$data = $this->Load($key);
-		if ($data === false)
-			return false;
-
-		return unserialize($data);
+		return $this->Load($key);
 	}
 
 	/**
@@ -86,7 +112,7 @@
 		if ($lifetime >= 0)
 			$expire = time() + $lifetime;
 
-		$this->Save($key, serialize($value), $expire);
+		$this->Save($key, $value, $expire);
 	}
 
 	/**
@@ -154,7 +180,7 @@
 
 		$flags = strtok($contents, "\n");
 		$expire = strtok($flags, "|");
-		$compressed = strtok("|");
+		$cachetype = strtok("|");
 
 		if (!empty($expire) && ($expire < time())) {
 			unlink($file);
@@ -167,26 +193,41 @@
 			return false;
 		}
 
-		if ($compressed == '1')
-			$data = gzuncompress($data);
+		if ($cachetype == GitPHP_Cache_File::CacheTypeIgbinary) {
+			if ($this->igbinary) {
+				$data = igbinary_unserialize($data);
+			} else {
+				unlink($file);
+				return false;
+			}
+		} else if ($cachetype == GitPHP_Cache_File::CacheTypeGzip) {
+			$data = unserialize(gzuncompress($data));
+		} else {
+			$data = unserialize($data);
+		}
 
 		return $data;
 	}
 
 	/**
-	 * Save a key's serialized data
-	 *
-	 * @param string $key cache key
-	 * @param string $data serialized data
+	 * Save a key's data
+	 *
+	 * @param string $key cache key
+	 * @param mixed $data data
 	 * @param int $expire expiration instant
 	 */
 	private function Save($key, $data, $expire = '')
 	{
 		$flags = $expire;
 
-		if (($this->compressThreshold > 0) && (strlen($data) > $this->compressThreshold)) {
-			$data = gzcompress($data);
-			$flags .= '|1';
+		if ($this->igbinary) {
+			$data = igbinary_serialize($data);
+			$flags .= '|' . GitPHP_Cache_File::CacheTypeIgbinary;
+		} else if (($this->compressThreshold > 0) && (strlen($data) > $this->compressThreshold)) {
+			$data = gzcompress(serialize($data));
+			$flags .= '|' . GitPHP_Cache_File::CacheTypeGzip;
+		} else {
+			$data = serialize($data);
 		}
 
 		file_put_contents($this->cacheDir . $this->KeyToFile($key), $flags . "\n" . $data);

--- a/test/cache/CacheTest.php
+++ b/test/cache/CacheTest.php
@@ -11,7 +11,7 @@
 {
 	public function testFile()
 	{
-		$cache = new GitPHP_Cache(new GitPHP_Cache_File(GITPHP_CACHEDIR . 'objects'));
+		$cache = new GitPHP_Cache(new GitPHP_Cache_File(GITPHP_CACHEDIR . 'objects', 0, false));
 		$cache->Clear();
 
 		$this->assertFalse($cache->Exists('testkey1|testkey2'));
@@ -33,7 +33,7 @@
 
 	public function testFileLifetime()
 	{
-		$cache = new GitPHP_Cache(new GitPHP_Cache_File(GITPHP_CACHEDIR . 'objects'));
+		$cache = new GitPHP_Cache(new GitPHP_Cache_File(GITPHP_CACHEDIR . 'objects', 0, false));
 		$cache->Clear();
 
 		$cache->Set('testkey1|testkey2', 'testvalue1', 1);
@@ -48,7 +48,35 @@
 
 	public function testFileCompressed()
 	{
-		$cache = new GitPHP_Cache(new GitPHP_Cache_File(GITPHP_CACHEDIR . 'objects'), 20);
+		$cache = new GitPHP_Cache(new GitPHP_Cache_File(GITPHP_CACHEDIR . 'objects', 19, false));
+		$cache->Clear();
+
+		$this->assertFalse($cache->Exists('testkey1|testkey2'));
+		$cache->Set('testkey1|testkey2', '12345678');
+		$this->assertTrue($cache->Exists('testkey1|testkey2'));
+		$this->assertEquals('12345678', $cache->Get('testkey1|testkey2'));
+
+		$this->assertFalse($cache->Get('testkey3|testkey4'));
+		$cache->Set('testkey3|testkey4', '12345678901234567890');
+		$this->assertTrue($cache->Exists('testkey3|testkey4'));
+		$this->assertEquals('12345678901234567890', $cache->Get('testkey3|testkey4'));
+
+		$cache->Delete('testkey1|testkey2');
+		$this->assertFalse($cache->Exists('testkey1|testkey2'));
+
+		$this->assertTrue($cache->Exists('testkey3|testkey4'));
+
+		$cache->Clear();
+		$this->assertFalse($cache->Exists('testkey3|testkey4'));
+	}
+
+	public function testFileIgbinary()
+	{
+		if (!function_exists('igbinary_serialize')) {
+			$this->markTestSkipped();
+			return;
+		}
+		$cache = new GitPHP_Cache(new GitPHP_Cache_File(GITPHP_CACHEDIR . 'objects', 0, true));
 		$cache->Clear();
 
 		$this->assertFalse($cache->Exists('testkey1|testkey2'));

comments