Use transparent cache compression
authorMichael M Slusarz <slusarz@curecanti.org>
Mon, 4 Oct 2010 18:55:52 +0000 (12:55 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Mon, 4 Oct 2010 19:11:11 +0000 (13:11 -0600)
framework/Imap_Client/lib/Horde/Imap/Client.php
framework/Imap_Client/lib/Horde/Imap/Client/Cache.php
framework/Imap_Client/package.xml
horde/config/conf.xml
imp/config/backends.php.dist
imp/lib/Imap.php
imp/scripts/query-imap-cache.php

index 4b8099c..acea9ec 100644 (file)
@@ -115,13 +115,11 @@ class Horde_Imap_Client
      *
      * Optional Parameters:
      * --------------------
-     * cache - (array) If set, caches data from fetch() calls. Requires
-     *         Horde_Cache and Horde_Serialize to be installed. The array can
-     *         contain the following keys (see Horde_Imap_Client_Cache:: for
-     *         default values):
+     * cache - (array) If set, caches data from fetch() calls. Requires the
+     *         horde/Cache package to be installed. The array can contain the
+     *         following keys (see Horde_Imap_Client_Cache:: for default
+     *         values):
      *   cacheob - [REQUIRED] (Horde_Cache) The cache object to use.
-     *   compress - [OPTIONAL] (string) Compression to use on the cached data.
-     *              VALUES: false, 'gzip' or 'lzf'.
      *   fields - [OPTIONAL] (array) The fetch criteria to cache. If not
      *            defined, all cacheable data is cached. The following is a
      *            list of criteria that can be cached:
index d38a233..ec87f17 100644 (file)
@@ -3,7 +3,7 @@
  * Horde_Imap_Client_Cache:: provides an interface to cache various data
  * retrieved from the IMAP server.
  *
- * Requires Horde_Cache and Horde_Serialize packages.
+ * Requires the horde/Cache package.
  *
  * <pre>
  * REQUIRED Parameters:
@@ -15,9 +15,6 @@
  *
  * Optional Parameters:
  * ====================
- * 'compress' - (string) Compression to use on the cached data.
- *              Either false, 'gzip' or 'lzf'.
- *              DEFAULT: No compression
  * 'debug' - (resource) If set, will output debug information to the stream
  *           identified.
  *           DEFAULT: No debug output
@@ -130,31 +127,9 @@ class Horde_Imap_Client_Cache
             'slicesize' => 50
         ), array_filter($params));
 
-        $compress = null;
-        if (!empty($params['compress'])) {
-            switch ($params['compress']) {
-            case 'gzip':
-                if (Horde_Serialize::hasCapability(Horde_Serialize::GZ_COMPRESS)) {
-                    $compress = Horde_Serialize::GZ_COMPRESS;
-                }
-                break;
-
-            case 'lzf':
-                if (Horde_Serialize::hasCapability(Horde_Serialize::LZF)) {
-                    $compress = Horde_Serialize::LZF;
-                }
-                break;
-            }
-
-            if (is_null($compress)) {
-                throw new InvalidArgumentException('Horde_Cache does not support the compression type given.');
-            }
-        }
-
         $this->_cache = $params['cacheob'];
 
         $this->_params = array(
-            'compress' => $compress,
             'debug' => $params['debug'],
             'hostspec' => $params['hostspec'],
             'lifetime' => intval($params['lifetime']),
@@ -169,7 +144,6 @@ class Horde_Imap_Client_Cache
      */
     public function __destruct()
     {
-        $compress = $this->_params['compress'];
         $lifetime = $this->_params['lifetime'];
 
         foreach ($this->_save as $mbox => $uids) {
@@ -182,11 +156,8 @@ class Horde_Imap_Client_Cache
 
                 /* Get the list of IDs to save. */
                 foreach (array_keys($sptr['slice'], $slice) as $uid) {
-                    /* Compress individual UID entries. We will worry about
-                     * error checking when decompressing (cache data will
-                     * automatically be invalidated then). */
                     if (isset($dptr[$uid])) {
-                        $data[$uid] = ($compress && is_array($dptr[$uid])) ? Horde_Serialize::serialize($dptr[$uid], array(Horde_Serialize::BASIC, $compress)) : $dptr[$uid];
+                        $data[$uid] = $dptr[$uid];
                     }
                 }
 
@@ -195,12 +166,12 @@ class Horde_Imap_Client_Cache
                     // If empty, we can expire the cache.
                     $this->_cache->expire($cid);
                 } else {
-                    $this->_cache->set($cid, Horde_Serialize::serialize($data, Horde_Serialize::BASIC), $lifetime);
+                    $this->_cache->set($cid, serialize($data), $lifetime);
                 }
             }
 
             // Save the slicemap
-            $this->_cache->set($this->_getCID($mbox, 'slicemap'), Horde_Serialize::serialize($sptr, Horde_Serialize::BASIC), $lifetime);
+            $this->_cache->set($this->_getCID($mbox, 'slicemap'), serialize($sptr), $lifetime);
         }
     }
 
