summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2014-08-19 12:20:47 (GMT)
committerAleksander Machniak <machniak@kolabsys.com>2014-08-19 12:20:47 (GMT)
commit07308521792a182e9cd4de10d067b96c190d21a5 (patch)
treed6d96356c7eb52fe0af9f538e3bb3c4732be44e9
parente3d29617ae5a0f72efca8f08b5c3f57af6cb4c26 (diff)
downloadroundcubemail-plugins-kolab-07308521792a182e9cd4de10d067b96c190d21a5.tar.gz
Cache relation members for better performance (#3452)
-rw-r--r--plugins/kolab_notes/kolab_notes.php89
-rw-r--r--plugins/libkolab/lib/kolab_format_configuration.php25
-rw-r--r--plugins/libkolab/lib/kolab_storage_cache_configuration.php6
-rw-r--r--plugins/libkolab/lib/kolab_storage_config.php79
4 files changed, 123 insertions, 76 deletions
diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php
index 7553fd1..a5723a1 100644
--- a/plugins/kolab_notes/kolab_notes.php
+++ b/plugins/kolab_notes/kolab_notes.php
@@ -391,7 +391,7 @@ class kolab_notes extends rcube_plugin
$this->rc->output->set_env('kolab_notes_template', array(
'_from_mail' => true,
'title' => $message->get('subject'),
- 'links' => array($this->get_message_reference($this->get_message_uri($message, $folder))),
+ 'links' => array($this->get_message_reference(kolab_storage_config::get_message_uri($message, $folder))),
));
}
}
@@ -996,7 +996,6 @@ class kolab_notes extends rcube_plugin
foreach ($relations as $relation) {
if (empty($links)) {
$config->delete($relation['uid']);
- $this->relations = null; // clear in-memory cache
}
else {
// make relation members up-to-date
@@ -1010,7 +1009,6 @@ class kolab_notes extends rcube_plugin
if (count($diff1) || count($diff2)) {
$relation['members'] = $members;
$config->save($relation, 'relation');
- $this->relations = null; // clear in-memory cache
}
$links = null;
@@ -1025,7 +1023,6 @@ class kolab_notes extends rcube_plugin
);
$config->save($relation, 'relation');
- $this->relations = null; // clear in-memory cache
}
}
@@ -1070,33 +1067,11 @@ class kolab_notes extends rcube_plugin
*/
private function get_message_notes($message, $folder)
{
- $result = array();
- $uids = array();
-
- // TODO: only query for notes if message was flagged with $KolabNotes ?
-
- // get UIDs of assigned notes
- foreach ($this->get_relations() as $relation) {
- // get Folder/UIDs of relation members
- $messages = kolab_storage_config::resolve_members($relation);
-
- if (!empty($messages[$folder]) && in_array($message->uid, $messages[$folder])) {
- // find note UID(s)
- foreach ($relation['members'] as $member) {
- if (strpos($member, 'urn:uuid:') === 0) {
- $uids[] = substr($member, 9);
- }
- }
- }
- }
+ $config = kolab_storage_config::get_instance();
+ $result = $config->get_message_relations($message, $folder, 'note');
- // get Note objects
- if (!empty($uids)) {
- $query = array(array('uid', '=', $uids));
- foreach (kolab_storage::select($query, 'note') as $record) {
- $record['list'] = kolab_storage::folder_id($record['_mailbox']);
- $result[] = $record;
- }
+ foreach ($result as $idx => $note) {
+ $result[$idx]['list'] = kolab_storage::folder_id($note['_mailbox']);
}
return $result;
@@ -1105,55 +1080,17 @@ class kolab_notes extends rcube_plugin
/**
* Find relation objects referring to specified note
*/
- private function get_relations($uid = null)
- {
- if (!isset($this->relations)) {
- $config = kolab_storage_config::get_instance();
- $default = true;
- $filter = array(
- array('type', '=', 'relation'),
- array('category', '=', 'generic')
- );
-
- $this->relations = $config->get_objects($filter, $default);
- }
-
- if ($uid === null) {
- return $this->relations;
- }
-
- $result = array();
- $search = kolab_storage_config::build_member_url($uid);
-
- foreach ($this->relations as $relation) {
- if (in_array($search, (array) $relation['members'])) {
- $result[] = $relation;
- }
- }
-
- return $result;
- }
-
- /**
- * Build a URI representing the given message reference
- */
- private function get_message_uri($headers, $folder)
+ private function get_relations($uid)
{
- $params = array(
- 'folder' => $headers->folder ?: $folder,
- 'uid' => $headers->uid,
+ $config = kolab_storage_config::get_instance();
+ $default = true;
+ $filter = array(
+ array('type', '=', 'relation'),
+ array('category', '=', 'generic'),
+ array('member', '=', $uid),
);
- if (($messageid = $headers->get('message-id', false)) && ($date = $headers->get('date', false))) {
- $params['message-id'] = $messageid;
- $params['date'] = $date;
-
- if ($subject = $headers->get('subject')) {
- $params['subject'] = $subject;
- }
- }
-
- return kolab_storage_config::build_member_url($params);
+ return $config->get_objects($filter, $default, 100);
}
/**
diff --git a/plugins/libkolab/lib/kolab_format_configuration.php b/plugins/libkolab/lib/kolab_format_configuration.php
index 6b71f3e..17b46a7 100644
--- a/plugins/libkolab/lib/kolab_format_configuration.php
+++ b/plugins/libkolab/lib/kolab_format_configuration.php
@@ -220,4 +220,29 @@ class kolab_format_configuration extends kolab_format
return $tags;
}
+
+ /**
+ * Callback for kolab_storage_cache to get words to index for fulltext search
+ *
+ * @return array List of words to save in cache
+ */
+ public function get_words()
+ {
+ $words = array();
+
+ foreach ((array)$this->data['members'] as $url) {
+ $member = kolab_storage_config::parse_member_url($url);
+
+ if (empty($member)) {
+ if (strpos($url, 'urn:uuid:') === 0) {
+ $words[] = substr($url, 9);
+ }
+ }
+ else if (!empty($member['params']['message-id'])) {
+ $words[] = $member['params']['message-id'];
+ }
+ }
+
+ return $words;
+ }
}
diff --git a/plugins/libkolab/lib/kolab_storage_cache_configuration.php b/plugins/libkolab/lib/kolab_storage_cache_configuration.php
index 97315da..ec015dd 100644
--- a/plugins/libkolab/lib/kolab_storage_cache_configuration.php
+++ b/plugins/libkolab/lib/kolab_storage_cache_configuration.php
@@ -52,6 +52,12 @@ class kolab_storage_cache_configuration extends kolab_storage_cache
$query[$idx][0] = 'tags';
$query[$idx][2] = count($param[2]) > 1 ? $param[2] : $param[2][0];
}
+ // convert member filter (we support only = operator with single value)
+ else if ($param[0] == 'member') {
+ $query[$idx][0] = 'words';
+ $query[$idx][1] = '~';
+ $query[$idx][2] = '^' . $param[2] . '$';
+ }
}
}
diff --git a/plugins/libkolab/lib/kolab_storage_config.php b/plugins/libkolab/lib/kolab_storage_config.php
index beaa928..9bc5d50 100644
--- a/plugins/libkolab/lib/kolab_storage_config.php
+++ b/plugins/libkolab/lib/kolab_storage_config.php
@@ -623,6 +623,12 @@ class kolab_storage_config
array('category', '=', 'tag')
);
+ // use faster method
+ if ($uid && $uid != '*') {
+ $filter[] = array('member', '=', $uid);
+ return $this->get_objects($filter, $default);
+ }
+
$this->tags = $this->get_objects($filter, $default);
}
@@ -641,4 +647,77 @@ class kolab_storage_config
return $result;
}
+
+ /**
+ * Find kolab objects assigned to specified e-mail message
+ *
+ * @param rcube_message $message E-mail message
+ * @param string $folder Folder name
+ * @param string $type Result objects type
+ *
+ * @return array List of kolab objects
+ */
+ public function get_message_relations($message, $folder, $type)
+ {
+ $result = array();
+ $uids = array();
+ $default = true;
+ $uri = self::get_message_uri($message, $folder);
+ $filter = array(
+ array('type', '=', 'relation'),
+ array('category', '=', 'generic'),
+ // @TODO: what if Message-Id (and Date) does not exist?
+ array('member', '=', $message->get('message-id', false)),
+ );
+
+ // get UIDs of assigned notes
+ foreach ($this->get_objects($filter, $default) as $relation) {
+ // we don't need to update members if the URI is found
+ if (in_array($uri, $relation['members'])) {
+ // update members...
+ $messages = kolab_storage_config::resolve_members($relation);
+ // ...and check again
+ if (empty($messages[$folder]) || !in_array($message->uid, $messages[$folder])) {
+ continue;
+ }
+ }
+
+ // find note UID(s)
+ foreach ($relation['members'] as $member) {
+ if (strpos($member, 'urn:uuid:') === 0) {
+ $uids[] = substr($member, 9);
+ }
+ }
+ }
+
+ // get kolab objects of specified type
+ if (!empty($uids)) {
+ $query = array(array('uid', '=', array_unique($uids)));
+ $result = kolab_storage::select($query, $type);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Build a URI representing the given message reference
+ */
+ public static function get_message_uri($headers, $folder)
+ {
+ $params = array(
+ 'folder' => $headers->folder ?: $folder,
+ 'uid' => $headers->uid,
+ );
+
+ if (($messageid = $headers->get('message-id', false)) && ($date = $headers->get('date', false))) {
+ $params['message-id'] = $messageid;
+ $params['date'] = $date;
+
+ if ($subject = $headers->get('subject')) {
+ $params['subject'] = $subject;
+ }
+ }
+
+ return self::build_member_url($params);
+ }
}