? d7_memcache.patch
? d7_review.txt
? memcache.module
? memcache.test
? sess.d7.patch
Index: memcache-session.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/memcache/memcache-session.inc,v
retrieving revision 1.4.2.1
diff -u -p -r1.4.2.1 memcache-session.inc
--- memcache-session.inc	5 Dec 2009 00:26:30 -0000	1.4.2.1
+++ memcache-session.inc	11 Dec 2009 00:34:13 -0000
@@ -10,15 +10,15 @@ require_once dirname(__FILE__) . '/dmemc
  * An alternative to includes/session.inc.
  */
 
-function sess_open($save_path, $session_name) {
+function _drupal_session_open() {
   return TRUE;
 }
 
-function sess_close() {
+function _drupal_session_close() {
   return TRUE;
 }
 
-function sess_read($key) {
+function _drupal_session_read($key) {
   global $user;
 
   // Write and Close handlers are called after destructing objects since PHP 5.0.5
@@ -26,20 +26,20 @@ function sess_read($key) {
   // So we are moving session closure before destructing objects.
   register_shutdown_function('session_write_close');
 
-  // Handle the case of first time visitors and clients that don't store 
+  // Handle the case of first time visitors and clients that don't store
   // cookies (eg. web crawlers).
   if (!isset($_COOKIE[session_name()])) {
     $user = drupal_anonymous_user();
     return '';
   }
 
-  // Otherwise, if the session is still active, we have a record of the 
+  // Otherwise, if the session is still active, we have a record of the
   // client's session in memcache.
   $session = dmemcache_get($key, 'session');
-  
-  $user = sess_user_load($session);
 
-  // Record whether this session contains data so that in sess_write() it can 
+  $user = _memcache_session_user_load($session);
+
+  // Record whether this session contains data so that in sess_write() it can
   // be determined whether to skip a write.
   $user->session_data_present_at_load = !empty($session->session);
 
@@ -70,7 +70,7 @@ function sess_read($key) {
  * @return
  *   TRUE.
  */
-function sess_write($key, $value) {
+function _drupal_session_write($key, $value) {
   global $user;
 
   // If the client doesn't have a session, and one isn't being created ($value),
@@ -90,10 +90,10 @@ function sess_write($key, $value) {
   $session->timestamp = time();
 
   // If this is an authenticated user, or there is something to save in the
-  // session, or this is an anonymous user who currently has nothing in the 
+  // session, or this is an anonymous user who currently has nothing in the
   // session but did have something in session storage, write it to memcache.
   // If $user->session_data_present_at_load is not set, the current user
-  // was created during this request and it's safest to do a write. 
+  // was created during this request and it's safest to do a write.
   // Cases 1b, 1d, 2a, and 2b are covered here.
   if ($user->uid || !empty($value) || empty($value) && (!isset($user->session_data_present_at_load) || $user->session_data_present_at_load)) {
     dmemcache_set($key, $session, ini_get('session.gc_maxlifetime'), 'session');
@@ -109,23 +109,64 @@ function sess_write($key, $value) {
     unset($user->session_data_present_at_load);
     // Store the session id so we can locate the session with the user id.
     $user->sid = $key;
-    
+
     dmemcache_set($user->uid, $user, ini_get('session.gc_maxlifetime'), 'users');
   }
 
   return TRUE;
 }
 
-function sess_regenerate() {
-  // We code around http://bugs.php.net/bug.php?id=32802 by destroying
-  // the session cookie by setting expiration in the past (a negative
-  // value).  This issue only arises in PHP versions before 4.4.0,
-  // regardless of the Drupal configuration.
-  // TODO: remove this when we require at least PHP 4.4.0
+
+/**
+ * Called by PHP session handling with the PHP session ID to end a user's session.
+ *
+ * @param  string $sid
+ *   the session id
+ */
+function _drupal_session_destroy($sid) {
+  dmemcache_delete($sid, 'session');
+}
+
+function _drupal_session_garbage_collection($lifetime) {
+  // Automatic with memcached.
+  // Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
+  // value. For example, if you want user sessions to stay in your database
+  // for three weeks before deleting them, you need to set gc_maxlifetime
+  // to '1814400'. At that value, only after a user doesn't log in after
+  // three weeks (1814400 seconds) will his/her session be removed.
+  return TRUE;
+}
+
+/**
+ * Initialize the session handler, starting a session if needed.
+ */
+function drupal_session_initialize() {
+  global $user;
+
+  session_set_save_handler('_drupal_session_open', '_drupal_session_close', '_drupal_session_read', '_drupal_session_write', '_drupal_session_destroy', '_drupal_session_garbage_collection');
+
   if (isset($_COOKIE[session_name()])) {
-    setcookie(session_name(), '', time() - 42000, '/');
+    // If a session cookie exists, initialize the session. Otherwise the
+    // session is only started on demand in drupal_session_commit(), making
+    // anonymous users not use a session cookie unless something is stored in
+    // $_SESSION. This allows HTTP proxies to cache anonymous pageviews.
+    drupal_session_start();
+    if (!empty($user->uid) || !empty($_SESSION)) {
+      drupal_page_is_cacheable(FALSE);
+    }
   }
+  else {
+    // Set a session identifier for this request. This is necessary because
+    // we lazyly start sessions at the end of this request, and some
+    // processes (like drupal_get_token()) needs to know the future
+    // session ID in advance.
+    $user = drupal_anonymous_user();
+    session_id(md5(uniqid('', TRUE)));
+  }
+}
+
 
+function sess_regenerate() {
   // Store the current (anonymous) session id.
   $old_session_id = session_id();
 
@@ -151,23 +192,102 @@ function sess_regenerate() {
  * Would be insane slow with memcached as we would need to retrieve at least the stats of all object.
  * Not implemented.
  */
-function sess_count($timestamp = 0, $anonymous = true) {
+function drupal_session_count($timestamp = 0, $anonymous = true) {
 }
 
 /**
- * Called by PHP session handling with the PHP session ID to end a user's session.
+ * Forcefully start a session, preserving already set session data.
  *
- * @param  string $sid
- *   the session id
+ * @ingroup php_wrappers
  */
-function sess_destroy_sid($sid) {
-  dmemcache_delete($sid, 'session');
+function drupal_session_start() {
+  if (!drupal_session_started()) {
+    // Save current session data before starting it, as PHP will destroy it.
+    $session_data = isset($_SESSION) ? $_SESSION : NULL;
+
+    session_start();
+    drupal_session_started(TRUE);
+
+    // Restore session data.
+    if (!empty($session_data)) {
+      $_SESSION += $session_data;
+    }
+  }
+}
+
+/**
+ * Commit the current session, if necessary.
+ *
+ * If an anonymous user already have an empty session, destroy it.
+ */
+function drupal_session_commit() {
+  global $user;
+
+  if (!drupal_save_session()) {
+    // We don't have anything to do if we are not allowed to save the session.
+    return;
+  }
+
+  if (empty($user->uid) && empty($_SESSION)) {
+    // There is no session data to store, destroy the session if it was
+    // previously started.
+    if (drupal_session_started()) {
+      session_destroy();
+    }
+  }
+  else {
+    // There is session data to store. Start the session if it is not already
+    // started.
+    if (!drupal_session_started()) {
+      drupal_session_start();
+    }
+    // Write the session data.
+    session_write_close();
+  }
+}
+
+/**
+ * Return whether a session has been started.
+ */
+function drupal_session_started($set = NULL) {
+  static $session_started = FALSE;
+  if (isset($set)) {
+    $session_started = $set;
+  }
+  return $session_started && session_id();
 }
 
 /**
+ * Called when an anonymous user becomes authenticated or vice-versa.
+ *
+ * @ingroup php_wrappers
+ */
+function drupal_session_regenerate() {
+  global $user;
+  if (drupal_session_started()) {
+    $old_session_id = session_id();
+    session_regenerate_id();
+  }
+  else {
+    // Start the session when it doesn't exist yet.
+    // Preserve the logged in user, as it will be reset to anonymous
+    // by _drupal_session_read.
+    $account = $user;
+    drupal_session_start();
+    $user = $account;
+  }
+
+  if (isset($old_session_id)) {
+    $session = dmemcache_get($old_session_id, 'session');
+    dmemcache_set($sesion_id, $session, ini_get('session.gc_maxlifetime'), 'session');
+  }
+}
+
+
+/**
  * End a specific user's session.
  */
-function sess_destroy_uid($uid) {
+function drupal_session_destroy_uid($uid) {
   $user = dmemcache_get($uid, 'users');
   if (is_object($user) && isset($user->sid)) {
     dmemcache_delete($user->sid, 'session');
@@ -175,15 +295,6 @@ function sess_destroy_uid($uid) {
   dmemcache_delete($uid, 'users');
 }
 
-function sess_gc($lifetime) {
-  // Automatic with memcached.
-  // Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
-  // value. For example, if you want user sessions to stay in your database
-  // for three weeks before deleting them, you need to set gc_maxlifetime
-  // to '1814400'. At that value, only after a user doesn't log in after
-  // three weeks (1814400 seconds) will his/her session be removed.
-  return TRUE;
-}
 
 /**
  * Determine whether to save session data of the current request.
@@ -197,8 +308,8 @@ function sess_gc($lifetime) {
  * @return
  *   FALSE if writing session data has been disabled. Otherwise, TRUE.
  */
-function session_save_session($status = NULL) {
-  static $save_session = TRUE;
+function drupal_save_session($status = NULL) {
+  $save_session = &drupal_static(__FUNCTION__, TRUE);
   if (isset($status)) {
     $save_session = $status;
   }
@@ -213,7 +324,7 @@ function session_save_session($status = 
  * @return $user
  *   The user object.
  */
-function sess_user_load($session) {
+function _memcache_session_user_load($session) {
   // We found the client's session record and they are an authenticated user.
   if ($session && $session->uid != 0) {
     $user = dmemcache_get($session->uid, 'users');
Index: memcache.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/memcache/memcache.info,v
retrieving revision 1.2.2.1
diff -u -p -r1.2.2.1 memcache.info
--- memcache.info	5 Dec 2009 00:26:30 -0000	1.2.2.1
+++ memcache.info	11 Dec 2009 00:34:13 -0000
@@ -2,3 +2,7 @@
 name = Memcache
 description = High performance integration with memcache.
 package = Caching
+core = 7.x
+files[] = memcache.inc
+files[] = memcache.module
+files[] = memcache.test
