예제 #1
0
 /**
  * Puts shallow read and/or write locks on files
  * 
  * Resources with a shallow lock on it can only be modified in the same
  * request as they were placed and not by parallel requests (in different
  * server threads/processes). However, as soon as the request ends, the lock
  * will be released.
  * 
  * Write locks can not be set if there is already a read or write lock set.
  * Read locks can not be set if there is already a write lock set. There can
  * be multiple read locks on the same resource!
  * 
  * @param  array  $write  paths to write-lock, use an empty array to skip
  * @param  array  $read   paths to read-lock
  * @return  void
  */
 public function shallowLock($write, $read = array())
 {
     $whashes = $rhashes = array();
     foreach ($write as $value) {
         $whashes[] = BeeHub_DB::escape_string(hash('sha256', $value, true));
     }
     foreach ($read as $value) {
         $rhashes[] = BeeHub_DB::escape_string(hash('sha256', $value, true));
     }
     sort($whashes, SORT_STRING);
     sort($rhashes, SORT_STRING);
     if (!empty($whashes)) {
         BeeHub_DB::query('INSERT IGNORE INTO `shallowLocks` VALUES (' . implode('),(', $whashes) . ');');
         $whashes = implode(',', $whashes);
         $whashes = "SELECT * FROM `shallowLocks` WHERE `pathhash` IN ({$whashes}) FOR UPDATE;";
     } else {
         $whashes = null;
     }
     if (!empty($rhashes)) {
         BeeHub_DB::query('INSERT IGNORE INTO `shallowLocks` VALUES (' . implode('),(', $rhashes) . ');');
         $rhashes = implode(',', $rhashes);
         $rhashes = "SELECT * FROM `shallowLocks` WHERE `pathhash` IN ({$rhashes}) LOCK IN SHARE MODE;";
     } else {
         $rhashes = null;
     }
     $microsleeptimer = 10000;
     // also functions as success flag
     while ($microsleeptimer) {
         if ($microsleeptimer > 1280000) {
             $microsleeptimer = 1280000;
         }
         BeeHub_DB::query('START TRANSACTION');
         if ($whashes) {
             try {
                 BeeHub_DB::query($whashes)->free_result();
             } catch (BeeHub_Deadlock $e) {
                 BeeHub_DB::query('ROLLBACK');
                 usleep($microsleeptimer);
                 $microsleeptimer *= 2;
                 continue;
             } catch (BeeHub_Timeout $e) {
                 BeeHub_DB::query('ROLLBACK');
                 throw new DAV_Status(DAV::HTTP_SERVICE_UNAVAILABLE);
             }
         }
         if ($rhashes) {
             try {
                 BeeHub_DB::query($rhashes)->free_result();
             } catch (BeeHub_Deadlock $e) {
                 BeeHub_DB::query('ROLLBACK');
                 usleep($microsleeptimer);
                 $microsleeptimer *= 2;
                 continue;
             } catch (BeeHub_Timeout $e) {
                 BeeHub_DB::query('ROLLBACK');
                 throw new DAV_Status(DAV::HTTP_SERVICE_UNAVAILABLE);
             }
         }
         $microsleeptimer = 0;
     }
 }