Changeset View
Changeset View
Standalone View
Standalone View
plugins/libkolab/lib/kolab_storage_cache.php
Show First 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | public function synchronize() | ||||
$time_limit = ini_get('max_execution_time') * 0.7; | $time_limit = ini_get('max_execution_time') * 0.7; | ||||
$sync_start = time(); | $sync_start = time(); | ||||
// assume sync will be completed | // assume sync will be completed | ||||
$this->sync_complete = true; | $this->sync_complete = true; | ||||
if (!$this->ready) { | if (!$this->ready) { | ||||
// kolab cache is disabled, synchronize IMAP mailbox cache only | // kolab cache is disabled, synchronize IMAP mailbox cache only | ||||
$this->imap_mode(true); | |||||
$this->imap->folder_sync($this->folder->name); | $this->imap->folder_sync($this->folder->name); | ||||
$this->imap_mode(false); | |||||
} | } | ||||
else { | else { | ||||
// read cached folder metadata | // read cached folder metadata | ||||
$this->_read_folder_data(); | $this->_read_folder_data(); | ||||
// check cache status ($this->metadata is set in _read_folder_data()) | // check cache status ($this->metadata is set in _read_folder_data()) | ||||
if ( empty($this->metadata['ctag']) || | if ( empty($this->metadata['ctag']) || | ||||
empty($this->metadata['changed']) || | empty($this->metadata['changed']) || | ||||
$this->metadata['objectcount'] === null || | $this->metadata['objectcount'] === null || | ||||
$this->metadata['changed'] < date(self::DB_DATE_FORMAT, time() - $this->cache_refresh) || | $this->metadata['changed'] < date(self::DB_DATE_FORMAT, time() - $this->cache_refresh) || | ||||
$this->metadata['ctag'] != $this->folder->get_ctag() || | $this->metadata['ctag'] != $this->folder->get_ctag() || | ||||
intval($this->metadata['objectcount']) !== $this->count() | intval($this->metadata['objectcount']) !== $this->count() | ||||
) { | ) { | ||||
// lock synchronization for this folder or wait if locked | // lock synchronization for this folder or wait if locked | ||||
$this->_sync_lock(); | $this->_sync_lock(); | ||||
// disable messages cache if configured to do so | // disable messages cache if configured to do so | ||||
$this->bypass(true); | $this->imap_mode(true); | ||||
// synchronize IMAP mailbox cache | // synchronize IMAP mailbox cache | ||||
$this->imap->folder_sync($this->folder->name); | $this->imap->folder_sync($this->folder->name); | ||||
// compare IMAP index with object cache index | // compare IMAP index with object cache index | ||||
$imap_index = $this->imap->index($this->folder->name, null, null, true, true); | $imap_index = $this->imap->index($this->folder->name, null, null, true, true); | ||||
$this->imap_mode(false); | |||||
// determine objects to fetch or to invalidate | // determine objects to fetch or to invalidate | ||||
if (!$imap_index->is_error()) { | if (!$imap_index->is_error()) { | ||||
$imap_index = $imap_index->get(); | $imap_index = $imap_index->get(); | ||||
// read cache index | // read cache index | ||||
$sql_result = $this->db->query( | $sql_result = $this->db->query( | ||||
"SELECT `msguid`, `uid` FROM `{$this->cache_table}` WHERE `folder_id` = ?", | "SELECT `msguid`, `uid` FROM `{$this->cache_table}` WHERE `folder_id` = ?", | ||||
$this->folder_id | $this->folder_id | ||||
Show All 33 Lines | public function synchronize() | ||||
if ($this->sync_complete) { | if ($this->sync_complete) { | ||||
$this->metadata['ctag'] = $this->folder->get_ctag(); | $this->metadata['ctag'] = $this->folder->get_ctag(); | ||||
$this->metadata['changed'] = date(self::DB_DATE_FORMAT, time()); | $this->metadata['changed'] = date(self::DB_DATE_FORMAT, time()); | ||||
// remember the number of cache entries linked to this folder | // remember the number of cache entries linked to this folder | ||||
$this->metadata['objectcount'] = $this->count(); | $this->metadata['objectcount'] = $this->count(); | ||||
} | } | ||||
} | } | ||||
$this->bypass(false); | |||||
// remove lock | // remove lock | ||||
$this->_sync_unlock(); | $this->_sync_unlock(); | ||||
} | } | ||||
} | } | ||||
$this->check_error(); | $this->check_error(); | ||||
$this->synched = time(); | $this->synched = time(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 324 Lines • ▼ Show 20 Lines | public function select($query = array(), $uids = false) | ||||
$result[] = $sql_arr; | $result[] = $sql_arr; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// use IMAP | // use IMAP | ||||
else { | else { | ||||
$filter = $this->_query2assoc($query); | $filter = $this->_query2assoc($query); | ||||
$this->imap_mode(true); | |||||
if ($filter['type']) { | if ($filter['type']) { | ||||
$search = 'UNDELETED HEADER X-Kolab-Type ' . kolab_format::KTYPE_PREFIX . $filter['type']; | $search = 'UNDELETED HEADER X-Kolab-Type ' . kolab_format::KTYPE_PREFIX . $filter['type']; | ||||
$index = $this->imap->search_once($this->folder->name, $search); | $index = $this->imap->search_once($this->folder->name, $search); | ||||
} | } | ||||
else { | else { | ||||
$index = $this->imap->index($this->folder->name, null, null, true, true); | $index = $this->imap->index($this->folder->name, null, null, true, true); | ||||
} | } | ||||
$this->imap_mode(false); | |||||
if ($index->is_error()) { | if ($index->is_error()) { | ||||
$this->check_error(); | $this->check_error(); | ||||
if ($uids) { | if ($uids) { | ||||
return null; | return null; | ||||
} | } | ||||
$result->set_error(true); | $result->set_error(true); | ||||
return $result; | return $result; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | public function count($query = array()) | ||||
$sql_arr = $this->db->fetch_assoc($sql_result); | $sql_arr = $this->db->fetch_assoc($sql_result); | ||||
$count = intval($sql_arr['numrows']); | $count = intval($sql_arr['numrows']); | ||||
} | } | ||||
// use IMAP | // use IMAP | ||||
else { | else { | ||||
$filter = $this->_query2assoc($query); | $filter = $this->_query2assoc($query); | ||||
$this->imap_mode(true); | |||||
if ($filter['type']) { | if ($filter['type']) { | ||||
$search = 'UNDELETED HEADER X-Kolab-Type ' . kolab_format::KTYPE_PREFIX . $filter['type']; | $search = 'UNDELETED HEADER X-Kolab-Type ' . kolab_format::KTYPE_PREFIX . $filter['type']; | ||||
$index = $this->imap->search_once($this->folder->name, $search); | $index = $this->imap->search_once($this->folder->name, $search); | ||||
} | } | ||||
else { | else { | ||||
$index = $this->imap->index($this->folder->name, null, null, true, true); | $index = $this->imap->index($this->folder->name, null, null, true, true); | ||||
} | } | ||||
$this->imap_mode(false); | |||||
if ($index->is_error()) { | if ($index->is_error()) { | ||||
$this->check_error(); | $this->check_error(); | ||||
return null; | return null; | ||||
} | } | ||||
// TODO: post-filter result according to query | // TODO: post-filter result according to query | ||||
$count = $index->count(); | $count = $index->count(); | ||||
▲ Show 20 Lines • Show All 442 Lines • ▼ Show 20 Lines | public function __get($name) | ||||
if ($name == 'folder_id') { | if ($name == 'folder_id') { | ||||
$this->_read_folder_data(); | $this->_read_folder_data(); | ||||
} | } | ||||
return $this->$name; | return $this->$name; | ||||
} | } | ||||
/** | /** | ||||
* Bypass Roundcube messages cache. | * Set Roundcube storage options and bypass messages cache. | ||||
* Roundcube cache duplicates information already stored in kolab_cache. | |||||
* | * | ||||
* @param bool $disable True disables, False enables messages cache | * We use skip_deleted and threading settings specific to Kolab, | ||||
* we have to change these global settings only temporarily. | |||||
* Roundcube cache duplicates information already stored in kolab_cache, | |||||
* that's why we can disable it for better performance. | |||||
* | |||||
* @param bool $force True to start Kolab mode, False to stop it. | |||||
*/ | */ | ||||
public function bypass($disable = false) | public function imap_mode($force = false) | ||||
{ | { | ||||
// remember current IMAP settings | |||||
if ($force) { | |||||
$this->imap_options = array( | |||||
'skip_deleted' => $this->imap->get_option('skip_deleted'), | |||||
'threading' => $this->imap->get_threading(), | |||||
); | |||||
} | |||||
// re-set IMAP settings | |||||
$this->imap->set_threading($force ? false : $this->imap_options['threading']); | |||||
$this->imap->set_options(array( | |||||
'skip_deleted' => $force ? true : $this->imap_options['skip_deleted'], | |||||
)); | |||||
// if kolab cache is disabled do nothing | // if kolab cache is disabled do nothing | ||||
if (!$this->enabled) { | if (!$this->enabled) { | ||||
return; | return; | ||||
} | } | ||||
static $messages_cache, $cache_bypass; | static $messages_cache, $cache_bypass; | ||||
if ($messages_cache === null) { | if ($messages_cache === null) { | ||||
$rcmail = rcube::get_instance(); | $rcmail = rcube::get_instance(); | ||||
$messages_cache = (bool) $rcmail->config->get('messages_cache'); | $messages_cache = (bool) $rcmail->config->get('messages_cache'); | ||||
$cache_bypass = (int) $rcmail->config->get('kolab_messages_cache_bypass'); | $cache_bypass = (int) $rcmail->config->get('kolab_messages_cache_bypass'); | ||||
} | } | ||||
if ($messages_cache) { | if ($messages_cache) { | ||||
// handle recurrent (multilevel) bypass() calls | // handle recurrent (multilevel) bypass() calls | ||||
if ($disable) { | if ($force) { | ||||
$this->cache_bypassed += 1; | $this->cache_bypassed += 1; | ||||
if ($this->cache_bypassed > 1) { | if ($this->cache_bypassed > 1) { | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
else { | else { | ||||
$this->cache_bypassed -= 1; | $this->cache_bypassed -= 1; | ||||
if ($this->cache_bypassed > 0) { | if ($this->cache_bypassed > 0) { | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
switch ($cache_bypass) { | switch ($cache_bypass) { | ||||
case 2: | case 2: | ||||
// Disable messages cache completely | // Disable messages cache completely | ||||
$this->imap->set_messages_caching(!$disable); | $this->imap->set_messages_caching(!$force); | ||||
break; | break; | ||||
case 1: | case 1: | ||||
// We'll disable messages cache, but keep index cache. | // We'll disable messages cache, but keep index cache. | ||||
// Default mode is both (MODE_INDEX | MODE_MESSAGE) | // Default mode is both (MODE_INDEX | MODE_MESSAGE) | ||||
$mode = rcube_imap_cache::MODE_INDEX; | $mode = rcube_imap_cache::MODE_INDEX; | ||||
if (!$disable) { | if (!$force) { | ||||
$mode |= rcube_imap_cache::MODE_MESSAGE; | $mode |= rcube_imap_cache::MODE_MESSAGE; | ||||
} | } | ||||
$this->imap->set_messages_caching(true, $mode); | $this->imap->set_messages_caching(true, $mode); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
Show All 16 Lines |