Recover caching logic lost in bad merge

I made a bad merge on Jan 10th from master to 0.9.x. This lost a number
of memcache enhancements made on the 0.9.x branch. I've been able to
re-do the manual merge, and this represents the changes. Most of them
are related to caching on insert.
This commit is contained in:
Evan Prodromou 2010-01-24 22:39:32 -05:00
parent 7cd666ae92
commit e6cf293db8

View File

@ -66,7 +66,6 @@ class Memcached_DataObject extends DB_DataObject
// Clear this out so we don't accidentally break global // Clear this out so we don't accidentally break global
// state in *this* process. // state in *this* process.
$this->_DB_resultid = null; $this->_DB_resultid = null;
// We don't have any local DBO refs, so clear these out. // We don't have any local DBO refs, so clear these out.
$this->_link_loaded = false; $this->_link_loaded = false;
} }
@ -91,9 +90,7 @@ class Memcached_DataObject extends DB_DataObject
unset($i); unset($i);
} }
$i = Memcached_DataObject::getcached($cls, $k, $v); $i = Memcached_DataObject::getcached($cls, $k, $v);
if ($i) { if ($i === false) { // false == cache miss
return $i;
} else {
$i = DB_DataObject::factory($cls); $i = DB_DataObject::factory($cls);
if (empty($i)) { if (empty($i)) {
$i = false; $i = false;
@ -101,22 +98,34 @@ class Memcached_DataObject extends DB_DataObject
} }
$result = $i->get($k, $v); $result = $i->get($k, $v);
if ($result) { if ($result) {
// Hit!
$i->encache(); $i->encache();
return $i;
} else { } else {
// save the fact that no such row exists
$c = self::memcache();
if (!empty($c)) {
$ck = self::cachekey($cls, $k, $v);
$c->set($ck, null);
}
$i = false; $i = false;
}
}
return $i; return $i;
} }
}
}
function &pkeyGet($cls, $kv) /**
* @fixme Should this return false on lookup fail to match staticGet?
*/
function pkeyGet($cls, $kv)
{ {
$i = Memcached_DataObject::multicache($cls, $kv); $i = Memcached_DataObject::multicache($cls, $kv);
if ($i) { if ($i !== false) { // false == cache miss
return $i; return $i;
} else { } else {
$i = new $cls(); $i = DB_DataObject::factory($cls);
if (empty($i)) {
return false;
}
foreach ($kv as $k => $v) { foreach ($kv as $k => $v) {
$i->$k = $v; $i->$k = $v;
} }
@ -124,6 +133,11 @@ class Memcached_DataObject extends DB_DataObject
$i->encache(); $i->encache();
} else { } else {
$i = null; $i = null;
$c = self::memcache();
if (!empty($c)) {
$ck = self::multicacheKey($cls, $kv);
$c->set($ck, null);
}
} }
return $i; return $i;
} }
@ -132,6 +146,9 @@ class Memcached_DataObject extends DB_DataObject
function insert() function insert()
{ {
$result = parent::insert(); $result = parent::insert();
if ($result) {
$this->encache(); // in case of cached negative lookups
}
return $result; return $result;
} }
@ -186,6 +203,17 @@ class Memcached_DataObject extends DB_DataObject
function keyTypes() function keyTypes()
{ {
// ini-based classes return number-indexed arrays. handbuilt
// classes return column => keytype. Make this uniform.
$keys = $this->keys();
$keyskeys = array_keys($keys);
if (is_string($keyskeys[0])) {
return $keys;
}
global $_DB_DATAOBJECT; global $_DB_DATAOBJECT;
if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"])) { if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"])) {
$this->databaseStructure(); $this->databaseStructure();
@ -197,6 +225,7 @@ class Memcached_DataObject extends DB_DataObject
function encache() function encache()
{ {
$c = $this->memcache(); $c = $this->memcache();
if (!$c) { if (!$c) {
return false; return false;
} else if ($this->tableName() == 'user' && is_object($this->id)) { } else if ($this->tableName() == 'user' && is_object($this->id)) {
@ -206,62 +235,84 @@ class Memcached_DataObject extends DB_DataObject
str_replace("\n", " ", $e->getTraceAsString())); str_replace("\n", " ", $e->getTraceAsString()));
return false; return false;
} else { } else {
$pkey = array(); $keys = $this->_allCacheKeys();
$pval = array();
$types = $this->keyTypes(); foreach ($keys as $key) {
ksort($types); $c->set($key, $this);
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() function decache()
{ {
$c = $this->memcache(); $c = $this->memcache();
if (!$c) { if (!$c) {
return false; return false;
} else { }
$pkey = array();
$pval = array(); $keys = $this->_allCacheKeys();
foreach ($keys as $key) {
$c->delete($key, $this);
}
}
function _allCacheKeys()
{
$ckeys = array();
$types = $this->keyTypes(); $types = $this->keyTypes();
ksort($types); ksort($types);
$pkey = array();
$pval = array();
foreach ($types as $key => $type) { foreach ($types as $key => $type) {
if ($type == 'K') {
assert(!empty($key));
if ($type == 'U') {
if (empty($this->$key)) {
continue;
}
$ckeys[] = $this->cacheKey($this->tableName(), $key, $this->$key);
} else if ($type == 'K' || $type == 'N') {
$pkey[] = $key; $pkey[] = $key;
$pval[] = $this->$key; $pval[] = $this->$key;
} else { } else {
$c->delete($this->cacheKey($this->tableName(), $key, $this->$key)); throw new Exception("Unknown key type $key => $type for " . $this->tableName());
} }
} }
# should work for both compound and scalar pkeys
# XXX: comma works for now but may not be safe separator for future keys assert(count($pkey) > 0);
// XXX: should work for both compound and scalar pkeys
$pvals = implode(',', $pval); $pvals = implode(',', $pval);
$pkeys = implode(',', $pkey); $pkeys = implode(',', $pkey);
$c->delete($this->cacheKey($this->tableName(), $pkeys, $pvals));
} $ckeys[] = $this->cacheKey($this->tableName(), $pkeys, $pvals);
return $ckeys;
} }
function multicache($cls, $kv) function multicache($cls, $kv)
{ {
ksort($kv); ksort($kv);
$c = Memcached_DataObject::memcache(); $c = self::memcache();
if (!$c) { if (!$c) {
return false; return false;
} else { } else {
return $c->get(self::multicacheKey($cls, $kv));
}
}
static function multicacheKey($cls, $kv)
{
ksort($kv);
$pkeys = implode(',', array_keys($kv)); $pkeys = implode(',', array_keys($kv));
$pvals = implode(',', array_values($kv)); $pvals = implode(',', array_values($kv));
return $c->get(Memcached_DataObject::cacheKey($cls, $pkeys, $pvals)); return self::cacheKey($cls, $pkeys, $pvals);
}
} }
function getSearchEngine($table) function getSearchEngine($table)
@ -298,7 +349,8 @@ class Memcached_DataObject extends DB_DataObject
$key_part = common_keyize($cls).':'.md5($qry); $key_part = common_keyize($cls).':'.md5($qry);
$ckey = common_cache_key($key_part); $ckey = common_cache_key($key_part);
$stored = $c->get($ckey); $stored = $c->get($ckey);
if ($stored) {
if ($stored !== false) {
return new ArrayWrapper($stored); return new ArrayWrapper($stored);
} }