Branch 'dev/kolab3' - 3 commits - plugins/calendar plugins/kolab_config plugins/libkolab
Thomas Brüderli
bruederli at kolabsys.com
Wed May 9 19:03:02 CEST 2012
plugins/calendar/drivers/kolab/kolab_calendar.php | 45 ++++++-------
plugins/kolab_config/kolab_config.php | 11 ---
plugins/libkolab/SQL/mysql.sql | 2
plugins/libkolab/lib/kolab_storage_cache.php | 72 +++++++++++++++++++++-
plugins/libkolab/lib/kolab_storage_folder.php | 35 ++++++++++
plugins/libkolab/libkolab.php | 2
6 files changed, 128 insertions(+), 39 deletions(-)
New commits:
commit b37784bb3ba3b3e89b54b542242d568c4d5af20a
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed May 9 19:02:46 2012 +0200
Query objects directly from the storage layer; no need to fetch all for every operation
diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php
index 7763159..53a8d83 100644
--- a/plugins/calendar/drivers/kolab/kolab_calendar.php
+++ b/plugins/calendar/drivers/kolab/kolab_calendar.php
@@ -38,8 +38,7 @@ class kolab_calendar
public $storage;
private $cal;
- private $events;
- private $id2uid;
+ private $events = array();
private $imap_folder = 'INBOX/Calendar';
private $search_fields = array('title', 'description', 'location', '_attendees');
private $sensitivity_map = array('public', 'private', 'confidential');
@@ -175,17 +174,21 @@ class kolab_calendar
*/
public function get_event($id)
{
- $this->_fetch_events();
-
+ // directly access storage object
+ if (!$this->events[$id] && ($record = $this->storage->get_object($id)))
+ $this->events[$id] = $this->_to_rcube_event($record);
+
// event not found, maybe a recurring instance is requested
if (!$this->events[$id]) {
$master_id = preg_replace('/-\d+$/', '', $id);
- if ($this->events[$master_id] && $this->events[$master_id]['recurrence']) {
- $master = $this->events[$master_id];
+ if ($record = $this->storage->get_object($master_id))
+ $this->events[$master_id] = $this->_to_rcube_event($record);
+
+ if (($master = $this->events[$master_id]) && $master['recurrence']) {
$this->_get_recurring_events($master, $master['start'], $master['start'] + 86400 * 365 * 10, $id);
}
}
-
+
return $this->events[$id];
}
@@ -199,8 +202,16 @@ class kolab_calendar
*/
public function list_events($start, $end, $search = null, $virtual = 1)
{
- $this->_fetch_events();
-
+ // query Kolab storage
+ $query = array(
+ array('dtstart', '<=', $end),
+ array('dtend', '>=', $start),
+ );
+ foreach ((array)$this->storage->select($query) as $record) {
+ $event = $this->_to_rcube_event($record);
+ $this->events[$event['id']] = $event;
+ }
+
if (!empty($search))
$search = mb_strtolower($search);
@@ -345,22 +356,6 @@ class kolab_calendar
return false;
}
- /**
- * Simply fetch all records and store them in private member vars
- * We thereby rely on cahcing done by the Horde classes
- */
- private function _fetch_events()
- {
- if (!isset($this->events)) {
- $this->events = array();
-
- foreach ((array)$this->storage->get_objects() as $record) {
- $event = $this->_to_rcube_event($record);
- $this->events[$event['id']] = $event;
- }
- }
- }
-
/**
* Create instances of a recurring event
commit 86c1d510f1c192880920085fd7b77d65f3f848ad
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed May 9 19:01:51 2012 +0200
Add select() method to query objects from cache; Use locks to avoid multiple threads synching the same folder simultaneously
diff --git a/plugins/libkolab/SQL/mysql.sql b/plugins/libkolab/SQL/mysql.sql
index 376eb4f..5f49e92 100644
--- a/plugins/libkolab/SQL/mysql.sql
+++ b/plugins/libkolab/SQL/mysql.sql
@@ -6,7 +6,7 @@
* @licence GNU AGPL
**/
-CREATE TABLE `kolab_cache` (
+CREATE TABLE IF NOT EXISTS `kolab_cache` (
`resource` VARCHAR(255) CHARACTER SET ascii NOT NULL,
`type` VARCHAR(32) CHARACTER SET ascii NOT NULL,
`msguid` BIGINT UNSIGNED NOT NULL,
diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index 9f80691..65aa4cb 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -81,6 +81,9 @@ class kolab_storage_cache
if ($this->synched)
return;
+ // lock synchronization for this folder or wait if locked
+ $this->_sync_lock();
+
// synchronize IMAP mailbox cache
$this->imap->folder_sync($this->folder->name);
@@ -92,8 +95,9 @@ class kolab_storage_cache
if ($this->ready) {
// read cache index
$sql_result = $this->db->query(
- "SELECT msguid, uid FROM kolab_cache WHERE resource=?",
- $this->resource_uri
+ "SELECT msguid, uid FROM kolab_cache WHERE resource=? AND type<>?",
+ $this->resource_uri,
+ 'lock'
);
$old_index = array();
@@ -120,6 +124,9 @@ class kolab_storage_cache
}
}
+ // remove lock
+ $this->_sync_unlock();
+
$this->synched = time();
}
@@ -349,6 +356,7 @@ class kolab_storage_cache
$this->db->quote($param[2])
);
}
+
return $sql_where;
}
@@ -400,6 +408,11 @@ class kolab_storage_cache
// database runs in server's timezone so using date() is what we want
$sql_data['dtstart'] = date('Y-m-d H:i:s', is_object($object['start']) ? $object['start']->format('U') : $object['start']);
$sql_data['dtend'] = date('Y-m-d H:i:s', is_object($object['end']) ? $object['end']->format('U') : $object['end']);
+
+ // extend date range for recurring events
+ if ($object['recurrence']) {
+ $sql_data['dtend'] = date('Y-m-d H:i:s', $object['recurrence']['UNTIL'] ?: strtotime('now + 2 years'));
+ }
}
if ($object['_formatobj'])
@@ -454,6 +467,61 @@ class kolab_storage_cache
}
/**
+ * Check lock record for this folder and wait if locked or set lock
+ */
+ private function _sync_lock()
+ {
+ if (!$this->ready)
+ return;
+
+ $sql_arr = $this->db->fetch_assoc($this->db->query(
+ "SELECT msguid AS locked FROM kolab_cache ".
+ "WHERE resource=? AND type=?",
+ $this->resource_uri,
+ 'lock'
+ ));
+
+ // create lock record if not exists
+ if (!$sql_arr) {
+ $this->db->query(
+ "INSERT INTO kolab_cache (resource, type, msguid, uid, data, xml)".
+ " VALUES (?, ?, ?, '', '', '')",
+ $this->resource_uri,
+ 'lock',
+ time()
+ );
+ }
+ // wait if locked (expire locks after 10 minutes)
+ else if (intval($sql_arr['locked']) > 0 && (time() - $sql_arr['locked']) < 600) {
+ usleep(500000);
+ return $this->_sync_lock();
+ }
+ // set lock
+ else {
+ $this->db->query(
+ "UPDATE kolab_cache SET msguid=? ".
+ "WHERE resource=? AND type=?",
+ time(),
+ $this->resource_uri,
+ 'lock'
+ );
+ }
+ }
+
+ /**
+ * Remove lock for this folder
+ */
+ private function _sync_unlock()
+ {
+ $this->db->query(
+ "UPDATE kolab_cache SET msguid=0 ".
+ "WHERE resource=? AND type=?",
+ $this->resource_uri,
+ 'lock'
+ );
+ }
+
+ /**
* Resolve an object UID into an IMAP message UID
*
* @param string Kolab object UID
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index c55a34f..eed7b08 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -318,6 +318,41 @@ class kolab_storage_folder
/**
+ * Select *some* Kolab objects matching the given query
+ *
+ * @param array Pseudo-SQL query as list of filter parameter triplets
+ * triplet: array('<colname>', '<comparator>', '<value>')
+ * @return array List of Kolab data objects (each represented as hash array)
+ */
+ public function select($query = array())
+ {
+ // check query argument
+ if (empty($query))
+ return $this->get_objects();
+
+ $type = null;
+ foreach ($query as $i => $param) {
+ if ($param[0] == 'type') {
+ $type = $param[2];
+ }
+ else if (($param[0] == 'dtstart' || $param[0] == 'dtend') && is_numeric($param[2])) {
+ $query[$i][2] = date('Y-m-d H:i:s', $param[2]);
+ }
+ }
+
+ // add type selector if not in $query
+ if (!$type)
+ $query[] = array('type','=',$this->type);
+
+ // synchronize caches
+ $this->cache->synchronize();
+
+ // fetch objects from cache
+ return $this->cache->select($query);
+ }
+
+
+ /**
* Getter for a single Kolab object, identified by its UID
*
* @param string Object UID
diff --git a/plugins/libkolab/libkolab.php b/plugins/libkolab/libkolab.php
index 3d0709b..fd911be 100644
--- a/plugins/libkolab/libkolab.php
+++ b/plugins/libkolab/libkolab.php
@@ -63,9 +63,7 @@ class libkolab extends rcube_plugin
*/
function storage_init($p)
{
- $rcmail = rcmail::get_instance();
$p['fetch_headers'] = trim($p['fetch_headers'] .' X-KOLAB-TYPE');
-
return $p;
}
commit ed467e73f910f56e50759ad35f9a6bacf030bbe0
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed May 9 17:20:39 2012 +0200
Disable kolab_config plugin for now
diff --git a/plugins/kolab_config/kolab_config.php b/plugins/kolab_config/kolab_config.php
index 24d569e..b785306 100644
--- a/plugins/kolab_config/kolab_config.php
+++ b/plugins/kolab_config/kolab_config.php
@@ -61,16 +61,9 @@ class kolab_config extends rcube_plugin
if ($this->config)
return;
- $this->require_plugin('kolab_folders');
+ return; // CURRENTLY DISABLED until libkolabxml has support for config objects
- // load dependencies
- require_once 'Horde/Util.php';
- require_once 'Horde/Kolab/Format.php';
- require_once 'Horde/Kolab/Format/XML.php';
- require_once $this->home . '/lib/configuration.php';
- require_once $this->home . '/lib/kolab_configuration.php';
-
- String::setDefaultCharset('UTF-8');
+ $this->require_plugin('libkolab');
$this->config = new kolab_configuration();
More information about the commits
mailing list