summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2010-10-09 16:46:53 +0000
committeralecpl <alec@alec.pl>2010-10-09 16:46:53 +0000
commit29983c16711b7eb6828afab8ca87a09eec9f6fe3 (patch)
tree0dc46b945bc30874df11005cba29ef6e7977b650
parentca1f564598614f62fa8b210c414a919491176865 (diff)
- Add caching support in id2uid and uid2id functions (#1487019), Fix get_message_cache_index
to use internal cache when only sort order changes. Both changes improves performance of 'show' action - code cleanup/function description fixes
-rw-r--r--CHANGELOG1
-rw-r--r--program/include/rcube_imap.php226
2 files changed, 159 insertions, 68 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 03eb27ef4..135d352f8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -25,6 +25,7 @@ CHANGELOG Roundcube Webmail
- Use css sprite image for messages list
- Add (different) attachment icon for messages of type multipart/report (#1486165)
- Prevent from inserting empty link when composing HTML message (#1486944)
+- Add caching support in id2uid and uid2id functions (#1487019)
RELEASE 0.4.2
-------------
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 4e8998fdf..0a27989b9 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -114,7 +114,7 @@ class rcube_imap
$this->conn = new rcube_imap_generic();
}
-
+
/**
* Connect to an IMAP server
*
@@ -183,7 +183,7 @@ class rcube_imap
return false;
}
-
+
/**
* Close IMAP connection
* Usually done on script shutdown
@@ -196,7 +196,7 @@ class rcube_imap
$this->write_cache();
}
-
+
/**
* Close IMAP connection and re-connect
* This is used to avoid some strange socket errors when talking to Courier IMAP
@@ -213,6 +213,7 @@ class rcube_imap
$this->conn->select($this->mailbox);
}
+
/**
* Set options to be used in rcube_imap_generic::connect()
*
@@ -223,6 +224,7 @@ class rcube_imap
$this->options = array_merge($this->options, (array)$opt);
}
+
/**
* Set a root folder for the IMAP connection.
*
@@ -244,7 +246,7 @@ class rcube_imap
$this->get_hierarchy_delimiter();
}
-
+
/**
* Set default message charset
*
@@ -258,7 +260,7 @@ class rcube_imap
$this->default_charset = $cs;
}
-
+
/**
* This list of folders will be listed above all other folders
*
@@ -276,7 +278,7 @@ class rcube_imap
}
}
-
+
/**
* Set internal mailbox reference.
*
@@ -298,7 +300,7 @@ class rcube_imap
$this->_clear_messagecount($mailbox);
}
-
+
/**
* Set internal list page
*
@@ -310,7 +312,7 @@ class rcube_imap
$this->list_page = (int)$page;
}
-
+
/**
* Set internal page size
*
@@ -322,7 +324,7 @@ class rcube_imap
$this->page_size = (int)$size;
}
-
+
/**
* Save a set of message ids for future message listing methods
*
@@ -349,7 +351,7 @@ class rcube_imap
$this->search_sorted = $sorted;
}
-
+
/**
* Return the saved search set as hash array
* @return array Search set
@@ -365,7 +367,7 @@ class rcube_imap
);
}
-
+
/**
* Returns the currently used mailbox name
*
@@ -377,7 +379,7 @@ class rcube_imap
return $this->conn->connected() ? $this->mod_mailbox($this->mailbox, 'out') : '';
}
-
+
/**
* Returns the IMAP server's capability
*
@@ -390,7 +392,7 @@ class rcube_imap
return $this->conn->getCapability(strtoupper($cap));
}
-
+
/**
* Sets threading flag to the best supported THREAD algorithm
*
@@ -414,13 +416,13 @@ class rcube_imap
return $this->threading;
}
-
+
/**
* Checks the PERMANENTFLAGS capability of the current mailbox
* and returns true if the given flag is supported by the IMAP server
*
* @param string $flag Permanentflag name
- * @return mixed True if this flag is supported
+ * @return boolean True if this flag is supported
* @access public
*/
function check_permflag($flag)
@@ -430,7 +432,7 @@ class rcube_imap
return (in_array_nocase($imap_flag, $this->conn->permanentflags));
}
-
+
/**
* Returns the delimiter that is used by the IMAP server for folder separation
*
@@ -448,7 +450,7 @@ class rcube_imap
return $this->delimiter;
}
-
+
/**
* Get message count for a specific mailbox
*
@@ -466,7 +468,7 @@ class rcube_imap
return $this->_messagecount($mailbox, $mode, $force, $status);
}
-
+
/**
* Private method for getting nr of messages
*
@@ -556,8 +558,8 @@ class rcube_imap
/**
* Private method for getting nr of threads
*
- * @param string $mailbox
- * @param int $msg_count
+ * @param string $mailbox Folder name
+ * @param int $msg_count Number of messages in the folder
* @access private
* @see rcube_imap::messagecount()
*/
@@ -574,7 +576,7 @@ class rcube_imap
return count($thread_tree);
}
-
+
/**
* Public method for listing headers
* convert mailbox name with root dir first
@@ -593,7 +595,7 @@ class rcube_imap
return $this->_list_headers($mailbox, $page, $sort_field, $sort_order, false, $slice);
}
-
+
/**
* Private method for listing message headers
*
@@ -723,7 +725,7 @@ class rcube_imap
return array_values($a_msg_headers);
}
-
+
/**
* Private method for listing message headers using threads
*
@@ -731,7 +733,7 @@ class rcube_imap
* @param int $page Current page to list
* @param string $sort_field Header field to sort by
* @param string $sort_order Sort order [ASC|DESC]
- * @param boolean $recursive
+ * @param boolean $recursive True if called recursively
* @param int $slice Number of slice items to extract from result array
* @return array Indexed array with message header objects
* @access private
@@ -790,13 +792,14 @@ class rcube_imap
/**
* Private method for fetching threaded messages headers
*
- * @param string $mailbox Mailbox name
- * @param string $thread_tree
- * @param int $msg_depth
- * @param boolean $has_children
- * @param int $msg_index
- * @param int $page
- * @param int $slice
+ * @param string $mailbox Mailbox name
+ * @param array $thread_tree Thread tree data
+ * @param array $msg_depth Thread depth data
+ * @param array $has_children Thread children data
+ * @param array $msg_index Messages index
+ * @param int $page List page number
+ * @param int $slice Number of threads to slice
+ * @return array Messages headers
* @access private
*/
private function _fetch_thread_headers($mailbox, $thread_tree, $msg_depth, $has_children, $msg_index, $page, $slice=0)
@@ -1050,9 +1053,9 @@ class rcube_imap
/**
* Helper function to get first and last index of the requested set
*
- * @param int $max message count
- * @param mixed $page page number to show, or string 'all'
- * @return array array with two values: first index, last index
+ * @param int $max Messages count
+ * @param mixed $page Page number to show, or string 'all'
+ * @return array Array with two values: first index, last index
* @access private
*/
private function _get_message_range($max, $page)
@@ -1081,13 +1084,12 @@ class rcube_imap
/**
- * Fetches message headers
- * Used for loop
+ * Fetches message headers (used for loop)
*
- * @param string Mailbox name
- * @param string Message index to fetch
- * @param array Reference to message headers array
- * @param string Cache index string
+ * @param string $mailbox Mailbox name
+ * @param string $msgs Message index to fetch
+ * @param array $a_msg_headers Reference to message headers array
+ * @param string $cache_key Cache index key
* @return int Messages count
* @access private
*/
@@ -1212,7 +1214,7 @@ class rcube_imap
* @param string $mbox_name Mailbox to get index from
* @param string $sort_field Sort column
* @param string $sort_order Sort order [ASC, DESC]
- * @return array Indexed array with message ids
+ * @return array Indexed array with message IDs
*/
function message_index($mbox_name='', $sort_field=NULL, $sort_order=NULL)
{
@@ -1496,11 +1498,11 @@ class rcube_imap
/**
* Invoke search request to IMAP server
*
- * @param string $mbox_name mailbox name to search in
- * @param string $str search string
- * @param string $charset search string charset
- * @param string $sort_field header field to sort by
- * @return array search results as list of message ids
+ * @param string $mbox_name Mailbox name to search in
+ * @param string $str Search criteria
+ * @param string $charset Search charset
+ * @param string $sort_field Header field to sort by
+ * @return array search results as list of message IDs
* @access public
*/
function search($mbox_name='', $str=NULL, $charset=NULL, $sort_field=NULL)
@@ -2077,9 +2079,9 @@ class rcube_imap
/**
* Set attachment filename from message part structure
*
- * @access private
* @param rcube_message_part $part Part object
* @param string $headers Part's raw headers
+ * @access private
*/
private function _set_part_filename(&$part, $headers=null)
{
@@ -2198,11 +2200,11 @@ class rcube_imap
/**
* Get charset name from message structure (first part)
*
- * @access private
* @param array $structure Message structure
* @return string Charset name
+ * @access private
*/
- function _structure_charset($structure)
+ private function _structure_charset($structure)
{
while (is_array($structure)) {
if (is_array($structure[2]) && $structure[2][0] == 'charset')
@@ -3121,6 +3123,7 @@ class rcube_imap
$this->caching_enabled = false;
}
+
/**
* Returns cached value
*
@@ -3138,6 +3141,7 @@ class rcube_imap
return $this->cache[$key];
}
+
/**
* Update cache
*
@@ -3152,6 +3156,7 @@ class rcube_imap
$this->cache_changes[$key] = true;
}
+
/**
* Writes the cache
*
@@ -3167,6 +3172,7 @@ class rcube_imap
}
}
+
/**
* Clears the cache.
*
@@ -3193,6 +3199,7 @@ class rcube_imap
}
}
+
/**
* Returns cached entry
*
@@ -3222,6 +3229,7 @@ class rcube_imap
return $this->cache[$key];
}
+
/**
* Writes single cache record
*
@@ -3269,6 +3277,7 @@ class rcube_imap
}
}
+
/**
* Clears cache for single record
*
@@ -3351,6 +3360,7 @@ class rcube_imap
return -2;
}
+
/**
* @param string $key Cache key
* @param string $from
@@ -3395,9 +3405,10 @@ class rcube_imap
return $result;
}
+
/**
* @param string $key Cache key
- * @param int $uid User id
+ * @param int $uid Message UID
* @return mixed
* @access private
*/
@@ -3429,11 +3440,12 @@ class rcube_imap
return $this->icache[$internal_key][$uid];
}
+
/**
- * @param string $key Cache key
- * @param boolean $force Force flag
- * @param string $sort_field
- * @param string $sort_order
+ * @param string $key Cache key
+ * @param string $sort_field Sorting column
+ * @param string $sort_order Sorting order
+ * @return array Messages index
* @access private
*/
private function get_message_cache_index($key, $sort_field='idx', $sort_order='ASC')
@@ -3445,19 +3457,21 @@ class rcube_imap
if (!$sort_field || !in_array($sort_field, $this->db_header_fields))
$sort_field = 'idx';
- $ord = $sort_field . $sort_order;
-
if (array_key_exists('index', $this->icache)
&& $this->icache['index']['key'] == $key
- && $this->icache['index']['ord'] == $ord
+ && $this->icache['index']['sort_field'] == $sort_field
) {
- return $this->icache['index']['result'];
+ if ($this->icache['index']['sort_order'] == $sort_order)
+ return $this->icache['index']['result'];
+ else
+ return array_reverse($this->icache['index']['result'], true);
}
$this->icache['index'] = array(
- 'result' => array(),
- 'ord' => $ord,
- 'key' => $key,
+ 'result' => array(),
+ 'key' => $key,
+ 'sort_field' => $sort_field,
+ 'sort_order' => $sort_order,
);
$sql_result = $this->db->query(
@@ -3475,6 +3489,7 @@ class rcube_imap
return $this->icache['index']['result'];
}
+
/**
* @access private
*/
@@ -3551,6 +3566,7 @@ class rcube_imap
unset($this->icache['index']);
}
+
/**
* @access private
*/
@@ -3570,6 +3586,7 @@ class rcube_imap
unset($this->icache['index']);
}
+
/**
* @param string $key Cache key
* @param int $start_index Start index
@@ -3590,6 +3607,7 @@ class rcube_imap
unset($this->icache['index']);
}
+
/**
* @access private
*/
@@ -3621,6 +3639,70 @@ class rcube_imap
}
+ /**
+ * @param string $key Cache key
+ * @param int $id Message (sequence) ID
+ * @return int Message UID
+ * @access private
+ */
+ private function get_cache_id2uid($key, $id)
+ {
+ if (!$this->caching_enabled)
+ return null;
+
+ if (array_key_exists('index', $this->icache)
+ && $this->icache['index']['key'] == $key
+ ) {
+ return $this->icache['index']['result'][$id];
+ }
+
+ $sql_result = $this->db->query(
+ "SELECT uid".
+ " FROM ".get_table_name('messages').
+ " WHERE user_id=?".
+ " AND cache_key=?".
+ " AND idx=?",
+ $_SESSION['user_id'], $key, $id);
+
+ if ($sql_arr = $this->db->fetch_assoc($sql_result))
+ return intval($sql_arr['uid']);
+
+ return null;
+ }
+
+
+ /**
+ * @param string $key Cache key
+ * @param int $uid Message UID
+ * @return int Message (sequence) ID
+ * @access private
+ */
+ private function get_cache_uid2id($key, $uid)
+ {
+ if (!$this->caching_enabled)
+ return null;
+
+ if (array_key_exists('index', $this->icache)
+ && $this->icache['index']['key'] == $key
+ ) {
+ return array_search($uid, $this->icache['index']['result']);
+ }
+
+ $sql_result = $this->db->query(
+ "SELECT idx".
+ " FROM ".get_table_name('messages').
+ " WHERE user_id=?".
+ " AND cache_key=?".
+ " AND uid=?",
+ $_SESSION['user_id'], $key, $uid);
+
+ if ($sql_arr = $this->db->fetch_assoc($sql_result))
+ return intval($sql_arr['idx']);
+
+ return null;
+ }
+
+
/* --------------------------------
* encoding/decoding methods
* --------------------------------*/
@@ -3842,6 +3924,7 @@ class rcube_imap
$this->sort_order = strtoupper($sort_order) == 'DESC' ? 'DESC' : 'ASC';
}
+
/**
* Sort mailboxes first by default folders and then in alphabethical order
*
@@ -3903,9 +3986,9 @@ class rcube_imap
/**
- * @param int $uid User id
+ * @param int $uid Message UID
* @param string $mbox_name Mailbox name
- * @return int
+ * @return int Message (sequence) ID
* @access private
*/
private function _uid2id($uid, $mbox_name=NULL)
@@ -3913,16 +3996,21 @@ class rcube_imap
if (!$mbox_name)
$mbox_name = $this->mailbox;
- if (!isset($this->uid_id_map[$mbox_name][$uid]))
- $this->uid_id_map[$mbox_name][$uid] = $this->conn->UID2ID($mbox_name, $uid);
+ if (!isset($this->uid_id_map[$mbox_name][$uid])) {
+ if (!($id = $this->get_cache_uid2id($mbox_name.'.msg', $uid)))
+ $id = $this->conn->UID2ID($mbox_name, $uid);
+
+ $this->uid_id_map[$mbox_name][$uid] = $id;
+ }
return $this->uid_id_map[$mbox_name][$uid];
}
+
/**
- * @param int $id Id
+ * @param int $id Message (sequence) ID
* @param string $mbox_name Mailbox name
- * @return int
+ * @return int Message UID
* @access private
*/
private function _id2uid($id, $mbox_name=NULL)
@@ -3933,7 +4021,9 @@ class rcube_imap
if ($uid = array_search($id, (array)$this->uid_id_map[$mbox_name]))
return $uid;
- $uid = $this->conn->ID2UID($mbox_name, $id);
+ if (!($uid = $this->get_cache_id2uid($mbox_name.'.msg', $id)))
+ $uid = $this->conn->ID2UID($mbox_name, $id);
+
$this->uid_id_map[$mbox_name][$uid] = $id;
return $uid;