Completed
Pull Request — master (#9203)
by Morris
44:09 queued 29:08
created
lib/private/Lock/DBLockingProvider.php 1 patch
Indentation   +246 added lines, -246 removed lines patch added patch discarded remove patch
@@ -38,273 +38,273 @@
 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
-	public function releaseLock(string $path, int $type) {
215
-		$this->markRelease($path, $type);
210
+    /**
211
+     * @param string $path
212
+     * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
213
+     */
214
+    public function releaseLock(string $path, int $type) {
215
+        $this->markRelease($path, $type);
216 216
 
217
-		// we keep shared locks till the end of the request so we can re-use them
218
-		if ($type === self::LOCK_EXCLUSIVE) {
219
-			$this->connection->executeUpdate(
220
-				'UPDATE `*PREFIX*file_locks` SET `lock` = 0 WHERE `key` = ? AND `lock` = -1',
221
-				[$path]
222
-			);
223
-		} else if (!$this->cacheSharedLocks) {
224
-			$query = $this->connection->getQueryBuilder();
225
-			$query->update('file_locks')
226
-				->set('lock', $query->func()->subtract('lock', $query->createNamedParameter(1)))
227
-				->where($query->expr()->eq('key', $query->createNamedParameter($path)))
228
-				->andWhere($query->expr()->gt('lock', $query->createNamedParameter(0)));
229
-			$query->execute();
230
-		}
231
-	}
217
+        // we keep shared locks till the end of the request so we can re-use them
218
+        if ($type === self::LOCK_EXCLUSIVE) {
219
+            $this->connection->executeUpdate(
220
+                'UPDATE `*PREFIX*file_locks` SET `lock` = 0 WHERE `key` = ? AND `lock` = -1',
221
+                [$path]
222
+            );
223
+        } else if (!$this->cacheSharedLocks) {
224
+            $query = $this->connection->getQueryBuilder();
225
+            $query->update('file_locks')
226
+                ->set('lock', $query->func()->subtract('lock', $query->createNamedParameter(1)))
227
+                ->where($query->expr()->eq('key', $query->createNamedParameter($path)))
228
+                ->andWhere($query->expr()->gt('lock', $query->createNamedParameter(0)));
229
+            $query->execute();
230
+        }
231
+    }
232 232
 
233
-	/**
234
-	 * Change the type of an existing lock
235
-	 *
236
-	 * @param string $path
237
-	 * @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
238
-	 * @throws \OCP\Lock\LockedException
239
-	 */
240
-	public function changeLock(string $path, int $targetType) {
241
-		$expire = $this->getExpireTime();
242
-		if ($targetType === self::LOCK_SHARED) {
243
-			$result = $this->connection->executeUpdate(
244
-				'UPDATE `*PREFIX*file_locks` SET `lock` = 1, `ttl` = ? WHERE `key` = ? AND `lock` = -1',
245
-				[$expire, $path]
246
-			);
247
-		} else {
248
-			// since we only keep one shared lock in the db we need to check if we have more then one shared lock locally manually
249
-			if (isset($this->acquiredLocks['shared'][$path]) && $this->acquiredLocks['shared'][$path] > 1) {
250
-				throw new LockedException($path);
251
-			}
252
-			$result = $this->connection->executeUpdate(
253
-				'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 1',
254
-				[$expire, $path]
255
-			);
256
-		}
257
-		if ($result !== 1) {
258
-			throw new LockedException($path);
259
-		}
260
-		$this->markChange($path, $targetType);
261
-	}
233
+    /**
234
+     * Change the type of an existing lock
235
+     *
236
+     * @param string $path
237
+     * @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
238
+     * @throws \OCP\Lock\LockedException
239
+     */
240
+    public function changeLock(string $path, int $targetType) {
241
+        $expire = $this->getExpireTime();
242
+        if ($targetType === self::LOCK_SHARED) {
243
+            $result = $this->connection->executeUpdate(
244
+                'UPDATE `*PREFIX*file_locks` SET `lock` = 1, `ttl` = ? WHERE `key` = ? AND `lock` = -1',
245
+                [$expire, $path]
246
+            );
247
+        } else {
248
+            // since we only keep one shared lock in the db we need to check if we have more then one shared lock locally manually
249
+            if (isset($this->acquiredLocks['shared'][$path]) && $this->acquiredLocks['shared'][$path] > 1) {
250
+                throw new LockedException($path);
251
+            }
252
+            $result = $this->connection->executeUpdate(
253
+                'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 1',
254
+                [$expire, $path]
255
+            );
256
+        }
257
+        if ($result !== 1) {
258
+            throw new LockedException($path);
259
+        }
260
+        $this->markChange($path, $targetType);
261
+    }
262 262
 
263
-	/**
264
-	 * cleanup empty locks
265
-	 */
266
-	public function cleanExpiredLocks() {
267
-		$expire = $this->timeFactory->getTime();
268
-		try {
269
-			$this->connection->executeUpdate(
270
-				'DELETE FROM `*PREFIX*file_locks` WHERE `ttl` < ?',
271
-				[$expire]
272
-			);
273
-		} catch (\Exception $e) {
274
-			// If the table is missing, the clean up was successful
275
-			if ($this->connection->tableExists('file_locks')) {
276
-				throw $e;
277
-			}
278
-		}
279
-	}
263
+    /**
264
+     * cleanup empty locks
265
+     */
266
+    public function cleanExpiredLocks() {
267
+        $expire = $this->timeFactory->getTime();
268
+        try {
269
+            $this->connection->executeUpdate(
270
+                'DELETE FROM `*PREFIX*file_locks` WHERE `ttl` < ?',
271
+                [$expire]
272
+            );
273
+        } catch (\Exception $e) {
274
+            // If the table is missing, the clean up was successful
275
+            if ($this->connection->tableExists('file_locks')) {
276
+                throw $e;
277
+            }
278
+        }
279
+    }
280 280
 
281
-	/**
282
-	 * release all lock acquired by this instance which were marked using the mark* methods
283
-	 *
284
-	 */
285
-	public function releaseAll() {
286
-		parent::releaseAll();
281
+    /**
282
+     * release all lock acquired by this instance which were marked using the mark* methods
283
+     *
284
+     */
285
+    public function releaseAll() {
286
+        parent::releaseAll();
287 287
 
288
-		if (!$this->cacheSharedLocks) {
289
-			return;
290
-		}
291
-		// since we keep shared locks we need to manually clean those
292
-		$lockedPaths = array_keys($this->sharedLocks);
293
-		$lockedPaths = array_filter($lockedPaths, function ($path) {
294
-			return $this->sharedLocks[$path];
295
-		});
288
+        if (!$this->cacheSharedLocks) {
289
+            return;
290
+        }
291
+        // since we keep shared locks we need to manually clean those
292
+        $lockedPaths = array_keys($this->sharedLocks);
293
+        $lockedPaths = array_filter($lockedPaths, function ($path) {
294
+            return $this->sharedLocks[$path];
295
+        });
296 296
 
297
-		$chunkedPaths = array_chunk($lockedPaths, 100);
297
+        $chunkedPaths = array_chunk($lockedPaths, 100);
298 298
 
299
-		foreach ($chunkedPaths as $chunk) {
300
-			$builder = $this->connection->getQueryBuilder();
299
+        foreach ($chunkedPaths as $chunk) {
300
+            $builder = $this->connection->getQueryBuilder();
301 301
 
302
-			$query = $builder->update('file_locks')
303
-				->set('lock', $builder->createFunction('`lock` -1'))
304
-				->where($builder->expr()->in('key', $builder->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY)))
305
-				->andWhere($builder->expr()->gt('lock', new Literal(0)));
302
+            $query = $builder->update('file_locks')
303
+                ->set('lock', $builder->createFunction('`lock` -1'))
304
+                ->where($builder->expr()->in('key', $builder->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY)))
305
+                ->andWhere($builder->expr()->gt('lock', new Literal(0)));
306 306
 
307
-			$query->execute();
308
-		}
309
-	}
307
+            $query->execute();
308
+        }
309
+    }
310 310
 }
Please login to merge, or discard this patch.