// Check to see whether this record is eligible for caching (fields=*, only condition is id)
$docache = false;
- if (!empty($CFG->enablerecordcache) && $field1=='id' && !$field2 && !$field3 && $fields=='*') {
+ if (!empty($CFG->rcache) && $field1=='id' && !$field2 && !$field3 && $fields=='*') {
$docache = true;
// If it's in the cache, return it
- $cached = rcache_get($table, $value1);
+ $cached = rcache_getforfill($table, $value1);
if (!empty($cached)) {
return $cached;
}
// If we're caching records, store this one
// (supposing we got something - we don't cache failures)
- if ($record && $docache) {
- rcache_set($table, $value1, $record);
+ if ($docache) {
+ if (isset($record)) {
+ rcache_set($table, $value1, $record);
+ } else {
+ rcache_releaseforfill($table, $value1);
+ }
}
-
return $record;
}
// Clear record_cache based on the parameters passed
// (individual record or whole table)
- if (!empty($CFG->enablerecordcache)) {
+ if (!empty($CFG->rcache)) {
if ($field1 == 'id') {
rcache_unset($table, $value1);
} else if ($field2 == 'id') {
// Clear record_cache based on the parameters passed
// (individual record or whole table)
- if (!empty($CFG->enablerecordcache)) {
+ if (!empty($CFG->rcache)) {
rcache_unset_table($table);
}
}
// Clear record_cache based on the parameters passed
// (individual record or whole table)
- if (!empty($CFG->enablerecordcache)) {
+ if (!empty($CFG->rcache)) {
if ($field1 == 'id') {
rcache_unset($table, $value1);
} else if ($field2 == 'id') {
global $CFG, $db;
// Clear record_cache (whole table)
- if (!empty($CFG->enablerecordcache)) {
+ if (!empty($CFG->rcache)) {
rcache_unset_table($table);
}
}
// Remove this record from record cache since it will change
- if (!empty($CFG->enablerecordcache)) {
+ if (!empty($CFG->rcache)) {
rcache_unset($table, $dataobject->id);
}
return $status;
}
-
+/**
+ * Set cached record.
+ *
+ * If you have called rcache_getforfill() before, it will also
+ * release the lock.
+ *
+ * This function is private and must not be used outside dmllib at all
+ *
+ * @param $table string
+ * @param $id integer
+ * @param $rec obj
+ * @return bool
+ */
function rcache_set($table, $id, $rec) {
- global $CFG, $rcache;
+ global $CFG, $MCACHE, $rcache;
- $rcache->data[$table][$id] = $rec;
+ if ($CFG->rcache === 'internal') {
+ $rcache->data[$table][$id] = $rec;
+ } else {
+ $reckey = join('|', array($CFG->dbname, $CFG->prefix,
+ $table, $id));
+ $tablekey = $key = join('|', array($CFG->dbname, $CFG->prefix,
+ $table));
+ if (isset($MCACHE)) {
+ // $tablekey is a flag used to mark
+ // a table as dirty & uncacheable
+ // when an UPDATE or DELETE not bound by ID
+ // is taking place
+ if (!$MCACHE->get($tablekey)) {
+ $MCACHE->set($reckey, $rec, false, 2);
+ $MCACHE->delete($reckey . '_fill'); // release lock
+ }
+ }
+ }
return true;
+
}
+/**
+ * Unset cached record if it exists.
+ *
+ * This function is private and must not be used outside dmllib at all
+ *
+ * @param $table string
+ * @param $id integer
+ * @return bool
+ */
function rcache_unset($table, $id) {
- global $CFG, $rcache;
+ global $CFG, $MCACHE, $rcache;
- if (isset($rcache->data[$table][$id])) {
- unset($rcache->data[$table][$id]);
+ if ($CFG->rcache === 'internal') {
+ if (isset($rcache->data[$table][$id])) {
+ unset($rcache->data[$table][$id]);
+ }
+ } else {
+ $key = join('|', array($CFG->dbname, $CFG->prefix,
+ $table, $id));
+ if (isset($MCACHE)) {
+ $MCACHE->delete($key);
+ }
}
return true;
}
* @return mixed object-like record on cache hit, false otherwise
*/
function rcache_get($table, $id) {
- global $CFG, $rcache;
+ global $CFG, $MCACHE, $rcache;
- if (isset($rcache->data[$table][$id])) {
- $rcache->hits++;
- return $rcache->data[$table][$id];
- } else {
- $rcache->misses++;
- return false;
+ if ($CFG->rcache === 'internal') {
+ if (isset($rcache->data[$table][$id])) {
+ $rcache->hits++;
+ return $rcache->data[$table][$id];
+ } else {
+ $rcache->misses++;
+ return false;
+ }
+ }
+
+ $reckey = join('|', array($CFG->dbname, $CFG->prefix,
+ $table, $id));
+ $tablekey = $key = join('|', array($CFG->dbname, $CFG->prefix,
+ $table));
+ if (isset($MCACHE)) {
+ // $tablekey is a flag used to mark
+ // a table as dirty & uncacheable
+ // when an UPDATE or DELETE not bound by ID
+ // is taking place
+ if ($MCACHE->get($tablekey)) {
+ $rcache->misses++;
+ return false;
+ } else {
+ $rec = $MCACHE->get($reckey);
+ if (!empty($rec)) {
+ $rcache->hits++;
+ return $rec;
+ } else {
+ $rcache->misses++;
+ return false;
+ }
+ }
}
+ return false;
}
/**
* @return mixed object-like record on cache hit, false otherwise
*/
function rcache_getforfill($table, $id) {
- global $CFG, $rcache;
+ global $CFG, $MCACHE, $rcache;
+
+ if ($CFG->rcache === 'internal') {
+ return rcache_get($table, $id);
+ }
+
+ $reckey = join('|', array($CFG->dbname, $CFG->prefix,
+ $table, $id));
+ $tablekey = $key = join('|', array($CFG->dbname, $CFG->prefix,
+ $table));
+ if (isset($MCACHE)) {
+ // if $tablekey is set - we won't take the
+ // lock either
+ if ($MCACHE->get($tablekey)) {
+ $rcache->misses++;
+ return false;
+ } else {
+ $rec = $MCACHE->get($reckey);
+ if (!empty($rec)) { // easy
+ $rcache->hits++;
+ return $rec;
+ } else {
+ // not found - get the "_fill" lock or poll for
+ // the results if someone's holding it
+ // get the lock for 1s and tag a miss
+ if ($MCACHE->add($reckey . '_fill', true, false, 1)) {
+ $rcache->misses++;
+ return false;
+ } else { // could not get the lock - loop .05s waiting for it
+ for ($n=0;$n<5;$n++) {
+ usleep(10000);
+ $rec = $MCACHE->get($reckey);
+ if (!empty($rec)) { // easy
+ $rcache->hits++;
+ return $rec;
+ }
+ }
+ return false;
+ }
+ }
+ }
+ }
+ return false;
- return rcache_get($table, $id);
}
/**
* @return bool
*/
function rcache_releaseforfill($table, $id) {
- global $CFG, $rcache;
+ global $CFG, $MCACHE, $rcache;
+ $reckey = join('|', array($CFG->dbname, $CFG->prefix,
+ $table, $id));
+
+ if (isset($MCACHE)) {
+ $MCACHE->delete($reckey . '_fill');
+ }
return true;
}
* @return bool
*/
function rcache_unset_table ($table) {
- global $CFG, $rcache;
- if (isset($rcache->data[$table])) {
- unset($rcache->data[$table]);
+ global $CFG, $MCACHE, $rcache;
+
+ if ($CFG->rcache === 'internal') {
+ if (isset($rcache->data[$table])) {
+ unset($rcache->data[$table]);
+ }
+ return true;
+ }
+
+ if (isset($MCACHE)) {
+ $tablekey = $key = join('|', array($CFG->dbname, $CFG->prefix,
+ $table));
+ // at least as long as content keys to ensure they expire
+ // before the dirty flag
+ $MCACHE->set($tablekey, true, false, 2);
}
return true;
}
-
?>
\ No newline at end of file