]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Memcached_DataObject.php
let avatars be served over SSL
[quix0rs-gnu-social.git] / classes / Memcached_DataObject.php
index 400b05f9776fca066e462e3a812a2a37fc08f7a6..dfd06b57e50366f4fb60b86578c2f3ddaecb510d 100644 (file)
@@ -147,6 +147,7 @@ class Memcached_DataObject extends DB_DataObject
     {
         $result = parent::insert();
         if ($result) {
+            $this->fixupTimestamps();
             $this->encache(); // in case of cached negative lookups
         }
         return $result;
@@ -159,6 +160,7 @@ class Memcached_DataObject extends DB_DataObject
         }
         $result = parent::update($orig);
         if ($result) {
+            $this->fixupTimestamps();
             $this->encache();
         }
         return $result;
@@ -188,7 +190,16 @@ class Memcached_DataObject extends DB_DataObject
         if (!$c) {
             return false;
         } else {
-            return $c->get(Memcached_DataObject::cacheKey($cls, $k, $v));
+            $obj = $c->get(Memcached_DataObject::cacheKey($cls, $k, $v));
+            if (0 == strcasecmp($cls, 'User')) {
+                // Special case for User
+                if (is_object($obj) && is_object($obj->id)) {
+                    common_log(LOG_ERR, "User " . $obj->nickname . " was cached with User as ID; deleting");
+                    $c->delete(Memcached_DataObject::cacheKey($cls, $k, $v));
+                    return false;
+                }
+            }
+            return $obj;
         }
     }
 
@@ -219,12 +230,18 @@ class Memcached_DataObject extends DB_DataObject
 
         if (!$c) {
             return false;
-        }
-
-        $keys = $this->_allCacheKeys();
+        } else if ($this->tableName() == 'user' && is_object($this->id)) {
+            // Special case for User bug
+            $e = new Exception();
+            common_log(LOG_ERR, __METHOD__ . ' caching user with User object as ID ' .
+                       str_replace("\n", " ", $e->getTraceAsString()));
+            return false;
+        } else {
+               $keys = $this->_allCacheKeys();
 
-        foreach ($keys as $key) {
-            $c->set($key, $this);
+               foreach ($keys as $key) {
+                   $c->set($key, $this);
+               }
         }
     }
 
@@ -346,10 +363,43 @@ class Memcached_DataObject extends DB_DataObject
             $cached[] = clone($inst);
         }
         $inst->free();
-        $c->set($ckey, $cached, MEMCACHE_COMPRESSED, $expiry);
+        $c->set($ckey, $cached, Cache::COMPRESSED, $expiry);
         return new ArrayWrapper($cached);
     }
 
+    /**
+     * sends query to database - this is the private one that must work
+     *   - internal functions use this rather than $this->query()
+     *
+     * Overridden to do logging.
+     *
+     * @param  string  $string
+     * @access private
+     * @return mixed none or PEAR_Error
+     */
+    function _query($string)
+    {
+        $start = microtime(true);
+        $result = parent::_query($string);
+        $delta = microtime(true) - $start;
+
+        $limit = common_config('db', 'log_slow_queries');
+        if (($limit > 0 && $delta >= $limit) || common_config('db', 'log_queries')) {
+            $clean = $this->sanitizeQuery($string);
+            common_log(LOG_DEBUG, sprintf("DB query (%0.3fs): %s", $delta, $clean));
+        }
+        return $result;
+    }
+
+    // Sanitize a query for logging
+    // @fixme don't trim spaces in string literals
+    function sanitizeQuery($string)
+    {
+        $string = preg_replace('/\s+/', ' ', $string);
+        $string = trim($string);
+        return $string;
+    }
+
     // We overload so that 'SET NAMES "utf8"' is called for
     // each connection
 
@@ -366,6 +416,29 @@ class Memcached_DataObject extends DB_DataObject
             $exists = false;
        }
 
+        // @fixme horrible evil hack!
+        //
+        // In multisite configuration we don't want to keep around a separate
+        // connection for every database; we could end up with thousands of
+        // connections open per thread. In an ideal world we might keep
+        // a connection per server and select different databases, but that'd
+        // be reliant on having the same db username/pass as well.
+        //
+        // MySQL connections are cheap enough we're going to try just
+        // closing out the old connection and reopening when we encounter
+        // a new DSN.
+        //
+        // WARNING WARNING if we end up actually using multiple DBs at a time
+        // we'll need some fancier logic here.
+        if (!$exists && !empty($_DB_DATAOBJECT['CONNECTIONS']) && php_sapi_name() == 'cli') {
+            foreach ($_DB_DATAOBJECT['CONNECTIONS'] as $index => $conn) {
+                if (!empty($conn)) {
+                    $conn->disconnect();
+                }
+                unset($_DB_DATAOBJECT['CONNECTIONS'][$index]);
+            }
+        }
+
         $result = parent::_connect();
 
         if ($result && !$exists) {
@@ -439,4 +512,70 @@ class Memcached_DataObject extends DB_DataObject
 
         return $dsn;
     }
+
+    static function blow()
+    {
+        $c = self::memcache();
+
+        if (empty($c)) {
+            return false;
+        }
+
+        $args = func_get_args();
+
+        $format = array_shift($args);
+
+        $keyPart = vsprintf($format, $args);
+
+        $cacheKey = common_cache_key($keyPart);
+
+        return $c->delete($cacheKey);
+    }
+
+    function fixupTimestamps()
+    {
+        // Fake up timestamp columns
+        $columns = $this->table();
+        foreach ($columns as $name => $type) {
+            if ($type & DB_DATAOBJECT_MYSQLTIMESTAMP) {
+                $this->$name = common_sql_now();
+            }
+        }
+    }
+
+    function debugDump()
+    {
+        common_debug("debugDump: " . common_log_objstring($this));
+    }
+
+    function raiseError($message, $type = null, $behaviour = null)
+    {
+        throw new ServerException("DB_DataObject error [$type]: $message");
+    }
+
+    static function cacheGet($keyPart)
+    {
+        $c = self::memcache();
+
+        if (empty($c)) {
+            return false;
+        }
+
+        $cacheKey = common_cache_key($keyPart);
+
+        return $c->get($cacheKey);
+    }
+
+    static function cacheSet($keyPart, $value)
+    {
+        $c = self::memcache();
+
+        if (empty($c)) {
+            return false;
+        }
+
+        $cacheKey = common_cache_key($keyPart);
+
+        return $c->set($cacheKey, $value);
+    }
 }