From b72709a5cf0bf80eb4ca34d1eb5daea9765e7e80 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Mon, 7 Oct 2013 11:59:00 +0200 Subject: [PATCH] Lazy read kolab_folder record from DB; fix error when mass-inserting cache records --- plugins/libkolab/lib/kolab_storage_cache.php | 82 ++++++++++++++------ 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php index eeae0465..48a02852 100644 --- a/plugins/libkolab/lib/kolab_storage_cache.php +++ b/plugins/libkolab/lib/kolab_storage_cache.php @@ -38,6 +38,7 @@ class kolab_storage_cache protected $synclock = false; protected $ready = false; protected $cache_table; + protected $folders_table; protected $max_sql_packet; protected $max_sync_lock_time = 600; protected $binary_items = array( @@ -78,6 +79,8 @@ class kolab_storage_cache $this->enabled = $rcmail->config->get('kolab_cache', false); if ($this->enabled) { + // always read folder cache and lock state from DB master + $this->db->set_table_dsn('kolab_folders', 'w'); // remove sync-lock on script termination $rcmail->add_shutdown_function(array($this, '_sync_unlock')); } @@ -103,21 +106,10 @@ class kolab_storage_cache // compose fully qualified ressource uri for this instance $this->resource_uri = $this->folder->get_resource_uri(); + $this->folders_table = $this->db->table_name('kolab_folders'); $this->cache_table = $this->db->table_name('kolab_cache_' . $this->folder->type); $this->ready = $this->enabled; - - if ($this->enabled) { - $sql_arr = $this->db->fetch_assoc($this->db->query("SELECT ID, synclock, ctag FROM kolab_folders WHERE resource=?", $this->resource_uri)); - if ($sql_arr) { - $this->metadata = $sql_arr; - $this->folder_id = $sql_arr['ID']; - } - else { - $this->db->query("INSERT INTO kolab_folders (resource, type) VALUES (?, ?)", $this->resource_uri, $this->folder->type); - $this->folder_id = $this->db->insert_id('kolab_folders'); - $this->metadata = array(); - } - } + $this->folder_id = null; } /** @@ -143,7 +135,7 @@ class kolab_storage_cache // lock synchronization for this folder or wait if locked $this->_sync_lock(); - // check cache status hash first ($this->metadata is set in _sync_lock()) + // check cache status hash first ($this->metadata is set in _read_folder_data()) if ($this->metadata['ctag'] != $this->folder->get_ctag()) { // synchronize IMAP mailbox cache @@ -215,6 +207,8 @@ class kolab_storage_cache // load object if not in memory if (!isset($this->objects[$msguid])) { if ($this->ready) { + $this->_read_folder_data(); + $sql_result = $this->db->query( "SELECT * FROM $this->cache_table ". "WHERE folder_id=? AND msguid=?", @@ -259,6 +253,7 @@ class kolab_storage_cache // remove old entry if ($this->ready) { + $this->_read_folder_data(); $this->db->query("DELETE FROM $this->cache_table WHERE folder_id=? AND msguid=?", $this->folder_id, $msguid); } @@ -284,6 +279,8 @@ class kolab_storage_cache { // write to cache if ($this->ready) { + $this->_read_folder_data(); + $sql_data = $this->_serialize($object); $extra_cols = $this->extra_cols ? ', ' . join(', ', $this->extra_cols) : ''; @@ -307,7 +304,7 @@ class kolab_storage_cache $args[] = $sql_data[$col]; } - $result = call_user_func_array(array($this->db, 'call'), $args); + $result = call_user_func_array(array($this->db, 'query'), $args); if (!$this->db->affected_rows($result)) { rcube::raise_error(array( @@ -336,6 +333,8 @@ class kolab_storage_cache // resolve new message UID in target folder if ($new_msguid = $target->cache->uid2msguid($uid)) { + $this->_read_folder_data(); + $this->db->query( "UPDATE $this->cache_table SET folder_id=?, msguid=? ". "WHERE folder_id=? AND msguid=?", @@ -359,6 +358,8 @@ class kolab_storage_cache */ public function purge($type = null) { + $this->_read_folder_data(); + $result = $this->db->query( "DELETE FROM $this->cache_table WHERE folder_id=?". $this->folder_id @@ -377,10 +378,10 @@ class kolab_storage_cache // resolve new message UID in target folder $this->db->query( - "UPDATE kolab_folders SET resource=? ". - "WHERE folder_id=?", + "UPDATE $this->folders_table SET resource=? ". + "WHERE resource=?", $target->get_resource_uri(), - $this->folder_id + $this->resource_uri ); } @@ -398,6 +399,8 @@ class kolab_storage_cache // read from local cache DB (assume it to be synchronized) if ($this->ready) { + $this->_read_folder_data(); + $sql_result = $this->db->query( "SELECT " . ($uids ? 'msguid, uid' : '*') . " FROM $this->cache_table ". "WHERE folder_id=? " . $this->_sql_where($query), @@ -458,6 +461,8 @@ class kolab_storage_cache // cache is in sync, we can count records in local DB if ($this->synched) { + $this->_read_folder_data(); + $sql_result = $this->db->query( "SELECT COUNT(*) AS numrows FROM kolab_cache ". "WHERE folder_id=? " . $this->_sql_where($query), @@ -722,6 +727,27 @@ class kolab_storage_cache return $this->max_sql_packet; } + /** + * Read this folder's ID and cache metadata + */ + protected function _read_folder_data() + { + // already done + if (!empty($this->folder_id)) + return; + + $sql_arr = $this->db->fetch_assoc($this->db->query("SELECT ID, synclock, ctag FROM $this->folders_table WHERE resource=?", $this->resource_uri)); + if ($sql_arr) { + $this->metadata = $sql_arr; + $this->folder_id = $sql_arr['ID']; + } + else { + $this->db->query("INSERT INTO $this->folders_table (resource, type) VALUES (?, ?)", $this->resource_uri, $this->folder->type); + $this->folder_id = $this->db->insert_id('kolab_folders'); + $this->metadata = array(); + } + } + /** * Check lock record for this folder and wait if locked or set lock */ @@ -730,8 +756,8 @@ class kolab_storage_cache if (!$this->ready) return; - $sql_query = "SELECT synclock, ctag FROM kolab_folders WHERE ID=?"; - $this->metadata = $this->db->fetch_assoc($this->db->query($sql_query, $this->folder_id)); + $this->_read_folder_data(); + $sql_query = "SELECT synclock, ctag FROM $this->folders_table WHERE ID=?"; // abort if database is not set-up if ($this->db->is_error()) { @@ -748,7 +774,7 @@ class kolab_storage_cache } // set lock - $this->db->query("UPDATE kolab_folders SET synclock = ? WHERE ID = ?", time(), $this->folder_id); + $this->db->query("UPDATE $this->folders_table SET synclock = ? WHERE ID = ?", time(), $this->folder_id); } /** @@ -760,7 +786,7 @@ class kolab_storage_cache return; $this->db->query( - "UPDATE kolab_folders SET synclock = 0, ctag = ? WHERE ID = ?", + "UPDATE $this->folders_table SET synclock = 0, ctag = ? WHERE ID = ?", $this->metadata['ctag'], $this->folder_id ); @@ -788,4 +814,16 @@ class kolab_storage_cache return $this->uid2msg[$uid]; } + /** + * Getter for protected member variables + */ + public function __get($name) + { + if ($name == 'folder_id') { + $this->_read_folder_data(); + } + + return $this->$name; + } + }