@@ -468,7 +439,7 @@ class Horde_Imap_Client_Cache
             return;
         }
 
-        $data = Horde_Serialize::unserialize($data, Horde_Serialize::BASIC);
+        $data = @unserialize($data);
         if (!is_array($data)) {
             return;
         }
@@ -557,23 +528,15 @@ class Horde_Imap_Client_Cache
             return;
         }
 
-        $compress = $this->_params['compress'];
         $ptr = &$this->_data[$mailbox]['data'];
         $todelete = array();
 
         foreach ($uids as $val) {
-            if (isset($ptr[$val]) && !is_array($ptr[$val])) {
-                $success = false;
-                if (!is_null($compress)) {
-                    $res = Horde_Serialize::unserialize($ptr[$val], array($compress, Horde_Serialize::BASIC));
-                    if (!is_a($res, 'PEAR_Error')) {
-                        $ptr[$val] = $res;
-                        $success = true;
-                    }
-                }
-                if (!$success) {
-                    $todelete[] = $val;
-                }
+            if (isset($ptr[$val]) &&
+                ($res = @unserialize($ptr[$val]))) {
+                $ptr[$val] = $res;
+            } else {
+                $todelete[] = $val;
             }
         }
 
@@ -594,7 +557,7 @@ class Horde_Imap_Client_Cache
     {
         if (!isset($this->_slicemap[$mailbox])) {
             if (($data = $this->_cache->get($this->_getCID($mailbox, 'slicemap'), $this->_params['lifetime'])) !== false) {
-                $slice = Horde_Serialize::unserialize($data, Horde_Serialize::BASIC);
+                $slice = @unserialize($data);
                 if (is_array($slice)) {
                     $this->_slicemap[$mailbox] = $slice;
                 }
index 96586af..ef878f2 100644 (file)
@@ -115,10 +115,6 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <channel>pear.horde.org</channel>
    </package>
    <package>
-     <name>Serialize</name>
-     <channel>pear.horde.org</channel>
-   </package>
-   <package>
     <name>Stream_Filter</name>
     <channel>pear.horde.org</channel>
    </package>
index 3884ea4..51dc33e 100644 (file)
      </configsection>
     </case>
    </configswitch>
+   <configboolean name="compress" required="false" desc="Compress cached
+   data? Requires the 'lzf' PECL package to be installed">true</configboolean>
    <configswitch name="use_memorycache" required="false" desc="Use a
    separate memory cache driver to store data in memory? If data is not found
    in this driver, we will fall back to accessing the persistent backend. This
index a44d919..2c238cf 100644 (file)
  *        caching should be enabled on these servers.
  *
  *        The following optional configuration items are available:
- *          'compress' - (string) Should the contents of the cache files be
- *                       compressed before they are stored? This results in
- *                       reduced memory usage when retrieving the data at the
- *                       expense of slightly increased CPU usage. Either
- *                       false (no compression - DEFAULT), 'gzip' or 'lzf'.
- *                       'gzip' provides greater compression, and is generally
- *                       built into PHP, but is slower. 'lzf' requires
- *                       installation of a separate PECL module and provides
- *                       less compression but is extremely fast (within 5% of
- *                       regular string operations).  If available, 'lzf' is
- *                       HIGHLY RECOMMENDED.
  *          'lifetime' - (integer) The lifetime, in seconds, of the cached
  *                       data.
  *          'slicesize' - (integer) The number of messages stored in each
index 7974db9..93886ff 100644 (file)
@@ -190,7 +190,6 @@ class IMP_Imap
 
         return array(
             'cacheob' => $ob,
-            'compress' => empty($config['compress']) ? false : $config['compress'],
             'lifetime' => empty($config['lifetime']) ? false : $config['lifetime'],
             'slicesize' => empty($config['slicesize']) ? false : $config['slicesize'],
         );
index d9b419d..32b1440 100755 (executable)
@@ -122,6 +122,8 @@ $opts = array(
     0 => 'Exit'
 );
 
+$use_lzf = (!empty($conf['cache']['compress']) && Horde_Util::extensionExists('lzf'));
+
 while (true) {
     $cli->writeln();
 
@@ -173,21 +175,16 @@ while (true) {
                 $cli->message('Mailbox: ' . $cli->green($mbox));
                 $cli->message('Cached messages: ' . count($res) . ' [' . $ob->utils->toSequenceString($res) . ']');
 
-                $gzip_size = $lzf_size = $total_size = 0;
+                $lzf_size = $total_size = 0;
                 foreach ($ob->cache->get($mbox, $res, null) as $val) {
                     $data = serialize($val);
                     $total_size += strlen($data);
-                    if (Horde_Serialize::hasCapability(Horde_Serialize::GZ_COMPRESS)) {
-                        $gzip_size += strlen(Horde_Serialize::serialize($data, Horde_Serialize::GZ_COMPRESS));
-                    }
-                    if (Horde_Serialize::hasCapability(Horde_Serialize::LZF)) {
-                        $lzf_size += strlen(Horde_Serialize::serialize($data, Horde_Serialize::LZF));
+                    if ($use_lzf) {
+                        $lzf_size += strlen(lzf_compress($data));
                     }
                 }
+
                 $cli->message('Approximate size (bytes): ' . $total_size);
-                if (!empty($gzip_size)) {
-                    $cli->message('Approximate size - GZIP (bytes): ' . $gzip_size . ' [' . $cli->red(100 - round($gzip_size / $total_size * 100, 1) . '% savings') . ']');
-                }
                 if (!empty($lzf_size)) {
                     $cli->message('Approximate size - LZF (bytes): ' . $lzf_size . ' [' . $cli->red(100 - round($lzf_size / $total_size * 100, 1) . '% savings') . ']');
                 }
@@ -231,12 +228,9 @@ while (true) {
 
             $data = serialize($res[$uid]);
             $cli->message('Approximate size (bytes): ' . strlen($data));
-            if (Horde_Serialize::hasCapability(Horde_Serialize::GZ_COMPRESS)) {
-                $gzip_size = strlen(Horde_Serialize::serialize($data, Horde_Serialize::GZ_COMPRESS));
-                $cli->message('Approximate size - GZIP (bytes): ' . $gzip_size . ' [' . $cli->red(100 - round($gzip_size / $total_size * 100, 1) . '% savings]') . '');
-            }
-            if (Horde_Serialize::hasCapability(Horde_Serialize::LZF)) {
-                $lzf_size += strlen(Horde_Serialize::serialize($data, Horde_Serialize::LZF));
+
+            if ($use_lzf) {
+                $lzf_size += strlen(lzf_compress($data));
                 $cli->message('Approximate size - LZF (bytes): ' . $lzf_size . ' [' . $cli->red(100 -round($lzf_size / $total_size * 100, 1) . '% savings') . ']');
             }