summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2010-10-29 18:02:19 +0000
committeralecpl <alec@alec.pl>2010-10-29 18:02:19 +0000
commit9ae29c9525dbd878cff63d691625bb0c6f6cbf5c (patch)
treee4ad1075261213bfd929d84e3470051f0d9b79ea
parent93272ea91b3263acd883cac77986125e9a2ad8c6 (diff)
- Improve performance of message cache status checking when skip_disabled=true
-rw-r--r--CHANGELOG1
-rw-r--r--program/include/rcube_imap.php67
-rw-r--r--program/include/rcube_imap_generic.php32
3 files changed, 62 insertions, 38 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 94d6d0400..dbd9b5af1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -57,6 +57,7 @@ CHANGELOG Roundcube Webmail
- Plugin API: add possibility to disable plugin in AJAX mode, 'noajax' property
- Plugin API: add possibility to disable plugin in framed mode, 'noframe' property
- Improve performance of setting IMAP flags using .SILENT suffix
+- Improve performance of message cache status checking with skip_disabled=true
RELEASE 0.4.2
-------------
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 028d998c3..473e914b9 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -546,9 +546,14 @@ class rcube_imap
if ($mode == 'UNSEEN') {
$search_str .= " UNSEEN";
}
- else if ($status) {
- $keys[] = 'MAX';
- $need_uid = true;
+ else {
+ if ($this->caching_enabled) {
+ $keys[] = 'ALL';
+ }
+ if ($status) {
+ $keys[] = 'MAX';
+ $need_uid = true;
+ }
}
// get message count using (E)SEARCH
@@ -557,9 +562,15 @@ class rcube_imap
$count = is_array($index) ? $index['COUNT'] : 0;
- if ($mode == 'ALL' && $status) {
- $this->set_folder_stats($mailbox, 'cnt', $count);
- $this->set_folder_stats($mailbox, 'maxuid', is_array($index) ? $index['MAX'] : 0);
+ if ($mode == 'ALL') {
+ if ($need_uid && $this->caching_enabled) {
+ // Save messages index for check_cache_status()
+ $this->icache['all_undeleted_idx'] = $index['ALL'];
+ }
+ if ($status) {
+ $this->set_folder_stats($mailbox, 'cnt', $count);
+ $this->set_folder_stats($mailbox, 'maxuid', is_array($index) ? $index['MAX'] : 0);
+ }
}
}
else {
@@ -3646,45 +3657,43 @@ class rcube_imap
$cache_count = count($cache_index);
// empty mailbox
- if (!$msg_count)
+ if (!$msg_count) {
return $cache_count ? -2 : 1;
+ }
if ($cache_count == $msg_count) {
if ($this->skip_deleted) {
- $h_index = $this->conn->fetchHeaderIndex($mailbox, "1:*", 'UID', $this->skip_deleted);
-
- // Save index in internal cache, will be used when syncing the cache
- $this->icache['folder_index'] = $h_index;
-
- if (empty($h_index))
- return -2;
-
- if (sizeof($h_index) == $cache_count) {
- $cache_index = array_flip($cache_index);
- foreach ($h_index as $idx => $uid)
- unset($cache_index[$uid]);
-
- if (empty($cache_index))
- return 1;
- }
- return -2;
+ if (!empty($this->icache['all_undeleted_idx'])) {
+ $uids = rcube_imap_generic::uncompressMessageSet($this->icache['all_undeleted_idx']);
+ $uids = array_flip($uids);
+ foreach ($cache_index as $uid) {
+ unset($uids[$uid]);
+ }
+ }
+ else {
+ // get all undeleted messages excluding cached UIDs
+ $uids = $this->search_once($mailbox, 'ALL UNDELETED NOT UID '.
+ rcube_imap_generic::compressMessageSet($cache_index));
+ }
+ if (empty($uids)) {
+ return 1;
+ }
} else {
// get UID of the message with highest index
$uid = $this->_id2uid($msg_count, $mailbox);
$cache_uid = array_pop($cache_index);
// uids of highest message matches -> cache seems OK
- if ($cache_uid == $uid)
+ if ($cache_uid == $uid) {
return 1;
+ }
}
// cache is dirty
return -1;
}
+
// if cache count differs less than 10% report as dirty
- else if (abs($msg_count - $cache_count) < $msg_count/10)
- return -1;
- else
- return -2;
+ return (abs($msg_count - $cache_count) < $msg_count/10) ? -1 : -2;
}
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 5d16dc0c1..a7bfe05ad 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -1008,8 +1008,8 @@ class rcube_imap_generic
}
// message IDs
- if (is_array($add))
- $add = $this->compressMessageSet(join(',', $add));
+ if (!empty($add))
+ $add = $this->compressMessageSet($add);
list($code, $response) = $this->execute($is_uid ? 'UID SORT' : 'SORT',
array("($field)", $encoding, 'ALL' . (!empty($add) ? ' '.$add : '')));
@@ -1026,7 +1026,7 @@ class rcube_imap_generic
function fetchHeaderIndex($mailbox, $message_set, $index_field='', $skip_deleted=true, $uidfetch=false)
{
if (is_array($message_set)) {
- if (!($message_set = $this->compressMessageSet(join(',', $message_set))))
+ if (!($message_set = $this->compressMessageSet($message_set)))
return false;
} else {
list($from_idx, $to_idx) = explode(':', $message_set);
@@ -1150,12 +1150,12 @@ class rcube_imap_generic
return $result;
}
- private function compressMessageSet($messages, $force=false)
+ static function compressMessageSet($messages, $force=false)
{
// given a comma delimited list of independent mid's,
// compresses by grouping sequences together
- if (!is_array($message_set)) {
+ if (!is_array($messages)) {
// if less than 255 bytes long, let's not bother
if (!$force && strlen($messages)<255) {
return $messages;
@@ -1199,6 +1199,23 @@ class rcube_imap_generic
return implode(',', $result);
}
+ static function uncompressMessageSet($messages)
+ {
+ $result = array();
+ $messages = explode(',', $messages);
+
+ foreach ($messages as $part) {
+ $items = explode(':', $part);
+ $max = max($items[0], $items[1]);
+
+ for ($x=$items[0]; $x<=$max; $x++) {
+ $result[] = $x;
+ }
+ }
+
+ return $result;
+ }
+
/**
* Returns message sequence identifier
*
@@ -1265,9 +1282,6 @@ class rcube_imap_generic
return false;
}
- if (is_array($message_set))
- $message_set = join(',', $message_set);
-
$message_set = $this->compressMessageSet($message_set);
if ($add)
@@ -1824,7 +1838,7 @@ class rcube_imap_generic
if (in_array('MAX', $items))
$result['MAX'] = !empty($response) ? max($response) : 0;
if (in_array('ALL', $items))
- $result['ALL'] = $this->compressMessageSet(implode(',', $response), true);
+ $result['ALL'] = $this->compressMessageSet($response, true);
return $result;
}