summaryrefslogtreecommitdiff
path: root/plugins/libkolab
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2015-02-05 14:27:28 (GMT)
committerThomas Bruederli <bruederli@kolabsys.com>2015-02-05 14:27:28 (GMT)
commit39449c11ce0fc00546cab84ac873a2d6ceb44194 (patch)
treed92327067f28dc4e061c068733e9a785f1bca784 /plugins/libkolab
parent8d10498a8fe26687fac4c7d01d77bdd19c955181 (diff)
downloadroundcubemail-plugins-kolab-39449c11ce0fc00546cab84ac873a2d6ceb44194.tar.gz
Improve groupware object cache synchronization (#3933):
- store and compare the number of objects stored after last sync - use a (configurable) refresh interval and periodically force re-sync ATTENTION: requires database schema updates
Diffstat (limited to 'plugins/libkolab')
-rw-r--r--plugins/libkolab/SQL/mysql.initial.sql2
-rw-r--r--plugins/libkolab/SQL/mysql/2015020600.sql4
-rw-r--r--plugins/libkolab/SQL/oracle.initial.sql4
-rw-r--r--plugins/libkolab/SQL/oracle/2015020600.sql4
-rw-r--r--plugins/libkolab/config.inc.php.dist4
-rw-r--r--plugins/libkolab/lib/kolab_storage_cache.php23
6 files changed, 35 insertions, 6 deletions
diff --git a/plugins/libkolab/SQL/mysql.initial.sql b/plugins/libkolab/SQL/mysql.initial.sql
index 98e7e78..8f50d94 100644
--- a/plugins/libkolab/SQL/mysql.initial.sql
+++ b/plugins/libkolab/SQL/mysql.initial.sql
@@ -15,6 +15,8 @@ CREATE TABLE `kolab_folders` (
`type` VARCHAR(32) NOT NULL,
`synclock` INT(10) NOT NULL DEFAULT '0',
`ctag` VARCHAR(40) DEFAULT NULL,
+ `changed` DATETIME DEFAULT NULL,
+ `objectcount` BIGINT DEFAULT NULL,
PRIMARY KEY(`folder_id`),
INDEX `resource_type` (`resource`, `type`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
diff --git a/plugins/libkolab/SQL/mysql/2015020600.sql b/plugins/libkolab/SQL/mysql/2015020600.sql
new file mode 100644
index 0000000..d9077a0
--- /dev/null
+++ b/plugins/libkolab/SQL/mysql/2015020600.sql
@@ -0,0 +1,4 @@
+-- improve cache synchronization (#3933)
+ALTER TABLE `kolab_folders`
+ ADD `changed` DATETIME DEFAULT NULL,
+ ADD `objectcount` BIGINT DEFAULT NULL;
diff --git a/plugins/libkolab/SQL/oracle.initial.sql b/plugins/libkolab/SQL/oracle.initial.sql
index 8f1ed64..19027ee 100644
--- a/plugins/libkolab/SQL/oracle.initial.sql
+++ b/plugins/libkolab/SQL/oracle.initial.sql
@@ -12,7 +12,9 @@ CREATE TABLE "kolab_folders" (
"resource" VARCHAR(255) NOT NULL,
"type" VARCHAR(32) NOT NULL,
"synclock" integer DEFAULT 0 NOT NULL,
- "ctag" VARCHAR(40) DEFAULT NULL
+ "ctag" VARCHAR(40) DEFAULT NULL,
+ "changed" timestamp DEFAULT NULL,
+ "objectcount" number DEFAULT NULL
);
CREATE INDEX "kolab_folders_resource_idx" ON "kolab_folders" ("resource", "type");
diff --git a/plugins/libkolab/SQL/oracle/2015020600.sql b/plugins/libkolab/SQL/oracle/2015020600.sql
new file mode 100644
index 0000000..a605649
--- /dev/null
+++ b/plugins/libkolab/SQL/oracle/2015020600.sql
@@ -0,0 +1,4 @@
+-- improve cache synchronization (#3933)
+ALTER TABLE "kolab_folders"
+ ADD "changed" timestamp DEFAULT NULL,
+ ADD "objectcount" number DEFAULT NULL;
diff --git a/plugins/libkolab/config.inc.php.dist b/plugins/libkolab/config.inc.php.dist
index 7efa8d1..5973d33 100644
--- a/plugins/libkolab/config.inc.php.dist
+++ b/plugins/libkolab/config.inc.php.dist
@@ -5,6 +5,10 @@
// Enable caching of Kolab objects in local database
$config['kolab_cache'] = true;
+// Cache refresh interval (default is 12 hours)
+// after this period, cache is forced to synchronize with IMAP
+$config['kolab_cache_refresh'] = '12h';
+
// Specify format version to write Kolab objects (must be a string value!)
$config['kolab_format_version'] = '3.0';
diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index 227fa4e..9f4533c 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -41,6 +41,7 @@ class kolab_storage_cache
protected $synclock = false;
protected $ready = false;
protected $cache_table;
+ protected $cache_refresh = 3600;
protected $folders_table;
protected $max_sql_packet;
protected $max_sync_lock_time = 600;
@@ -82,6 +83,7 @@ class kolab_storage_cache
$this->imap = $rcmail->get_storage();
$this->enabled = $rcmail->config->get('kolab_cache', false);
$this->folders_table = $this->db->table_name('kolab_folders');
+ $this->cache_refresh = get_offset_sec($rcmail->config->get('kolab_cache_refresh', '12h'));
if ($this->enabled) {
// always read folder cache and lock state from DB master
@@ -187,8 +189,14 @@ class kolab_storage_cache
// read cached folder metadata
$this->_read_folder_data();
- // check cache status hash first ($this->metadata is set in _read_folder_data())
- if ($this->metadata['ctag'] != $this->folder->get_ctag()) {
+ // check cache status ($this->metadata is set in _read_folder_data())
+ if ( empty($this->metadata['ctag']) ||
+ empty($this->metadata['changed']) ||
+ $this->metadata['objectcount'] === null ||
+ $this->metadata['changed'] < date(self::DB_DATE_FORMAT, time() - $this->cache_refresh) ||
+ $this->metadata['ctag'] != $this->folder->get_ctag() ||
+ intval($this->metadata['objectcount']) !== $this->count()
+ ) {
// lock synchronization for this folder or wait if locked
$this->_sync_lock();
@@ -244,6 +252,9 @@ class kolab_storage_cache
// update ctag value (will be written to database in _sync_unlock())
if ($this->sync_complete) {
$this->metadata['ctag'] = $this->folder->get_ctag();
+ $this->metadata['changed'] = date(self::DB_DATE_FORMAT, time());
+ // remember the number of cache entries linked to this folder
+ $this->metadata['objectcount'] = $this->count();
}
}
@@ -749,7 +760,7 @@ class kolab_storage_cache
$sql_data = array('changed' => null, 'xml' => '', 'tags' => '', 'words' => '');
if ($object['changed']) {
- $sql_data['changed'] = date('Y-m-d H:i:s', is_object($object['changed']) ? $object['changed']->format('U') : $object['changed']);
+ $sql_data['changed'] = date(self::DB_DATE_FORMAT, is_object($object['changed']) ? $object['changed']->format('U') : $object['changed']);
}
if ($object['_formatobj']) {
@@ -943,7 +954,7 @@ class kolab_storage_cache
return;
$sql_arr = $this->db->fetch_assoc($this->db->query(
- "SELECT `folder_id`, `synclock`, `ctag`"
+ "SELECT `folder_id`, `synclock`, `ctag`, `changed`, `objectcount`"
. " FROM `{$this->folders_table}` WHERE `resource` = ?",
$this->resource_uri
));
@@ -1004,8 +1015,10 @@ class kolab_storage_cache
return;
$this->db->query(
- "UPDATE `{$this->folders_table}` SET `synclock` = 0, `ctag` = ? WHERE `folder_id` = ?",
+ "UPDATE `{$this->folders_table}` SET `synclock` = 0, `ctag` = ?, `changed` = ?, `objectcount` = ? WHERE `folder_id` = ?",
$this->metadata['ctag'],
+ $this->metadata['changed'],
+ $this->metadata['objectcount'],
$this->folder_id
);