Hi, I've find it at last !!
there is a bug in the object cache of WordpressMu. (in fact, there are two bugs);
1) The first one is about the "key" function of the cache. This function is used to calculate a hash key based on the group dir and the data key. But this function is also used to calculate "group" key by calling it with '' parameter for the data key. In this case, the function returns a group key like "<group name>:" the ":" is useless and confused the function that saves the cache because she used the key to detect the group name.
2) The second bug is that in the "save" function of the cache, we loop through the "cache" array using this function "$this->cache[$group][$id]", but we set the data using "$this->cache[$hash]" where $hash is a key calculated using the above function... strange
I don't know if it's very clear (sorry for my bad english...) but to correct the bugs, you must make the following changes in the file "wp-includes/cache.php" :
NOTE : I'm not really sure that everything is OK with the changes i've made. It's based on my own code analysis. If someone of the developpement team could check it, it would be nice.
Replace the function "key" :
function key($key, $group) {
global $blog_id;
if ( empty($group) )
$group = 'default';
if (false !== array_search($group, $this->global_groups))
$prefix = '';
else
$prefix = $blog_id . ':';
//Correct Bug
if ($key!='')
$key=":".$key;
return "$prefix$group$key";
}
Replace the "save" function with :
function save() {
//$this->stats();
if (!$this->cache_enabled)
return true;
if (empty ($this->dirty_objects))
return true;
// Give the new dirs the same perms as wp-content.
$stat = stat(ABSPATH.'wp-content');
$dir_perms = $stat['mode'] & 0007777; // Get the permission bits.
$file_perms = $dir_perms & 0000666; // Remove execute bits for files.
// Make the base cache dir.
if (!file_exists($this->cache_dir)) {
if (! @ mkdir($this->cache_dir))
return false;
@ chmod($this->cache_dir, $dir_perms);
}
if (!file_exists($this->cache_dir."index.php")) {
@ touch($this->cache_dir."index.php");
@ chmod($this->cache_dir."index.php", $file_perms);
}
if ( ! $this->acquire_lock() )
return false;
// Loop over dirty objects and save them.
$errors = 0;
foreach ($this->dirty_objects as $group => $ids) {
$group_key = $this->key( '', $group );
$group_dir = $this->make_group_dir($group_key, $dir_perms);
$ids = array_unique($ids);
foreach ($ids as $id) {
$cache_file = $group_dir.$this->hash($id).'.php';
//Correct bug : Calculate hash
$hash = $this->key($id, $group);
// Remove the cache file if the key is not set.
//Correct bug : use hash in array
if (!isset ($this->cache[$hash])) {
if (file_exists($cache_file))
@ unlink($cache_file);
continue;
}
$temp_file = tempnam($group_dir, 'tmp');
//Correct bug : use hash in array
$serial = CACHE_SERIAL_HEADER.base64_encode(serialize($this->cache[$hash])).CACHE_SERIAL_FOOTER;
$fd = @fopen($temp_file, 'w');
if ( false === $fd ) {
$errors++;
continue;
}
fputs($fd, $serial);
fclose($fd);
if (!@ rename($temp_file, $cache_file)) {
if (@ copy($temp_file, $cache_file))
@ unlink($temp_file);
else
$errors++;
}
@ chmod($cache_file, $file_perms);
}
}
$this->dirty_objects = array();
$this->release_lock();
if ( $errors )
return false;
return true;
}
It was a hard work to find it. I hope it can help someone...