Hello. I installed memcache and some pages of my site don't get updated for anonymous users. For example, when users post new blog entries, /blog page is not refreshed in cache. Same thing with new comments not displayed, deleted information still displayed for anonymous users etc etc. I guess it's problem with cache_page but there is maybe more general problem with my site. I think it is clearly cache related problem cause everything works ok in general, and pages work ok for logged in users.
Here is my setup:

'memcache_servers' => array(
                              'localhost:11211' => 'default',
                              'localhost:11212' => 'cluster2',
                              'localhost:11213' => 'cluster3',
                              'localhost:11214' => 'cluster4',
                              'localhost:11215' => 'cluster5',
                              'localhost:11216' => 'cluster6',
                              'localhost:11217' => 'cluster7',
                             ),
  'memcache_bins' => array(
                           'cache' => 'default',
                           'cache_page' => 'cluster2',
                           'cache_menu' => 'cluster3',
                           'cache_filter' => 'cluster4',
                           'cache_content' => 'cluster5',
                           'cache_captcha' => 'cluster6',
                           'cache_views' => 'cluster7',
                          ),
);

Drupal 5.6 with serialize patch, views and cck serialize patches applied too. I have 7 memcache daemons that run on ports listed above. At admin/performance caching mode set to normal caching. Memcached daemon version 1.2.2, PHP 5.2.6 compiled as fast-cgi with pecl memcache version 2.2.3 and eaccelerator 0.9.5.3 extensions.
Please tell me if anything wrong with my setup or what direction to look in to solve my problem. Thanks

Comments

crea’s picture

To be more clear, I have minimum cache lifetime set to "none", if I understand it correctly that should mean invalidate cache_page immediatly if content is changed

I use http://drupal.org/node/152983 for manual clearing and it works ok, but ofcourse it's not solution to my problem

chx’s picture

Assigned: Unassigned » chx
Category: support » bug
Priority: Normal » Critical
Status: Active » Reviewed & tested by the community
StatusFileSize
new1.04 KB

This is as bad as it can be because currently we flush the NULL table and that leads to flushin 'cache' instead 'cache_page':

if (empty($memcache_bins[$bin]) && !empty($memcacheCache['cache'])) {
  $memcacheCache[$bin] = &$memcacheCache['cache'];
}
slantview’s picture

 function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
+  // We cover the occassional explicit NULLs as well this way.
+  if (empty($table)) {
+    $table == 'cache';
+  }
   // Memcache logic is simpler because memcache doesn't have a minimum cache
   // lifetime consideration (it handles it internally), and doesn't support
   // wildcards.
-  $bin = empty($table) ? 'cache' : $table;
   if (empty($cid) || ($cid == '*' && $wildcard !== TRUE)) {
     // don't do anything if cid is unset. this matches the default drupal behavior...
     if ($wildcard && $cid != '*') {

There is a typo when you are trying to set the table to 'cache' you have an == instead of an = sign. Also, how is this different? I read this as you would rather flush 'cache_page' but in this patch you are still attempting to set it to cache. you just changed the ternary operator into a full if statement. Am I missing something?

allie micka’s picture

Status: Reviewed & tested by the community » Needs work
nicholasthompson’s picture

Slantview, its similar...

The ternary sets $bin to be 'cache' if $table is empty, otherwise sets it to $table.
The patch, on the other hand, sets $table to 'cache' if $table is empty.

Whats wrong with flushing cache if you've not specified a table? If a table is not specified, should $table be "*"?

crea’s picture

Hmmmm.... How this kind of bug could exist after so many people use memcache module ? If page cache is not flushing at all that means site is almost not working :(
These moments just make me think how much of importance proper software testing is. Guess all you guys use cache and cache_page tables in one memcache bin so you don't notice this problem (in that case 'cache_page' is flushed together with 'cache' )

crea’s picture

So you say, after update of content function cache_clear_all() is called without $table argument
It seems so, for example from the end of node_save function in core

  // Clear the cache so an anonymous poster can see the node being added or updated.
  cache_clear_all();
}

from original cache.inc:

function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
  global $user;

  if (!isset($cid) && !isset($table)) {
    cache_clear_all(NULL, 'cache_page');
    return;
  }

Guess we should follow same rule then and flush cache_page if both $cid and $table are null

crea’s picture

chx, what version of memcache module you made your patch against ?
It wouldn't apply anyway, because there is no such line

$bin = empty($table) ? 'cache' : $table;

You messed it a bit :)
I guess error comes from using variable $bin in $table argument check. There is line

$bin = empty($table) ? 'cache_page' : $table;

but it's not working because we dont use $bin anymore in the function. Proper patch should include checking like this
if (!isset($cid) && !isset($table)) and setting $table variable to 'cache_page' instead of $bin variable

crea’s picture

It seems cache_clear_all() needs serious rework, cause comments like this don't make any sense

// don't do anything if cid is unset. this matches the default drupal behavior...

It actually DOESN'T match default drupal behavior when cache_clear_all() is called without arguments to flush cache.
This is awful.

I guess we should check if $table and $cid are null then set $table to 'cache_page' and call dmemcache_flush($table) ( it isn't called now, because $cid is null and we "don't do anything if cid is unset" :P )

crea’s picture

The following change fixed bug for me. Please test it too.

-  $bin = empty($table) ? 'cache_page' : $table;
+  if (!isset($cid) && !isset($table)) {
+    dmemcache_flush('cache_page');
+    return;
+  }

But I guess function code needs major rework to make code more clean ( and to remove nonsense comments :P )

chx’s picture

Status: Needs work » Needs review
StatusFileSize
new1.05 KB

Of course this needs to be cache_page...

crea’s picture

Status: Needs review » Needs work

chx, did you read my comments ? Your patch will not work because $cid is NULL too and dmemcache_flush() won't run.
Also this patch will not apply too ( same as above )

crea’s picture

Funny thing is, in memcache.db.inc there is correct code that handles flushes:

  if (!isset($cid) && !isset($table)) {
    cache_clear_all('*', 'cache_page', TRUE);
    return;
  }

but somehow this code didn't make it to memcache.inc ... :)

chx’s picture

Assigned: chx » Unassigned
Status: Needs work » Active

No time to work on this. I found the bug I let others patch it, we run our own hacked version which never flushes page_cache but lets invidual items expire after 300s.

dgtlmoon’s picture

subscribing, this aint good :D

jeremy’s picture

Assigned: Unassigned » jeremy
Status: Active » Needs review
StatusFileSize
new1.83 KB
new1.64 KB

Here are patches for memcache.inc and memcache.db.inc, updating the logic and the comments.

Patches were sponsored by ConsumerSearch.

Rather than adding a second call to dmemcache_flush, I update the parameters and fall through to the correct place. This way the same logic works in both memcache.inc and memcache.db.inc, and we don't have to recursively call ourselves as was happening in memcache.db.inc.

jeremy’s picture

Status: Needs review » Fixed

Committed to development branch.

jeremy’s picture

Also committed to DRUPAL-5 branch.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

jeremy’s picture

Version: 5.x-1.8 » 6.x-1.x-dev
Status: Closed (fixed) » Active

This bug still affects the 6.x version.

jeremy’s picture

Status: Active » Fixed

Patch ported to 6.x, committed.

6.x debugging sponsored by ParentsClick / Lifetime Digital.

jvandyk’s picture

Status: Fixed » Active

In D6, the cache_block table needs flushing too. See comments in cache_clear_all() of memcache.db.inc.

jeremy’s picture

Status: Active » Fixed

Thanks for catching that -- fix committed.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.