]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Memcached_DataObject.php
Merge branch '0.8.x' into userdesign
[quix0rs-gnu-social.git] / classes / Memcached_DataObject.php
index 2c44b734af80ae5f97f6454306662502fc17bc02..33ac70dd045643a5a57ff87e58d383a0bc52bd2b 100644 (file)
@@ -21,124 +21,234 @@ if (!defined('LACONICA')) { exit(1); }
 
 require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
 
-class Memcached_DataObject extends DB_DataObject 
+class Memcached_DataObject extends DB_DataObject
 {
-    static function &staticGet($cls, $k, $v=NULL) {
-               $i = $this->getcached($cls, $k, $v);
-               if (!is_null($i)) {
-                       return $i;
-               } else {
-                       $i = DB_DataObject::staticGet($cls, $k, $v);
-                       if (!is_null($i)) {
-                               $i->encache();
-                       }
-                       return $i;
-               }
-       }
-       
-       function insert() {
-               $result = parent::insert();
-               if ($result) {
-                       $this->encache();
-               }
-               return $result;
-       }
-       
-       function update($orig=NULL) {
-               if (!is_null($orig)) {
-                       $orig->decache(); # might be different keys
-               }
-               $result = parent::update($orig);
-               if ($result) {
-                       $this->encache();
-               }
-       }
-       
-       function delete() {
-               $this->decache(); # while we still have the values!
-               return parent::delete();
-       }
-       
-       static function memcache() {
-               if (!common_config('memcached', 'enabled')) {
-                       return NULL;
-               } else {
-                       $cache = new Memcache();
-                       $res = $cache->connect(common_config('memcached', 'server'), 
-                                                                  common_config('memcached', 'port'));
-                       return ($res) ? $cache : NULL;
-               }
-       }
-       
-       static function cacheKey($cls, $k, $v) {
-               return common_cache_key(strtolower($cls) . ':' .
-                                                               $k . ':' .
-                                                               $v);
-       }
-       
-       static function getcached($cls, $k, $v) {
-               $c = Memcached_DataObject::memcache();
-               if (!$c) {
-                       return false;
-               } else {
-                       return $c->get(Memcached_DataObject::cacheKey($cls, $k, $v));
-               }
-       }
-
-       function keyTypes() {
-               global $_DB_DATAOBJECT;
+    function &staticGet($cls, $k, $v=null)
+    {
+        if (is_null($v)) {
+            $v = $k;
+            # XXX: HACK!
+            $i = new $cls;
+            $keys = $i->keys();
+            $k = $keys[0];
+            unset($i);
+        }
+        $i = Memcached_DataObject::getcached($cls, $k, $v);
+        if ($i) {
+            return $i;
+        } else {
+            $i = DB_DataObject::staticGet($cls, $k, $v);
+            if ($i) {
+                $i->encache();
+            }
+            return $i;
+        }
+    }
+
+    function &pkeyGet($cls, $kv)
+    {
+        $i = Memcached_DataObject::multicache($cls, $kv);
+        if ($i) {
+            return $i;
+        } else {
+            $i = new $cls();
+            foreach ($kv as $k => $v) {
+                $i->$k = $v;
+            }
+            if ($i->find(true)) {
+                $i->encache();
+            } else {
+                $i = null;
+            }
+            return $i;
+        }
+    }
+
+    function insert()
+    {
+        $result = parent::insert();
+        return $result;
+    }
+
+    function update($orig=null)
+    {
+        if (is_object($orig) && $orig instanceof Memcached_DataObject) {
+            $orig->decache(); # might be different keys
+        }
+        $result = parent::update($orig);
+        if ($result) {
+            $this->encache();
+        }
+        return $result;
+    }
+
+    function delete()
+    {
+        $this->decache(); # while we still have the values!
+        return parent::delete();
+    }
+
+    static function memcache() {
+        return common_memcache();
+    }
+
+    static function cacheKey($cls, $k, $v) {
+        return common_cache_key(strtolower($cls).':'.$k.':'.$v);
+    }
+
+    static function getcached($cls, $k, $v) {
+        $c = Memcached_DataObject::memcache();
+        if (!$c) {
+            return false;
+        } else {
+            return $c->get(Memcached_DataObject::cacheKey($cls, $k, $v));
+        }
+    }
+
+    function keyTypes()
+    {
+        global $_DB_DATAOBJECT;
         if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"])) {
-                       $this->databaseStructure();
+            $this->databaseStructure();
+
+        }
+        return $_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"];
+    }
+
+    function encache()
+    {
+        $c = $this->memcache();
+        if (!$c) {
+            return false;
+        } else {
+            $pkey = array();
+            $pval = array();
+            $types = $this->keyTypes();
+            ksort($types);
+            foreach ($types as $key => $type) {
+                if ($type == 'K') {
+                    $pkey[] = $key;
+                    $pval[] = $this->$key;
+                } else {
+                    $c->set($this->cacheKey($this->tableName(), $key, $this->$key), $this);
+                }
+            }
+            # XXX: should work for both compound and scalar pkeys
+            $pvals = implode(',', $pval);
+            $pkeys = implode(',', $pkey);
+            $c->set($this->cacheKey($this->tableName(), $pkeys, $pvals), $this);
+        }
+    }
+
+    function decache()
+    {
+        $c = $this->memcache();
+        if (!$c) {
+            return false;
+        } else {
+            $pkey = array();
+            $pval = array();
+            $types = $this->keyTypes();
+            ksort($types);
+            foreach ($types as $key => $type) {
+                if ($type == 'K') {
+                    $pkey[] = $key;
+                    $pval[] = $this->$key;
+                } else {
+                    $c->delete($this->cacheKey($this->tableName(), $key, $this->$key));
+                }
+            }
+            # should work for both compound and scalar pkeys
+            # XXX: comma works for now but may not be safe separator for future keys
+            $pvals = implode(',', $pval);
+            $pkeys = implode(',', $pkey);
+            $c->delete($this->cacheKey($this->tableName(), $pkeys, $pvals));
+        }
+    }
+
+    function multicache($cls, $kv)
+    {
+        ksort($kv);
+        $c = Memcached_DataObject::memcache();
+        if (!$c) {
+            return false;
+        } else {
+            $pkeys = implode(',', array_keys($kv));
+            $pvals = implode(',', array_values($kv));
+            return $c->get(Memcached_DataObject::cacheKey($cls, $pkeys, $pvals));
+        }
+    }
+
+    function getSearchEngine($table)
+    {
+        require_once INSTALLDIR.'/lib/search_engines.php';
+        static $search_engine;
+        if (!isset($search_engine)) {
+                $connected = false;
+                if (common_config('sphinx', 'enabled')) {
+                    $search_engine = new SphinxSearch($this, $table);
+                    $connected = $search_engine->is_connected();
+                }
+
+                // unable to connect to sphinx' search daemon
+                if (!$connected) {
+                    if ('mysql' === common_config('db', 'type')) {
+                        $search_engine = new MySQLSearch($this, $table);
+                    } else {
+                        $search_engine = new PGSearch($this, $table);
+                    }
+                }
+        }
+        return $search_engine;
+    }
+
+    static function cachedQuery($cls, $qry, $expiry=3600)
+    {
+        $c = Memcached_DataObject::memcache();
+        if (!$c) {
+            $inst = new $cls();
+            $inst->query($qry);
+            return $inst;
+        }
+        $key_part = common_keyize($cls).':'.md5($qry);
+        $ckey = common_cache_key($key_part);
+        $stored = $c->get($ckey);
+        if ($stored) {
+            return new ArrayWrapper($stored);
+        }
+
+        $inst = new $cls();
+        $inst->query($qry);
+        $cached = array();
+        while ($inst->fetch()) {
+            $cached[] = clone($inst);
+        }
+        $inst->free();
+        $c->set($ckey, $cached, MEMCACHE_COMPRESSED, $expiry);
+        return new ArrayWrapper($cached);
+    }
+
+    // We overload so that 'SET NAMES "utf8"' is called for
+    // each connection
 
+    function _connect()
+    {
+        global $_DB_DATAOBJECT;
+        $exists = !empty($this->_database_dsn_md5) &&
+          isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]);
+        $result = parent::_connect();
+        if (!$exists) {
+            $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
+            if (common_config('db', 'type') == 'mysql' &&
+                common_config('db', 'utf8')) {
+                $conn = $DB->connection;
+                if ($DB instanceof DB_mysqli) {
+                    mysqli_set_charset($conn, 'utf8');
+                } else if ($DB instanceof DB_mysql) {
+                    mysql_set_charset('utf8', $conn);
+                }
+            }
         }
