alecpl
2008-11-21 3e48d2eee1d2af42aa777fd5e461fa570762732e
- Increase speed of session destroy and garbage clean up
- Fix session timeout when DB server got clock skew (#1485490)


11 files modified
96 ■■■■■ changed files
CHANGELOG 2 ●●●●● patch | view | raw | blame | history
SQL/mssql.initial.sql 3 ●●●●● patch | view | raw | blame | history
SQL/mysql.initial.sql 3 ●●●● patch | view | raw | blame | history
SQL/mysql.update.sql 3 ●●●●● patch | view | raw | blame | history
SQL/mysql5.initial.sql 3 ●●●● patch | view | raw | blame | history
SQL/postgres.initial.sql 1 ●●●● patch | view | raw | blame | history
SQL/postgres.update.sql 6 ●●●●● patch | view | raw | blame | history
SQL/sqlite.initial.sql 1 ●●●● patch | view | raw | blame | history
SQL/sqlite.update.sql 4 ●●●● patch | view | raw | blame | history
program/include/rcube_imap.php 6 ●●●● patch | view | raw | blame | history
program/include/session.inc 64 ●●●● patch | view | raw | blame | history
CHANGELOG
@@ -4,6 +4,8 @@
2008/11/21 (alec)
----------
- Fix 'cache' table cleanup on session destroy (#1485516)
- Increase speed of session destroy and garbage clean up
- Fix session timeout when DB server got clock skew (#1485490)
2008/11/19 (alec)
----------
SQL/mssql.initial.sql
@@ -196,6 +196,9 @@
    CONSTRAINT [DF_session_ip] DEFAULT ('') FOR [ip]
GO
 CREATE  INDEX [IX_session_changed] ON [dbo].[session]([changed]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] ADD 
    CONSTRAINT [DF_users_username] DEFAULT ('') FOR [username],
    CONSTRAINT [DF_users_mail_host] DEFAULT ('') FOR [mail_host],
SQL/mysql.initial.sql
@@ -73,7 +73,8 @@
  `changed` datetime NOT NULL default '0000-00-00 00:00:00',
  `ip` VARCHAR(40) NOT NULL default '',
  `vars` text NOT NULL,
  PRIMARY KEY  (`sess_id`)
  PRIMARY KEY  (`sess_id`),
  INDEX `changed_index` (`changed`)
);
-- --------------------------------------------------------
SQL/mysql.update.sql
@@ -38,3 +38,6 @@
    REFERENCES `session`(`sess_id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE;
ALTER TABLE `session`
    ADD INDEX `changed_index` (`changed`);
SQL/mysql5.initial.sql
@@ -14,7 +14,8 @@
 `changed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
 `ip` varchar(40) NOT NULL,
 `vars` text NOT NULL,
 PRIMARY KEY(`sess_id`)
 PRIMARY KEY(`sess_id`),
 INDEX `changed_index` (`changed`)
) TYPE=INNODB CHARACTER SET utf8 COLLATE utf8_general_ci;
SQL/postgres.initial.sql
@@ -42,6 +42,7 @@
    vars text NOT NULL
);
CREATE INDEX session_changed_idx ON session (changed);
--
SQL/postgres.update.sql
@@ -25,5 +25,7 @@
-- Updates from version 0.2-beta
ALTER TABLE cache DROP CONSTRAINT cache_session_id_fkey;
ALTER TABLE cache ADD FOREIGN KEY (session_id) REFERENCES session(sess_id) ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX cache_session_id_idx ON "cache" (session_id);
ALTER TABLE cache ADD FOREIGN KEY (session_id) REFERENCES session (sess_id) ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX cache_session_id_idx ON cache (session_id);
CREATE INDEX session_changed_idx ON session (changed);
SQL/sqlite.initial.sql
@@ -97,6 +97,7 @@
  vars text NOT NULL
);
CREATE INDEX ix_session_changed ON session (changed);
-- --------------------------------------------------------
SQL/sqlite.update.sql
@@ -29,3 +29,7 @@
-- Updates from version 0.2-alpha
CREATE INDEX ix_messages_created ON messages (created);
-- Updates from version 0.2-beta
CREATE INDEX ix_session_changed ON session (changed);
program/include/rcube_imap.php
@@ -2146,7 +2146,7 @@
      {
      $this->db->query(
        "UPDATE ".get_table_name('cache')."
         SET    created=".$this->db->now().", data=?, session_id=?
         SET    created=". $this->db->fromunixtime(time()).", data=?, session_id=?
         WHERE  user_id=?
         AND    cache_key=?",
        $data,
@@ -2160,7 +2160,7 @@
      $this->db->query(
        "INSERT INTO ".get_table_name('cache')."
         (created, user_id, cache_key, data, session_id)
         VALUES (".$this->db->now().", ?, ?, ?, ?)",
         VALUES (".$this->db->fromunixtime(time()).", ?, ?, ?, ?)",
        $_SESSION['user_id'],
        $key,
        $data,
@@ -2374,7 +2374,7 @@
      $this->db->query(
        "INSERT INTO ".get_table_name('messages')."
         (user_id, del, cache_key, created, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers, structure)
         VALUES (?, 0, ?, ".$this->db->now().", ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?, ?)",
         VALUES (?, 0, ?, ".$this->db->fromunixtime(time()).", ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?, ?)",
        $_SESSION['user_id'],
        $key,
        $index,
program/include/session.inc
@@ -75,10 +75,12 @@
     WHERE  sess_id=?",
    $key);
  $now = $DB->fromunixtime(time());
  if ($DB->num_rows($sql_result)) {
    $DB->query(
      "UPDATE " . get_table_name('session') . "
       SET    vars=?, changed=" . $DB->now() . "
       SET    vars=?, changed= " . $now . "
       WHERE  sess_id=?",
      $vars,
      $key);
@@ -87,7 +89,7 @@
    $DB->query(
      "INSERT INTO " . get_table_name('session') . "
       (sess_id, vars, ip, created, changed)
       VALUES (?, ?, ?, ".$DB->now().", ".$DB->now().")",
       VALUES (?, ?, ?, " . $now . ", " . $now .")",
      $key,
      $vars,
      (string)$_SERVER['REMOTE_ADDR']);
@@ -107,12 +109,13 @@
    return false;
  }
  $DB->query("DELETE FROM " . get_table_name('session') . " WHERE sess_id=?", $key);
  // delete session entries in cache table
  if ($rcmail->config->get('enable_caching')) {
  // on databases wthout foreign keys
  if ($rcmail->config->get('enable_caching') && $DB->db_provider != 'pgsql') {
    $DB->query("DELETE FROM " . get_table_name('cache') . " WHERE session_id=?", $key);
  }
  $DB->query("DELETE FROM " . get_table_name('session') . " WHERE sess_id=?", $key);
  return true;
}
@@ -128,40 +131,39 @@
    return false;
  }
  $now = $DB->fromunixtime(time() - $maxlifetime);
  // delete session entries in cache table
  if ($rcmail->config->get('enable_caching')) {
    // get all expired sessions
    $sql_result = $DB->query(
    "SELECT sess_id
        FROM " . get_table_name('session') . "
        WHERE " . $DB->unixtimestamp($DB->now())."-".$DB->unixtimestamp('changed') . " > ?",
    $maxlifetime);
    $exp_sessions = array();
    while ($sql_arr = $DB->fetch_assoc($sql_result)) {
      $exp_sessions[] = $sql_arr['sess_id'];
    }
    if (sizeof($exp_sessions)) {
      $exp_sessions = "'" . join("','", $exp_sessions) . "'";
      // delete session cache records
      $DB->query("DELETE FROM " . get_table_name('cache') . "
    // on databases wthout foreign keys...
    if($DB->db_provider != 'pgsql') {
      // get all expired sessions
      $sql_result = $DB->query(
    "SELECT sess_id FROM " . get_table_name('session') . "
            WHERE changed < " . $now);
      $exp_sessions = array();
      while ($sql_arr = $DB->fetch_assoc($sql_result)) {
        $exp_sessions[] = $sql_arr['sess_id'];
      }
      if (sizeof($exp_sessions)) {
        $exp_sessions = "'" . join("','", $exp_sessions) . "'";
        // delete session cache records
        $DB->query("DELETE FROM " . get_table_name('cache') . "
            WHERE session_id IN (" . $exp_sessions . ")");
      // delete session records
      $DB->query("DELETE FROM " . get_table_name('session') . "
            WHERE sess_id IN (" . $exp_sessions . ")");
      }
    }
    // also run message cache GC
    rcmail_message_cache_gc();
  } else {
    // just delete all expired sessions
    $DB->query("DELETE FROM " . get_table_name('session') . "
        WHERE " . $DB->unixtimestamp($DB->now())."-".$DB->unixtimestamp('changed') . " > ?",
    $maxlifetime);
  }
  // just delete all expired sessions
  $DB->query("DELETE FROM " . get_table_name('session') . "
    WHERE changed < " . $now);
  rcmail_temp_gc();
  return true;