Pave the way for pluggable sessions handling and sessions caching

robertDouglass - August 10, 2006 - 07:43
Project:Drupal
Version:x.y.z
Component:user system
Category:bug report
Priority:normal
Assigned:moshe weitzman
Status:closed
Description

I recently wanted to introduce memcached to a site and cache the sessions. This turned out to be slightly more difficult than expected because there is sessions handling code in user.module. This patch refactors that code out of user.module and puts it all in session.inc, where it belongs.

The advantages of doing this are many. First, we can easily switch our method of handling sessions by loading a different session.inc file (like chx's memcached_session.inc) during bootstrap. This makes session handling pluggable and will be a great asset to sites that want to manage sessions in-memory (like Digg and NowPublic). A second advantage is that the functionality of counting online users (formerly coded into the online users block of user.module) is now available as an API: drupal_count_sessions, and supports the counting of anonymous, authenticated or both.

AttachmentSize
pluggablesessions.patch5.69 KB

#1

robertDouglass - August 10, 2006 - 15:31

rm extraneous ''

AttachmentSize
pluggablesessions_0.patch5.66 KB

#2

robertDouglass - August 12, 2006 - 12:34

Hmmm.... maybe the '' wasn't so extraneous:

<?php
function sess_destroy($key, $type = 'sid') {
 
db_query("DELETE FROM {sessions} WHERE %s = '%s'", $type, $key);
}
?>

Does this open us up to SQL injection? Then use the first patch.

#3

robertDouglass - August 12, 2006 - 12:37

<?php
function drupal_count_sessions($timestamp = 0, $anonymous = 0) {
  switch (
$anonymous) {
    case
0:
     
$query ' AND uid = 0';
      break;
    case
1:
     
$query = ' AND uid > 0';
      break;
    default:
     
$query = '';
  }
?>

Does anyone else find it counter-intuitive if $anonymous = 0? Would the function feel better like this?

<?php
function drupal_count_sessions($timestamp = 0, $anonymous = true) {
 
$query = ($anonymous) ? ' AND uid = 0' : ' AND uid > 0';
  ...
?>

#4

robertDouglass - August 12, 2006 - 13:07

I like this one better. Addresses both of the above concerns. (note: the first patch doesn't work due to the '%s' = '%s' construction, so to avoid SQL injection I introduced my own validation on the parameter).

AttachmentSize
pluggablesessions_1.patch5.67 KB

#5

robertDouglass - August 13, 2006 - 11:31

Use true and false instead of 0 and 1 for better clarity (it is too psychologically confusing since we're talking about whether or not to query for uid = 0).

AttachmentSize
pluggablesessions_2.patch5.68 KB

#6

robertDouglass - August 13, 2006 - 11:37

Ooops, I'd introduced a bug in the query that gets the info for online authenticated users.

AttachmentSize
pluggablesessions_3.patch5.8 KB

#7

chx - August 13, 2006 - 14:00

sess_destroy IMO is conceptually wrong. Unless PHP calls it with random second parameters just document the valid chooses and remove that switch. Drupal sees such constructs as unnecessary cruft. Yes, if you call that function with the wrong parameters, then the program dies. So what? Don't call with wrong parameters.

#8

robertDouglass - August 13, 2006 - 14:35

the switch is not to keep you from calling the function with a wrong second parameter, it is to allow me to safely put that parameter in the query without '', which is our protection against SQL injection. Calling the function without the switch and with SQL injection in the 2nd parameter is what I was worried about; maybe I'm misplacing my concern?

#9

drumm - August 15, 2006 - 06:59
Status:patch (code needs review)» patch (code needs work)

Add a code comment to document that last follow-up. And i'm not sure we want to use %s for that, I think string concatenation is fine in that case.

#10

robertDouglass - August 15, 2006 - 07:37

Rerolled to track HEAD; followed all of Drumm's suggestions.

AttachmentSize
pluggablesessions_4.patch5.97 KB

#11

robertDouglass - August 15, 2006 - 07:42

Changed syntax for the parameter checking to something less verbose.

AttachmentSize
pluggablesessions_6.patch5.92 KB

#12

robertDouglass - August 15, 2006 - 07:42
Status:patch (code needs work)» patch (code needs review)

#13

moshe weitzman - August 16, 2006 - 03:04
Status:patch (code needs review)» patch (reviewed & tested by the community)

i improved docs a bit and add made throttle.module use the new drupal_count_sessions(). i grepped and noone else is touching sessions table anymore.

i tested the patch and seems fine.

incidentally, it would be very good to find a different way to count anon users so we didn't have to fill up session table with their records. both user block and throttle module currently use this info.

AttachmentSize
patch_9037.54 KB

#14

moshe weitzman - August 16, 2006 - 03:06

oops. proper patch here.

AttachmentSize
patch_916.44 KB

#15

moshe weitzman - August 16, 2006 - 03:10

oy. some .brzignore cruft in the last one. better one attached.

AttachmentSize
patch_926.34 KB

#16

Dries - August 16, 2006 - 04:48

(Please don't commit this yet. Want to review/test it first.)

#17

Dries - August 16, 2006 - 04:49

Also, please share performance results if possible.

#18

drumm - August 16, 2006 - 07:54
Status:patch (reviewed & tested by the community)» patch (code needs review)

#19

moshe weitzman - August 24, 2006 - 14:11

@Dries - any chance you can benchmark this on your rig? High volume sites could really use this.

#20

moshe weitzman - August 24, 2006 - 15:21

rerolled for HEAD

AttachmentSize
patch_1066.42 KB

#21

Amazon - August 31, 2006 - 07:40

What testing steps do you want?

If you outline the steps we maybe able to deploy on a hardware cluster and test it.

Kieran

#22

robertDouglass - August 31, 2006 - 09:18

This patch changes almost no logic... it just moves some code around.

To test you would make sure that people can log in, log out; that stuff that goes into their session stays in their session (such as comment format preferences). You would test that the number of authenticated and anonymous users in the "Who's online" block is accurate.

There is no need to test performance because there is *no* performance gain implicit in this patch. However, since it moves all of the session logic to one file, it is now possible to easily swap that file out with one that handles sessions totally differently, with memcached or LDAP or whatever.

#23

Dries - August 31, 2006 - 10:56
Status:patch (code needs review)» patch (code needs work)

No longer applies.

#24

jvandyk - August 31, 2006 - 11:54

drupal_count_sessions is broken. $timestamp parameter vs. $time_period used.

Unnecessary parentheses in $query definition.

+1 for pluggable session handling.

#25

moshe weitzman - August 31, 2006 - 13:04
Assigned to:Anonymous» moshe weitzman
Status:patch (code needs work)» patch (reviewed & tested by the community)

fixed issues reported by JVD. i tested logout/login and who's online block. looks good.

as robert said, this patch just moves code around, and has no impact on performance.

AttachmentSize
patch_1136.37 KB

#26

Dries - August 31, 2006 - 14:29

Any performance results that back up the need for this, or that demonstrate the performance gain of alternative session mechanisms? While I believe that it can be useful, I'd be interested in those. I'm a curious person. :)

Anyway, I think that drupal_count_sessions should be called sess_count (for consistency). Oh, and I wouldn't mind a s/sess_/session_/cg after that. We don't abbreviate words like 'sessions'.

#27

robertDouglass - August 31, 2006 - 14:48

I think session_destroy and so forth are off limits as they're already built-in php functions. I could make drupal_count_sessions into sess_count, or I could rename all the redefined session functions drupal_session_*. Do you have a preference?

#28

robertDouglass - August 31, 2006 - 15:04

sess_count it is. I also discovered that the query on the users table to count authenticated users was wrong because it doesn't address authenticated users who log off. Now both anonymous and authenticated users are counted using sess_count, which is the way it was intended. I also renamed the variables in user.module to $authenticated and $anonymous to better reflect what it is they do.

AttachmentSize
pluggablesessions_7.patch7.06 KB

#29

robertDouglass - August 31, 2006 - 15:07

ok I broke the users list. Going back to fix. The sad truth is, we can't count authenticated users from the users table... the only accurate counting is the sess_count. That means that the list of online users is also inaccurate and doesn't account for users who just logged out.

#30

robertDouglass - August 31, 2006 - 15:13

now we do both sess_count for authenticated users and the query on the users table to get the users' data. The count is accurate but the list may not be. We could fix this by changing the wording from "Online users" to "Recently seen".

AttachmentSize
pluggablesessions_8.patch7.41 KB

#31

Dries - August 31, 2006 - 15:13

Why the second paramater to sess_destroy()? Type is always $uid so it is not actually needed. Don't complicate this patch. ;-)

#32

robertDouglass - August 31, 2006 - 15:16

you don't see the need for ending a session based on SID?

#33

robertDouglass - August 31, 2006 - 15:23

without the second parameter to sess_destroy.

AttachmentSize
pluggablesessions_9.patch7.04 KB

#34

robertDouglass - August 31, 2006 - 15:29

no, this is broken. Don't commit.

#35

robertDouglass - August 31, 2006 - 15:38

replaced a call to session_destroy (the php function) in user_logout. It was calling sess_destroy with the SID. Now we always call sess_destroy directly with $uid, simplifying the matter greatly.

#36

robertDouglass - August 31, 2006 - 15:39

patch

AttachmentSize
pluggablesessions_10.patch7.25 KB

#37

robertDouglass - August 31, 2006 - 15:47
Status:patch (reviewed & tested by the community)» patch (code needs review)

Looking for reviewers.

#38

Dries - August 31, 2006 - 17:24

<?php
$result = db_fetch_object(db_query('SELECT COUNT(sid) AS count FROM {sessions} WHERE timestamp >= %d'. $query, $timestamp));
+  return
$result->count;
?>

can be:
<?php
+  return db_result(db_query('SELECT COUNT(sid) AS count FROM {sessions} WHERE timestamp >= %d'. $query, $timestamp));
?>

Add spaces around '-':
<?php
... time()-$time_period ...
...
time() - $time_period ...
?>

Otherwise looks good.

#39

robertDouglass - August 31, 2006 - 18:47

ok

AttachmentSize
pluggablesessions_11.patch7.22 KB

#40

robertDouglass - August 31, 2006 - 19:34
Status:patch (code needs review)» patch (reviewed & tested by the community)

#41

Dries - August 31, 2006 - 19:55
Status:patch (reviewed & tested by the community)» fixed

Committed to CVS HEAD. Thanks.

#42

robertDouglass - September 6, 2006 - 10:06
Status:fixed» patch (reviewed & tested by the community)

there's a misnamed variable in the last version.

AttachmentSize
user.patch_10.txt693 bytes

#43

robertDouglass - September 6, 2006 - 10:23

and unrelated to the bug in the previous followup, here is a patch against 4.7 in case anybody is interested.

AttachmentSize
pluggablesessions47.patch.txt7.49 KB

#44

Dries - September 6, 2006 - 11:17
Status:patch (reviewed & tested by the community)» fixed

Committed to CVS HEAD. Thanks.

#45

Anonymous - September 20, 2006 - 11:30
Status:fixed» closed

#46

moshe weitzman - November 6, 2006 - 15:49

we never edited bootstrap.inc so that it is possible to use other session.inc like we now offer for cache.inc. so our CHANGELOG is a lie: "pluggable session handler ..."

help please.

 
 

Drupal is a registered trademark of Dries Buytaert.