-               return $_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"];
-       }
-       
-       function encache() {
-               $c = $this->memcache();
-               if (!$c) {
-                       return false;
-               } else {
-                       $primary = array();
-                       $types = ksort($this->keyTypes());
-                       foreach ($types as $key => $type) {
-                               if ($type == 'K') {
-                                       $primary[] = $key;
-                               } else {
-                                       $c->set($this->cacheKey($this->tableName(), $key, $this->$key),
-                                                       $this);
-                               }
-                       }
-                       # XXX: figure out what to do with compound pkeys
-                       if (count($primary) == 1) {
-                               $key = $primary[0];
-                               $c->set($this->cacheKey($this->tableName(), $key, $this->$key),
-                                               $this);
-                       }
-               }
-       }
-       
-       function decache() {
-               $c = $this->memcache();
-               if (!$c) {
-                       return false;
-               } else {
-                       $primary = array();
-                       $types = ksort($this->keyTypes());
-                       foreach ($types as $key => $type) {
-                               if ($type == 'K') {
-                                       $primary[] = $this->$key;
-                               } else {
-                                       $c->delete($this->cacheKey($this->tableName(), $key, $this->$key),
-                                                          $this);
-                               }
-                       }
-                       # XXX: figure out what to do with compound pkeys
-                       if (count($primary) == 1) {
-                               $key = $primary[0];
-                               $c->delete($this->cacheKey($this->tableName(), $key, $this->$key),
-                                                  $this);
-                       }
-               }
-       }
+        return $result;
+    }
 }