plugins/libkolab

Thomas Brüderli bruederli at kolabsys.com
Fri Jan 23 14:44:00 CET 2015


 plugins/libkolab/lib/kolab_storage_cache.php |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

New commits:
commit af216b50e3251a138fd531ec0bbc79b4cd51829c
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Jan 22 20:09:22 2015 +0100

    Improve sync lock setting/reading to avoid race conditions (#4316)

diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index 144cfa1..524a03a 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -935,7 +935,6 @@ class kolab_storage_cache
             return;
 
         $this->_read_folder_data();
-        $sql_query = "SELECT `synclock`, `ctag` FROM `{$this->folders_table}` WHERE `folder_id` = ?";
 
         // abort if database is not set-up
         if ($this->db->is_error()) {
@@ -943,16 +942,21 @@ class kolab_storage_cache
             return;
         }
 
-        $this->synclock = true;
+        $read_query  = "SELECT `synclock`, `ctag` FROM `{$this->folders_table}` WHERE `folder_id` = ?";
+        $write_query = "UPDATE `{$this->folders_table}` SET `synclock` = ? WHERE `folder_id` = ? AND `synclock` = ?";
 
-        // wait if locked (expire locks after 10 minutes)
-        while ($this->metadata && intval($this->metadata['synclock']) > 0 && $this->metadata['synclock'] + $this->max_sync_lock_time > time()) {
+        // wait if locked (expire locks after 10 minutes) ...
+        // ... or if setting lock fails (another process meanwhile set it)
+        while (
+            (intval($this->metadata['synclock']) + $this->max_sync_lock_time > time()) ||
+            (($res = $this->db->query($write_query, time(), $this->folder_id, intval($this->metadata['synclock']))) &&
+                !($affected = $this->db->affected_rows($res)))
+        ) {
             usleep(500000);
-            $this->metadata = $this->db->fetch_assoc($this->db->query($sql_query, $this->folder_id));
+            $this->metadata = $this->db->fetch_assoc($this->db->query($read_query, $this->folder_id));
         }
 
-        // set lock
-        $this->db->query("UPDATE `{$this->folders_table}` SET `synclock` = ? WHERE `folder_id` = ?", time(), $this->folder_id);
+        $this->synclock = $affected > 0;
     }
 
     /**




More information about the commits mailing list