X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FMemcached_DataObject.php;h=ec36079c1c7a92a46b43fe69f4cbcbc9d1bcab5f;hb=9a78d70441d68f6c0eb2ab6c0ef16424879f1caa;hp=d50b4071d1eeaef3548dd992675498bd991fad31;hpb=6e894c010fc0e7ddaaafa8795634d6343019aafb;p=quix0rs-gnu-social.git diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index d50b4071d1..ec36079c1c 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -34,7 +34,7 @@ class Memcached_DataObject extends Safe_DataObject { if (is_null($v)) { $v = $k; - # XXX: HACK! + // XXX: HACK! $i = new $cls; $keys = $i->keys(); $k = $keys[0]; @@ -63,7 +63,116 @@ class Memcached_DataObject extends Safe_DataObject } return $i; } + + /** + * Get multiple items from the database by key + * + * @param string $cls Class to fetch + * @param string $keyCol name of column for key + * @param array $keyVals key values to fetch + * @param boolean $skipNulls return only non-null results? + * + * @return array Array of objects, in order + */ + function multiGet($cls, $keyCol, $keyVals, $skipNulls=true) + { + $result = self::pivotGet($cls, $keyCol, $keyVals); + + $values = array_values($result); + + if ($skipNulls) { + $tmp = array(); + foreach ($values as $value) { + if (!empty($value)) { + $tmp[] = $value; + } + } + $values = $tmp; + } + + return new ArrayWrapper($values); + } + + /** + * Get multiple items from the database by key + * + * @param string $cls Class to fetch + * @param string $keyCol name of column for key + * @param array $keyVals key values to fetch + * @param boolean $otherCols Other columns to hold fixed + * + * @return array Array mapping $keyVals to objects, or null if not found + */ + static function pivotGet($cls, $keyCol, $keyVals, $otherCols = array()) + { + $result = array_fill_keys($keyVals, null); + + $toFetch = array(); + + foreach ($keyVals as $keyVal) { + + $kv = array_merge($otherCols, array($keyCol => $keyVal)); + + $i = self::multicache($cls, $kv); + + if ($i !== false) { + $result[$keyVal] = $i; + } else if (!empty($keyVal)) { + $toFetch[] = $keyVal; + } + } + + if (count($toFetch) > 0) { + $i = DB_DataObject::factory($cls); + if (empty($i)) { + throw new Exception(_('Cannot instantiate class ' . $cls)); + } + foreach ($otherCols as $otherKeyCol => $otherKeyVal) { + $i->$otherKeyCol = $otherKeyVal; + } + $i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol)); + if ($i->find()) { + while ($i->fetch()) { + $copy = clone($i); + $copy->encache(); + $result[$i->$keyCol] = $copy; + } + } + + // Save state of DB misses + + foreach ($toFetch as $keyVal) { + if (empty($result[$keyVal])) { + $kv = array_merge($otherCols, array($keyCol => $keyVal)); + // save the fact that no such row exists + $c = self::memcache(); + if (!empty($c)) { + $ck = self::multicacheKey($cls, $keyCol, $keyVal); + $c->set($ck, null); + } + } + } + } + + return $result; + } + function columnType($columnName) + { + $keys = $this->table(); + if (!array_key_exists($columnName, $keys)) { + throw new Exception('Unknown key column ' . $columnName . ' in ' . join(',', array_keys($keys))); + } + + $def = $keys[$columnName]; + + if ($def & DB_DATAOBJECT_INT) { + return 'integer'; + } else { + return 'string'; + } + } + /** * @fixme Should this return false on lookup fail to match staticGet? */ @@ -78,7 +187,13 @@ class Memcached_DataObject extends Safe_DataObject return false; } foreach ($kv as $k => $v) { - $i->$k = $v; + if (is_null($v)) { + // XXX: possible SQL injection...? Don't + // pass keys from the browser, eh. + $i->whereAdd("$k is null"); + } else { + $i->$k = $v; + } } if ($i->find(true)) { $i->encache(); @@ -124,7 +239,7 @@ class Memcached_DataObject extends Safe_DataObject } static function memcache() { - return common_memcache(); + return Cache::instance(); } static function cacheKey($cls, $k, $v) { @@ -134,7 +249,7 @@ class Memcached_DataObject extends Safe_DataObject str_replace("\n", " ", $e->getTraceAsString())); } $vstr = self::valueString($v); - return common_cache_key(strtolower($cls).':'.$k.':'.$vstr); + return Cache::key(strtolower($cls).':'.$k.':'.$vstr); } static function getcached($cls, $k, $v) { @@ -273,24 +388,23 @@ class Memcached_DataObject extends Safe_DataObject function getSearchEngine($table) { require_once INSTALLDIR.'/lib/search_engines.php'; - static $search_engine; - if (!isset($search_engine)) { - if (Event::handle('GetSearchEngine', array($this, $table, &$search_engine))) { - if ('mysql' === common_config('db', 'type')) { - $type = common_config('search', 'type'); - if ($type == 'like') { - $search_engine = new MySQLLikeSearch($this, $table); - } else if ($type == 'fulltext') { - $search_engine = new MySQLSearch($this, $table); - } else { - // Low level exception. No need for i18n as discussed with Brion. - throw new ServerException('Unknown search type: ' . $type); - } + + if (Event::handle('GetSearchEngine', array($this, $table, &$search_engine))) { + if ('mysql' === common_config('db', 'type')) { + $type = common_config('search', 'type'); + if ($type == 'like') { + $search_engine = new MySQLLikeSearch($this, $table); + } else if ($type == 'fulltext') { + $search_engine = new MySQLSearch($this, $table); } else { - $search_engine = new PGSearch($this, $table); + // Low level exception. No need for i18n as discussed with Brion. + throw new ServerException('Unknown search type: ' . $type); } + } else { + $search_engine = new PGSearch($this, $table); } } + return $search_engine; } @@ -302,8 +416,8 @@ class Memcached_DataObject extends Safe_DataObject $inst->query($qry); return $inst; } - $key_part = common_keyize($cls).':'.md5($qry); - $ckey = common_cache_key($key_part); + $key_part = Cache::keyize($cls).':'.md5($qry); + $ckey = Cache::key($key_part); $stored = $c->get($ckey); if ($stored !== false) { @@ -338,9 +452,15 @@ class Memcached_DataObject extends Safe_DataObject } $start = microtime(true); + $fail = false; $result = null; if (Event::handle('StartDBQuery', array($this, $string, &$result))) { - $result = parent::_query($string); + common_perf_counter('query', $string); + try { + $result = parent::_query($string); + } catch (Exception $e) { + $fail = $e; + } Event::handle('EndDBQuery', array($this, $string, &$result)); } $delta = microtime(true) - $start; @@ -348,7 +468,16 @@ class Memcached_DataObject extends Safe_DataObject $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)); + if ($fail) { + $msg = sprintf("FAILED DB query (%0.3fs): %s - %s", $delta, $fail->getMessage(), $clean); + } else { + $msg = sprintf("DB query (%0.3fs): %s", $delta, $clean); + } + common_log(LOG_DEBUG, $msg); + } + + if ($fail) { + throw $fail; } return $result; } @@ -480,6 +609,10 @@ class Memcached_DataObject extends Safe_DataObject } } } + // Needed to make timestamp values usefully comparable. + if (common_config('db', 'type') == 'mysql') { + parent::_query("set time_zone='+0:00'"); + } } return $result; @@ -554,7 +687,7 @@ class Memcached_DataObject extends Safe_DataObject $keyPart = vsprintf($format, $args); - $cacheKey = common_cache_key($keyPart); + $cacheKey = Cache::key($keyPart); return $c->delete($cacheKey); } @@ -596,7 +729,7 @@ class Memcached_DataObject extends Safe_DataObject return false; } - $cacheKey = common_cache_key($keyPart); + $cacheKey = Cache::key($keyPart); return $c->get($cacheKey); } @@ -609,7 +742,7 @@ class Memcached_DataObject extends Safe_DataObject return false; } - $cacheKey = common_cache_key($keyPart); + $cacheKey = Cache::key($keyPart); return $c->set($cacheKey, $value, $flag, $expiry); }