Problem/Motivation
If wildcards
are used to clear the cache (cache_clear_all('filter_list_format', 'cache', TRUE);
), the cache isn't cleared as expected.
A full cache clear by using cache_clear_all('*', 'cache', TRUE)
works as expected.
Steps to reproduce:
- Using Filter Formats
-
- Open a filter and change its settings
- Save settings
- Re-open the same filter again:
Expected: Form reflects changes.
Actual: Form reflects the old settings. - Flush cache
- Re-open the same filter again - now the form reflects the new settings.
- Using Menu
-
- Open Menu Link and change its label
- Save changes
- Check if the change is reflected in the frontend:
Expected: Menu link label has changed.
Actual: Menu link label is still the same. - Flush cache.
- Check again if the change is reflected in the frontend: - now the menu link label has changed.
Looks like this is a follow-up of one of the various other wildcart issues we had:
- #931036: Wildcard flushing not working
- #1085626: Wildcard entries may go missing, leading to caches not being invalidated properly
- #885076: wildcard prefix cache clears failing
- #1307102: Tests for wildcard clears are broken again...
- #927692: Collisions in multihash_cid cause problems with wildcard flush
- #1281484: Wildcard clears are broken except on same page when they are still in the static cache
Please have a look at the new tests added with the patch in #1344036-1: Backport tests from: Cache clear fails when using wildcards - strange behavior with wildcard_valid()
Proposed resolution
Make sure the proper cache key is used for increment
in wildcards()
.
Remaining tasks
User interface changes
none
API changes
none
Original report by weri
We have some strange behaviours when memcache is enabled. For example: The format edit form (admin/config/content/formats/full_html).
When we change the enabled filters and safe the configuration, after the request the "old" checkboxes are selected. The changes are saved in the database but the settings are loaded from the cache (cache_get('filter_list_format') in filter.module). But the cached data is cleared after the form submit in the function filter_formats_reset() (cache_clear_all('filter_list_format', 'cache', TRUE);).
When I insert a cache_get('filter_list_format') directly after the cache_clear_all('filter_list_format', 'cache', TRUE), the return value is FALSE. That's correct, but after the form submission (drupal_goto()) the next cache_get('filter_list_format') loads the "old" object from cache and does not return FALSE anymore and prevent the module to load the settings from the database and store the new values with cache_set (filter.module line 660 in the function filter_list_format($format_id)).
When i change cache_clear_all('filter_list_format', 'cache', TRUE) to cache_clear_all('*', 'cache', TRUE), everything is cleared correctly and the settings are updated.
I could reproduce this behaviour on two different Drupal 7.9 installations.
Comment | File | Size | Author |
---|---|---|---|
#9 | fix_wildcard_saving_with_tests.patch | 9.07 KB | Berdir |
#4 | memcache-fix-for-wildcard-flush-1344036-4.diff | 492 bytes | das-peter |
#4 | memcache-attempt-to-create-better-tests.diff | 7.65 KB | das-peter |
#1 | memcache_real_world_tests.patch | 3.54 KB | das-peter |
Comments
Comment #1
das-peter CreditAttribution: das-peter commentedI didn't have the time for actual bug-hunting yet, but I've created a new test class to use the menu to verify the bug.
How to use the new test:
Real world cache tests
Real world cache tests
Comment #2
das-peter CreditAttribution: das-peter commentedAdded summary according to the Issue summary standards.
Modified title to be more general.
Comment #3
catchBumping to critical, this should block a 1.0 release.
Comment #4
das-peter CreditAttribution: das-peter commentedI can't believe how long I now debugged to fix this single line...
Root cause of the whole issue was that
MemCacheDrupal::wildcards()
didn't usedmemcache_key()
on this particular line but for lookupdmemcache_get_multi()
is used which internally usesdmemcache_key()
.That way the whole counting became inconsistent.
I've tried to another approach to create tests to cover that but I wasn't able to figure out how to really test that, nevertheless I've attached a patch with what I tried.
The tests I've added in #1 pass now.
Comment #5
das-peter CreditAttribution: das-peter commentedOh of course this needs review now :)
Comment #6
das-peter CreditAttribution: das-peter commentedBefore I forget it: Another change I thought of is to replace the
increment
by aset
.Currently:
Idea:
Advantage of this would be that even if initially something went wrong the value is later properly set. Because if you use
increment
it wont create a item if it doesn't already exist.Comment #6.0
das-peter CreditAttribution: das-peter commentedChanged summary to fit the new summary initiative standards
Comment #7
BerdirUsing set() instead of increment() sounds interesting, especially because we could then use the dmemcache_set() helper function, so that the encoding of the $key is again consistently encapsulated by dmemcache_*() functions.
Will look into the tests if I find the time.
Comment #8
weri CreditAttribution: weri commentedI applied the patch #4 and it resolved our problem.
Comment #9
BerdirOk, you were actually quite close with your tests, all I had to do was adding a second round of set/get/clear/get because the initial wildcard is written using dmemcache_set() which correctly encoded $key.
The attached patch now consistently uses dmemcache_set() to write the wildcard. This might be bit slower but is way more failure tolerant (e.g. memcache restarts) and consistent.
The attached patch passed all tests for me locally.
Comment #10
das-peter CreditAttribution: das-peter commentedAwesome! Thanks for your effort.
dmemcache_set()
sounds very good to me. Code will be more consistent and maybe somewhat self-healing within the same request :DComment #11
catchThis all makes sense, I've committed/pushed to 7.x-1.x.
We should backport the tests, and possibly the set/get change to 6.x (the increment usage is correct there though since it uses dmemcache_key(), so dropping priority for the backport).
Comment #12
catchRe-titling.
Comment #13
Cyberwolf CreditAttribution: Cyberwolf commentedI am still encountering the same issue, both with memcache-7.x-1.0 as 7.x-1.x-dev (2012-Jan-30) releases. I have the following configuration in settings.php (I replaced the IP with ***):
When I add the following modifying input formats works again like it should:
But of course we also want to use Memcache for the general cache bin.
Comment #14
catch@Cyberwolf, 'same issue' isn't enough information, and the fact we added simpletests here suggests you're most likely hitting a different bug. I'm going to move this back to 6.x for the test backport, however please open a new bug, against 7.x, with clear steps to reproduce (ideally starting with a clean install of Drupal 7 + memcache 7.x-1.0 and nothing else), thanks!
Comment #15
Cyberwolf CreditAttribution: Cyberwolf commentedI will specify more clearly what I mean with 'the same issue' then: I am unable to modify input formats with memcache-7.x-1.0 or 7.x-1.x-dev (2012-Jan-30) releases with the following configuration in settings.php:
It's exactly the same behavior as described in the original report by weri.
Will retry on a completely clean install and let you know if it works now or not.
Comment #16
BerdirAlso make sure that you're not using a broken memcache extension or server, see http://drupal.org/node/1131470
Comment #17
Cyberwolf CreditAttribution: Cyberwolf commentedThat probably explains everything, we are indeed using PECL memcache 3.0.4 which apparently has a bug with wildcard flushes. I'll ask our sysadmins to update to a newer version. Thanks @Berdir for pointing me in the right direction!
Comment #18
Cyberwolf CreditAttribution: Cyberwolf commentedThe memcache extension was upgraded and now it works correctly here with the Drupal memcache module 7.x-1.x-dev.
Comment #18.0
Cyberwolf CreditAttribution: Cyberwolf commentedUpdated issue summary.