Completed
Push — master ( db8bcf...056660 )
by Blizzz
38s
created
lib/private/Lock/DBLockingProvider.php 1 patch
Indentation   +249 added lines, -249 removed lines patch added patch discarded remove patch
@@ -38,276 +38,276 @@
 block discarded – undo
38 38
  * Locking provider that stores the locks in the database
39 39
  */
40 40
 class DBLockingProvider extends AbstractLockingProvider {
41
-	/**
42
-	 * @var \OCP\IDBConnection
43
-	 */
44
-	private $connection;
41
+    /**
42
+     * @var \OCP\IDBConnection
43
+     */
44
+    private $connection;
45 45
 
46
-	/**
47
-	 * @var \OCP\ILogger
48
-	 */
49
-	private $logger;
46
+    /**
47
+     * @var \OCP\ILogger
48
+     */
49
+    private $logger;
50 50
 
51
-	/**
52
-	 * @var \OCP\AppFramework\Utility\ITimeFactory
53
-	 */
54
-	private $timeFactory;
51
+    /**
52
+     * @var \OCP\AppFramework\Utility\ITimeFactory
53
+     */
54
+    private $timeFactory;
55 55
 
56
-	private $sharedLocks = [];
56
+    private $sharedLocks = [];
57 57
 
58
-	/**
59
-	 * @var bool
60
-	 */
61
-	private $cacheSharedLocks;
58
+    /**
59
+     * @var bool
60
+     */
61
+    private $cacheSharedLocks;
62 62
 
63
-	/**
64
-	 * Check if we have an open shared lock for a path
65
-	 *
66
-	 * @param string $path
67
-	 * @return bool
68
-	 */
69
-	protected function isLocallyLocked(string $path): bool {
70
-		return isset($this->sharedLocks[$path]) && $this->sharedLocks[$path];
71
-	}
63
+    /**
64
+     * Check if we have an open shared lock for a path
65
+     *
66
+     * @param string $path
67
+     * @return bool
68
+     */
69
+    protected function isLocallyLocked(string $path): bool {
70
+        return isset($this->sharedLocks[$path]) && $this->sharedLocks[$path];
71
+    }
72 72
 
73
-	/**
74
-	 * Mark a locally acquired lock
75
-	 *
76
-	 * @param string $path
77
-	 * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
78
-	 */
79
-	protected function markAcquire(string $path, int $type) {
80
-		parent::markAcquire($path, $type);
81
-		if ($this->cacheSharedLocks) {
82
-			if ($type === self::LOCK_SHARED) {
83
-				$this->sharedLocks[$path] = true;
84
-			}
85
-		}
86
-	}
73
+    /**
74
+     * Mark a locally acquired lock
75
+     *
76
+     * @param string $path
77
+     * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
78
+     */
79
+    protected function markAcquire(string $path, int $type) {
80
+        parent::markAcquire($path, $type);
81
+        if ($this->cacheSharedLocks) {
82
+            if ($type === self::LOCK_SHARED) {
83
+                $this->sharedLocks[$path] = true;
84
+            }
85
+        }
86
+    }
87 87
 
88
-	/**
89
-	 * Change the type of an existing tracked lock
90
-	 *
91
-	 * @param string $path
92
-	 * @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
93
-	 */
94
-	protected function markChange(string $path, int $targetType) {
95
-		parent::markChange($path, $targetType);
96
-		if ($this->cacheSharedLocks) {
97
-			if ($targetType === self::LOCK_SHARED) {
98
-				$this->sharedLocks[$path] = true;
99
-			} else if ($targetType === self::LOCK_EXCLUSIVE) {
100
-				$this->sharedLocks[$path] = false;
101
-			}
102
-		}
103
-	}
88
+    /**
89
+     * Change the type of an existing tracked lock
90
+     *
91
+     * @param string $path
92
+     * @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
93
+     */
94
+    protected function markChange(string $path, int $targetType) {
95
+        parent::markChange($path, $targetType);
96
+        if ($this->cacheSharedLocks) {
97
+            if ($targetType === self::LOCK_SHARED) {
98
+                $this->sharedLocks[$path] = true;
99
+            } else if ($targetType === self::LOCK_EXCLUSIVE) {
100
+                $this->sharedLocks[$path] = false;
101
+            }
102
+        }
103
+    }
104 104
 
105
-	/**
106
-	 * @param \OCP\IDBConnection $connection
107
-	 * @param \OCP\ILogger $logger
108
-	 * @param \OCP\AppFramework\Utility\ITimeFactory $timeFactory
109
-	 * @param int $ttl
110
-	 * @param bool $cacheSharedLocks
111
-	 */
112
-	public function __construct(
113
-		IDBConnection $connection,
114
-		ILogger $logger,
115
-		ITimeFactory $timeFactory,
116
-		int $ttl = 3600,
117
-		$cacheSharedLocks = true
118
-	) {
119
-		$this->connection = $connection;
120
-		$this->logger = $logger;
121
-		$this->timeFactory = $timeFactory;
122
-		$this->ttl = $ttl;
123
-		$this->cacheSharedLocks = $cacheSharedLocks;
124
-	}
105
+    /**
106
+     * @param \OCP\IDBConnection $connection
107
+     * @param \OCP\ILogger $logger
108
+     * @param \OCP\AppFramework\Utility\ITimeFactory $timeFactory
109
+     * @param int $ttl
110
+     * @param bool $cacheSharedLocks
111
+     */
112
+    public function __construct(
113
+        IDBConnection $connection,
114
+        ILogger $logger,
115
+        ITimeFactory $timeFactory,
116
+        int $ttl = 3600,
117
+        $cacheSharedLocks = true
118
+    ) {
119
+        $this->connection = $connection;
120
+        $this->logger = $logger;
121
+        $this->timeFactory = $timeFactory;
122
+        $this->ttl = $ttl;
123
+        $this->cacheSharedLocks = $cacheSharedLocks;
124
+    }
125 125
 
126
-	/**
127
-	 * Insert a file locking row if it does not exists.
128
-	 *
129
-	 * @param string $path
130
-	 * @param int $lock
131
-	 * @return int number of inserted rows
132
-	 */
126
+    /**
127
+     * Insert a file locking row if it does not exists.
128
+     *
129
+     * @param string $path
130
+     * @param int $lock
131
+     * @return int number of inserted rows
132
+     */
133 133
 
134
-	protected function initLockField(string $path, int $lock = 0): int {
135
-		$expire = $this->getExpireTime();
136
-		return $this->connection->insertIfNotExist('*PREFIX*file_locks', ['key' => $path, 'lock' => $lock, 'ttl' => $expire], ['key']);
137
-	}
134
+    protected function initLockField(string $path, int $lock = 0): int {
135
+        $expire = $this->getExpireTime();
136
+        return $this->connection->insertIfNotExist('*PREFIX*file_locks', ['key' => $path, 'lock' => $lock, 'ttl' => $expire], ['key']);
137
+    }
138 138
 
139
-	/**
140
-	 * @return int
141
-	 */
142
-	protected function getExpireTime(): int {
143
-		return $this->timeFactory->getTime() + $this->ttl;
144
-	}
139
+    /**
140
+     * @return int
141
+     */
142
+    protected function getExpireTime(): int {
143
+        return $this->timeFactory->getTime() + $this->ttl;
144
+    }
145 145
 
146
-	/**
147
-	 * @param string $path
148
-	 * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
149
-	 * @return bool
150
-	 */
151
-	public function isLocked(string $path, int $type): bool {
152
-		if ($this->hasAcquiredLock($path, $type)) {
153
-			return true;
154
-		}
155
-		$query = $this->connection->prepare('SELECT `lock` from `*PREFIX*file_locks` WHERE `key` = ?');
156
-		$query->execute([$path]);
157
-		$lockValue = (int)$query->fetchColumn();
158
-		if ($type === self::LOCK_SHARED) {
159
-			if ($this->isLocallyLocked($path)) {
160
-				// if we have a shared lock we kept open locally but it's released we always have at least 1 shared lock in the db
161
-				return $lockValue > 1;
162
-			} else {
163
-				return $lockValue > 0;
164
-			}
165
-		} else if ($type === self::LOCK_EXCLUSIVE) {
166
-			return $lockValue === -1;
167
-		} else {
168
-			return false;
169
-		}
170
-	}
146
+    /**
147
+     * @param string $path
148
+     * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
149
+     * @return bool
150
+     */
151
+    public function isLocked(string $path, int $type): bool {
152
+        if ($this->hasAcquiredLock($path, $type)) {
153
+            return true;
154
+        }
155
+        $query = $this->connection->prepare('SELECT `lock` from `*PREFIX*file_locks` WHERE `key` = ?');
156
+        $query->execute([$path]);
157
+        $lockValue = (int)$query->fetchColumn();
158
+        if ($type === self::LOCK_SHARED) {
159
+            if ($this->isLocallyLocked($path)) {
160
+                // if we have a shared lock we kept open locally but it's released we always have at least 1 shared lock in the db
161
+                return $lockValue > 1;
162
+            } else {
163
+                return $lockValue > 0;
164
+            }
165
+        } else if ($type === self::LOCK_EXCLUSIVE) {
166
+            return $lockValue === -1;
167
+        } else {
168
+            return false;
169
+        }
170
+    }
171 171
 
172
-	/**
173
-	 * @param string $path
174
-	 * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
175
-	 * @throws \OCP\Lock\LockedException
176
-	 */
177
-	public function acquireLock(string $path, int $type) {
178
-		$expire = $this->getExpireTime();
179
-		if ($type === self::LOCK_SHARED) {
180
-			if (!$this->isLocallyLocked($path)) {
181
-				$result = $this->initLockField($path, 1);
182
-				if ($result <= 0) {
183
-					$result = $this->connection->executeUpdate(
184
-						'UPDATE `*PREFIX*file_locks` SET `lock` = `lock` + 1, `ttl` = ? WHERE `key` = ? AND `lock` >= 0',
185
-						[$expire, $path]
186
-					);
187
-				}
188
-			} else {
189
-				$result = 1;
190
-			}
191
-		} else {
192
-			$existing = 0;
193
-			if ($this->hasAcquiredLock($path, ILockingProvider::LOCK_SHARED) === false && $this->isLocallyLocked($path)) {
194
-				$existing = 1;
195
-			}
196
-			$result = $this->initLockField($path, -1);
197
-			if ($result <= 0) {
198
-				$result = $this->connection->executeUpdate(
199
-					'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = ?',
200
-					[$expire, $path, $existing]
201
-				);
202
-			}
203
-		}
204
-		if ($result !== 1) {
205
-			throw new LockedException($path);
206
-		}
207
-		$this->markAcquire($path, $type);
208
-	}
172
+    /**
173
+     * @param string $path
174
+     * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
175
+     * @throws \OCP\Lock\LockedException
176
+     */
177
+    public function acquireLock(string $path, int $type) {
178
+        $expire = $this->getExpireTime();
179
+        if ($type === self::LOCK_SHARED) {
180
+            if (!$this->isLocallyLocked($path)) {
181
+                $result = $this->initLockField($path, 1);
182
+                if ($result <= 0) {
183
+                    $result = $this->connection->executeUpdate(
184
+                        'UPDATE `*PREFIX*file_locks` SET `lock` = `lock` + 1, `ttl` = ? WHERE `key` = ? AND `lock` >= 0',
185
+                        [$expire, $path]
186
+                    );
187
+                }
188
+            } else {
189
+                $result = 1;
190
+            }
191
+        } else {
192
+            $existing = 0;
193
+            if ($this->hasAcquiredLock($path, ILockingProvider::LOCK_SHARED) === false && $this->isLocallyLocked($path)) {
194
+                $existing = 1;
195
+            }
196
+            $result = $this->initLockField($path, -1);
197
+            if ($result <= 0) {
198
+                $result = $this->connection->executeUpdate(
199
+                    'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = ?',
200
+                    [$expire, $path, $existing]
201
+                );
202
+            }
203
+        }
204
+        if ($result !== 1) {
205
+            throw new LockedException($path);
206
+        }
207
+        $this->markAcquire($path, $type);
208
+    }
209 209
 
210
-	/**
211
-	 * @param string $path
212
-	 * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
213
-	 *
214
-	 * @suppress SqlInjectionChecker
215
-	 */
216
-	public function releaseLock(string $path, int $type) {
217
-		$this->markRelease($path, $type);
210
+    /**
211
+     * @param string $path
212
+     * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
213
+     *
214
+     * @suppress SqlInjectionChecker
215
+     */
216
+    public function releaseLock(string $path, int $type) {
217
+        $this->markRelease($path, $type);
218 218
 
219
-		// we keep shared locks till the end of the request so we can re-use them
220
-		if ($type === self::LOCK_EXCLUSIVE) {
221
-			$this->connection->executeUpdate(
222
-				'UPDATE `*PREFIX*file_locks` SET `lock` = 0 WHERE `key` = ? AND `lock` = -1',
223
-				[$path]
224
-			);
225
-		} else if (!$this->cacheSharedLocks) {
226
-			$query = $this->connection->getQueryBuilder();
227
-			$query->update('file_locks')
228
-				->set('lock', $query->func()->subtract('lock', $query->createNamedParameter(1)))
229
-				->where($query->expr()->eq('key', $query->createNamedParameter($path)))
230
-				->andWhere($query->expr()->gt('lock', $query->createNamedParameter(0)));
231
-			$query->execute();
232
-		}
233
-	}
219
+        // we keep shared locks till the end of the request so we can re-use them
220
+        if ($type === self::LOCK_EXCLUSIVE) {
221
+            $this->connection->executeUpdate(
222
+                'UPDATE `*PREFIX*file_locks` SET `lock` = 0 WHERE `key` = ? AND `lock` = -1',
223
+                [$path]
224
+            );
225
+        } else if (!$this->cacheSharedLocks) {
226
+            $query = $this->connection->getQueryBuilder();
227
+            $query->update('file_locks')
228
+                ->set('lock', $query->func()->subtract('lock', $query->createNamedParameter(1)))
229
+                ->where($query->expr()->eq('key', $query->createNamedParameter($path)))
230
+                ->andWhere($query->expr()->gt('lock', $query->createNamedParameter(0)));
231
+            $query->execute();
232
+        }
233
+    }
234 234
 
235
-	/**
236
-	 * Change the type of an existing lock
237
-	 *
238
-	 * @param string $path
239
-	 * @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
240
-	 * @throws \OCP\Lock\LockedException
241
-	 */
242
-	public function changeLock(string $path, int $targetType) {
243
-		$expire = $this->getExpireTime();
244
-		if ($targetType === self::LOCK_SHARED) {
245
-			$result = $this->connection->executeUpdate(
246
-				'UPDATE `*PREFIX*file_locks` SET `lock` = 1, `ttl` = ? WHERE `key` = ? AND `lock` = -1',
247
-				[$expire, $path]
248
-			);
249
-		} else {
250
-			// since we only keep one shared lock in the db we need to check if we have more then one shared lock locally manually
251
-			if (isset($this->acquiredLocks['shared'][$path]) && $this->acquiredLocks['shared'][$path] > 1) {
252
-				throw new LockedException($path);
253
-			}
254
-			$result = $this->connection->executeUpdate(
255
-				'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 1',
256
-				[$expire, $path]
257
-			);
258
-		}
259
-		if ($result !== 1) {
260
-			throw new LockedException($path);
261
-		}
262
-		$this->markChange($path, $targetType);
263
-	}
235
+    /**
236
+     * Change the type of an existing lock
237
+     *
238
+     * @param string $path
239
+     * @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
240
+     * @throws \OCP\Lock\LockedException
241
+     */
242
+    public function changeLock(string $path, int $targetType) {
243
+        $expire = $this->getExpireTime();
244
+        if ($targetType === self::LOCK_SHARED) {
245
+            $result = $this->connection->executeUpdate(
246
+                'UPDATE `*PREFIX*file_locks` SET `lock` = 1, `ttl` = ? WHERE `key` = ? AND `lock` = -1',
247
+                [$expire, $path]
248
+            );
249
+        } else {
250
+            // since we only keep one shared lock in the db we need to check if we have more then one shared lock locally manually
251
+            if (isset($this->acquiredLocks['shared'][$path]) && $this->acquiredLocks['shared'][$path] > 1) {
252
+                throw new LockedException($path);
253
+            }
254
+            $result = $this->connection->executeUpdate(
255
+                'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 1',
256
+                [$expire, $path]
257
+            );
258
+        }
259
+        if ($result !== 1) {
260
+            throw new LockedException($path);
261
+        }
262
+        $this->markChange($path, $targetType);
263
+    }
264 264
 
265
-	/**
266
-	 * cleanup empty locks
267
-	 */
268
-	public function cleanExpiredLocks() {
269
-		$expire = $this->timeFactory->getTime();
270
-		try {
271
-			$this->connection->executeUpdate(
272
-				'DELETE FROM `*PREFIX*file_locks` WHERE `ttl` < ?',
273
-				[$expire]
274
-			);
275
-		} catch (\Exception $e) {
276
-			// If the table is missing, the clean up was successful
277
-			if ($this->connection->tableExists('file_locks')) {
278
-				throw $e;
279
-			}
280
-		}
281
-	}
265
+    /**
266
+     * cleanup empty locks
267
+     */
268
+    public function cleanExpiredLocks() {
269
+        $expire = $this->timeFactory->getTime();
270
+        try {
271
+            $this->connection->executeUpdate(
272
+                'DELETE FROM `*PREFIX*file_locks` WHERE `ttl` < ?',
273
+                [$expire]
274
+            );
275
+        } catch (\Exception $e) {
276
+            // If the table is missing, the clean up was successful
277
+            if ($this->connection->tableExists('file_locks')) {
278
+                throw $e;
279
+            }
280
+        }
281
+    }
282 282
 
283
-	/**
284
-	 * release all lock acquired by this instance which were marked using the mark* methods
285
-	 *
286
-	 * @suppress SqlInjectionChecker
287
-	 */
288
-	public function releaseAll() {
289
-		parent::releaseAll();
283
+    /**
284
+     * release all lock acquired by this instance which were marked using the mark* methods
285
+     *
286
+     * @suppress SqlInjectionChecker
287
+     */
288
+    public function releaseAll() {
289
+        parent::releaseAll();
290 290
 
291
-		if (!$this->cacheSharedLocks) {
292
-			return;
293
-		}
294
-		// since we keep shared locks we need to manually clean those
295
-		$lockedPaths = array_keys($this->sharedLocks);
296
-		$lockedPaths = array_filter($lockedPaths, function ($path) {
297
-			return $this->sharedLocks[$path];
298
-		});
291
+        if (!$this->cacheSharedLocks) {
292
+            return;
293
+        }
294
+        // since we keep shared locks we need to manually clean those
295
+        $lockedPaths = array_keys($this->sharedLocks);
296
+        $lockedPaths = array_filter($lockedPaths, function ($path) {
297
+            return $this->sharedLocks[$path];
298
+        });
299 299
 
300
-		$chunkedPaths = array_chunk($lockedPaths, 100);
300
+        $chunkedPaths = array_chunk($lockedPaths, 100);
301 301
 
302
-		foreach ($chunkedPaths as $chunk) {
303
-			$builder = $this->connection->getQueryBuilder();
302
+        foreach ($chunkedPaths as $chunk) {
303
+            $builder = $this->connection->getQueryBuilder();
304 304
 
305
-			$query = $builder->update('file_locks')
306
-				->set('lock', $builder->createFunction('`lock` -1'))
307
-				->where($builder->expr()->in('key', $builder->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY)))
308
-				->andWhere($builder->expr()->gt('lock', new Literal(0)));
305
+            $query = $builder->update('file_locks')
306
+                ->set('lock', $builder->createFunction('`lock` -1'))
307
+                ->where($builder->expr()->in('key', $builder->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY)))
308
+                ->andWhere($builder->expr()->gt('lock', new Literal(0)));
309 309
 
310
-			$query->execute();
311
-		}
312
-	}
310
+            $query->execute();
311
+        }
312
+    }
313 313
 }
Please login to merge, or discard this patch.