Sentmail SQL driver now supports split read/write operation
authorMichael M Slusarz <slusarz@curecanti.org>
Fri, 14 May 2010 19:01:37 +0000 (13:01 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Fri, 14 May 2010 19:02:10 +0000 (13:02 -0600)
imp/config/conf.xml
imp/docs/CHANGES
imp/lib/Injector/Binder/Sentmail.php
imp/lib/Sentmail.php
imp/lib/Sentmail/Sql.php

index b58fbb7..52a5f3e 100644 (file)
    be used to configure message limits or create favourite recipients
    lists. Enable this feature only if it doesn't violate privacy rules or laws
    in your country. What storage driver should we use?">sql
-    <case name="none" desc="None"/>
-    <case name="sql" desc="SQL">
+    <case name="Null" desc="None"/>
+    <case name="Sql" desc="SQL">
      <configsection name="params">
       <configinteger name="threshold" desc="How many days should we keep old
       log entries?">60</configinteger>
index 64e6a23..8e395c9 100644 (file)
@@ -2,6 +2,7 @@
 v5.0-git
 --------
 
+[mms] Sentmail SQL driver now supports split read/write operation.
 [mms] Pass compose message data to mailer backend via stream; much more
       efficient, especially with larger messages (Request #8909).
 [mms] Add strip attachments support in DIMP.
index 5f4ccea..881465c 100644 (file)
@@ -16,12 +16,27 @@ class IMP_Injector_Binder_Sentmail implements Horde_Injector_Binder
      */
     public function create(Horde_Injector $injector)
     {
-        if (empty($GLOBALS['conf']['sentmail']['driver'])) {
-            return IMP_Sentmail::factory();
+        $driver = empty($GLOBALS['conf']['sentmail']['driver'])
+            ? 'Null'
+            : $GLOBALS['conf']['sentmail']['driver'];
+        $params = Horde::getDriverConfig('sentmail', $driver);
+
+        if (strcasecmp($driver, 'Sql') === 0) {
+            $write_db = $injector->getInstance('Horde_Db_Pear')->getOb();
+
+            /* Check if we need to set up the read DB connection
+             * separately. */
+            if (empty($params['splitread'])) {
+                $params['db'] = $write_db;
+            } else {
+                $params['write_db'] = $write_db;
+                $params['db'] = $injector->getInstance('Horde_Db_Pear')->getOb('read');
+            }
+        } elseif (strcasecmp($driver, 'None') === 0) {
+            $driver = 'Null';
         }
 
-        $driver = $GLOBALS['conf']['sentmail']['driver'];
-        return IMP_Sentmail::factory($driver, Horde::getDriverConfig('sentmail', $driver));
+        return IMP_Sentmail::factory($driver, $params);
     }
 
     /**
index 366a511..7cae7d8 100644 (file)
@@ -21,29 +21,26 @@ class IMP_Sentmail
     protected $_params = array();
 
     /**
-     * Attempts to return a concrete IMP_Sentmail instance based on $driver.
+     * Attempts to return a concrete instance based on $driver.
      *
-     * @param string $driver  The type of the concrete IMP_Sentmail subclass
-     *                        to return.  The class name is based on the
-     *                        storage driver ($driver).  The code is
-     *                        dynamically included.
+     * @param string $driver  The type of the concrete subclass to return.
+     *                        The class name is based on the storage driver
+     *                        ($driver).
      * @param array $params   A hash containing any additional configuration
      *                        or connection parameters a subclass might need.
      *
-     * @return IMP_Sentmail  The newly created concrete IMP_Sentmail instance.
+     * @return IMP_Sentmail  The newly created concrete instance.
+     * @throws IMP_Exception
      */
-    static public function factory($driver = null, $params = array())
+    static public function factory($driver, $params = array())
     {
-        if ($driver && ($driver != 'none')) {
-            $class = 'IMP_Sentmail_' . ucfirst(basename($driver));
-            if (class_exists($class)) {
-                try {
-                    return new $class($params);
-                } catch (IMP_Exception $e) {}
-            }
+        $class = __CLASS__ . '_' . ucfirst(basename($driver));
+
+        if (class_exists($class)) {
+            return new $class($params);
         }
 
-        return new IMP_Sentmail($params);
+        throw new IMP_Exception('Driver not found: ' . $driver);
     }
 
     /**
index c223618..fdca735 100644 (file)
@@ -2,29 +2,18 @@
 /**
  * IMP_Sentmail implementation for PHP's PEAR database abstraction layer.
  *
- * Required values for $params:
- * <pre>
- * 'phptype'       The database type (e.g. 'pgsql', 'mysql', etc.).
- * 'table'         The name of the foo table in 'database'.
- * </pre>
- *
- * Required by some database implementations:
- * <pre>
- * 'database'      The name of the database.
- * 'hostspec'      The hostname of the database server.
- * 'protocol'      The communication protocol ('tcp', 'unix', etc.).
- * 'username'      The username with which to connect to the database.
- * 'password'      The password associated with 'username'.
- * 'options'       Additional options to pass to the database.
- * 'tty'           The TTY on which to connect to the database.
- * 'port'          The port on which to connect to the database.
- * </pre>
- *
  * The table structure can be created by the scripts/sql/imp_sentmail.sql
  * script.
  *
- * @author  Jan Schneider <jan@horde.org>
- * @package IMP
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @package  IMP
  */
 class IMP_Sentmail_Sql extends IMP_Sentmail
 {
@@ -33,52 +22,47 @@ class IMP_Sentmail_Sql extends IMP_Sentmail
      *
      * @var DB
      */
-    protected $_db;
+    protected $_db = '';
+
+    /**
+     * Handle for the current database connection, used for writing. Defaults
+     * to the same handle as $_db if a separate write database is not required.
+     *
+     * @var DB
+     */
+    protected $_write_db;
 
     /**
      * Constructor.
      *
-     * @param array $params  A hash containing connection parameters.
+     * @param array $params  Parameters:
+     * <pre>
+     * 'db' - (DB) [REQUIRED] The DB instance.
+     * 'table' - (string) The name of the sentmail table.
+     *           DEFAULT: 'imp_sentmail'
+     * 'write_db' - (DB) The write DB instance.
+     * </pre>
      *
      * @throws IMP_Exception
      */
-    protected function __construct($params = array())
+    public function __construct(array $params = array())
     {
-        parent::__construct($params);
-
-        try {
-            Horde::assertDriverConfig($this->_params, 'storage', array('phptype', 'table'));
-        } catch (Horde_Exception $e) {
-            throw new IMP_Exception($e);
+        if (!isset($params['db'])) {
+            throw new IMP_Exception('Missing db parameter.');
         }
+        $this->_db = $params['db'];
 
-        if (!isset($this->_params['database'])) {
-            $this->_params['database'] = '';
-        }
-        if (!isset($this->_params['username'])) {
-            $this->_params['username'] = '';
-        }
-        if (!isset($this->_params['hostspec'])) {
-            $this->_params['hostspec'] = '';
-        }
+        $this->_write_db = isset($params['write_db'])
+            ? $params['write_db']
+            : $this->_db;
 
-        /* Connect to the SQL server using the supplied parameters. */
-        $this->_db = DB::connect($this->_params,
-                                 array('persistent' => !empty($this->_params['persistent']),
-                                       'ssl' => !empty($this->_params['ssl'])));
-        if ($this->_db instanceof PEAR_Error) {
-            throw new IMP_Exception($this->_db);
-        }
+        unset($params['db'], $params['write_db']);
 
-        /* Set DB portability options. */
-        switch ($this->_db->phptype) {
-        case 'mssql':
-            $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
-            break;
+        $params = array_merge(array(
+            'table' => 'imp_sentmail'
+        ), $params);
 
-        default:
-            $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
-        }
+        parent::__construct($params);
     }
 
     /**
@@ -101,13 +85,13 @@ class IMP_Sentmail_Sql extends IMP_Sentmail
                         $message_id,
                         $action,
                         $recipient,
-                        (int)$success);
+                        intval($success));
 
         /* Log the query at a DEBUG log level. */
         Horde::logMessage(sprintf('IMP_Sentmail_Sql::_log(): %s', $query), 'DEBUG');
 
         /* Execute the query. */
-        $result = $this->_db->query($query, $values);
+        $result = $this->_write_db->query($query, $values);
 
         /* Log errors. */
         if ($result instanceof PEAR_Error) {
@@ -208,7 +192,7 @@ class IMP_Sentmail_Sql extends IMP_Sentmail
         Horde::logMessage(sprintf('IMP_Sentmail_Sql::_deleteOldEntries(): %s', $query), 'DEBUG');
 
         /* Execute the query. */
-        $result = $this->_db->query($query, array($before));
+        $result = $this->_write_db->query($query, array($before));
         if ($result instanceof PEAR_Error) {
             Horde::logMessage($result, 'ERR');
         }