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