panels_common_cache_set() takes $did as the second argument and saves it to the table field 'did', which is an integer.
Now, in:
- common.inc:948
- common.inc:1053
- panels_mini.module:603
- panels_page.admin.inc:578
panels_common_cache_set() is given a string as the second argument. Of course this is not critical, as no warning is thrown and the string is translated to 0. But we should do this at all.
Obviously, the did column is not needed for this to work correctly. So, it should be just okay if we'd pass in a NULL value instead.
But it is also clear that the panels_object_cache table has been initially created just for display objects. So eventually we might want to make it a bit more generic.
For now, I think we should go for the easy fix.
I also renamed $cache to $data (which is way more obvious) and made $did optional (defaulting to NULL). Also, panels_cache_set() used panels_common_cache_set() as if it was return anything. Finally, I added some basic PHPDoc.
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | 264304-12_panels_object_cache_refactoring.patch | 13.27 KB | sdboyer |
| #6 | panels_object_cache.patch | 12.53 KB | pancho |
| panels_common_cache_set.patch | 5.52 KB | pancho |
Comments
Comment #1
panchoIt's actually not that easy. Having no valid identifier for panel pages (resp. mini panels) means two instances of the same session can't discriminate two different panel pages: If two panel pages are being edited in separate browser tabs, their data will be mutually overwritten.
We should actually make our cache table more generic, and it would surely be a good idea to adopt the table layout of the main Drupal cache tables, just as Views and other modules do. Also, we should rename our cache table from panels_object_cache to cache_panels to be consistent and to ease up truncating the cache.
This is critical because if we want to do this that late, we need to do it now. I'm in favor.
Comment #2
merlinofchaos commentedActually, Views borrowed the object cache table from panels; I think it made it more generic, but it's actually still different from the cache tables.
I actually have a little documentation in Views 2 as to why, but let me explain some bits about this table:
1) in Drupal, the cache_* tables are volatile. You cannot rely on them ever actually containing data.
2) You have to use cid mapping to attach specific cache bits to users or dids or whatever. That's actually ugly.
THese differences are enough to make the table not at all the same thing. It's a cache, but it is not a volatile cache. It must be reliable. I used to store this data in the 'cache' table and it turns out there are some really, really exciting bugs that can come up because of that.
In Views 2, the table is keyed on session id, 'object' name, and object identifier. I think if we make any changes to the table, we make it match the views_object_cache table -- which means it's no longer tied directly to did, but still can be.
Comment #3
panchoYeah, taking over views_object_cache's schema would make sense. I hit this bug while working on #264868: Store imported $page/$mini in cache not in $_SESSION
If you support that change, I'll do a patch tonight!
Comment #4
sdboyer commented+1 for calling it 'swap' instead of 'cache'! :)
Comment #5
merlinofchaos commentedEnh. Don't like the term swap.
Comment #6
panchoHere's a patch that changes the table definition for panels_object_cache to allow for a more generic object storage.
Mainly, the following is done:
I renamed the field 'did' to 'name' to reflect the more generic content.
It turned out to be a problem that panel_page.name is 255 chars long: To store panel_page.name in panels_object_cache.name the latter would also have to be 255 chars long. But this would be too long for panels_object_cache's composite index.
I therefore settled for 128 chars and changed this in panel_page.name as well. This is no problem as the corresponding name field panels_page_edit_form (by default) has a #maxlength of 128 chars. I made this default property explicit, as it isn't obvious.
The same applies for panel_mini.
For consistency and performance reasons I resized panel_page.name and panel_mini.name to 128 chars. Even smaller would be better performancewise - IMHO 64 or even 32 chars should be enough -- hey, this is the internal name.
For the same index reason, obj had to be reduced to 64 chars. This should be enough though. Do you think, 32 chars would also be enough? We're using not more than 23 chars, do we need to expect custom client modules using more?
'timestamp' was renamed to 'updated' as that field name is used in views and is more descriptive. I also added 'unsigned NOT NULL default 0'.
'data' was changed from text to blob (resp. bytea in pgsql). It is also used in views and should be a bit more performant.
Also I made our composite key the Primary key to improve reliability.
For several reasons the table had to be truncated. This should be no problem though, as cached data doesn't need to be preserved over an update.
The patch has been tested on my Drupal installation on MySQL 5, but not on MySQL 4 and only rudimentary on PgSQL 7.4 and 8.0.
Todo:
- decide if panel_page.name and panel_mini.name, and subsequently panels_object_cache.name should be downsized to 64 or even 32 chars.
- decide if panels_object_cache.obj should be downsized to 32 chars.
- extensive testing, including performance.
Comment #7
panchoNeeds some work as in some cases duplicate entries are set. Now that our cache table has a Unique key, this throws a warning. That's a good sign though, as can now be aware of data integrity breaks.
Comment #8
panchoComment #9
sdboyer commentedOne quick thing, more to come later - data will need to be 'longblob', not just 'blob'. Generally though, I'm in support of this.
Comment #10
sdboyer commentedOK, I've been through all of this, but I've not yet tested it. +1 overall, but a little more needs to be done. A few specific points -
I'd like to see some checking done on the panels_mini and panels_page tables to see if reducing the length of the the internal system name field will actually truncate anyone's data. The safest option, and therefore the preferable one IMO, is to check beforehand to see whether any records do exceed the new limit. If they do, then another check is run to see if truncating the data to 128 characters will cause there to be any non-unique names. If not, then proceed with the update, but add a text warning (i.e., use 'success' => FALSE) that certain names have been truncated - indicate the old and new names. (I do a message like this in 5218, you can reference that syntax for sticking messages into $ret).
If running the update will result in there being non-unique names, then truncate them to 125 characters or so, and add an auto-incrementing unique ID to the end, and generate a similar message to the one generated in the other case - notify that there's been a truncation, and that you've automatically renamed some of them in order to avoid namespace conflicts.
Pain in the butt, and probably totally unnecessary, but it'll be MUCH worse if we have to deal with it in the queue.
Comment #11
sdboyer commentedOK, I continue to be in support of this. But! The patch does still need the same work as it did last time I posted (obviously).
I don't think that pushing this off until d6 is necessarily a bad idea. People will be paying close attention to their database upgrades when going through an update to d6, and I think that some of the potential stickiness here with the data truncation issue.
Actually, y'know what, screw it. We should be able to do this now. Hang on while I run it through a few tests and update things on my end.
Comment #12
sdboyer commentedAll right, I've written the necessary pieces to ensure that there's no duplicate keys. However, the patch still needs work, as the cache isn't behaving as it should in certain modal forms (cache, pane add/edit configuration...). So, reposting this, and hoping that Pancho will have some more time to work on it.
Comment #13
sdboyer commentedComment #14
esmerel commentedNo fixes are going to get committed to the 2.x line