blob: 7b2cd8155b4429d3c857be7b67c5ee47837886f8 [file] [log] [blame]
Sergey Ulanov7de7e9f2019-03-09 00:41:021// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "sql/vfs_wrapper_fuchsia.h"
6
7#include "base/containers/flat_set.h"
Hans Wennborg0cfbeb32020-04-20 19:07:448#include "base/logging.h"
Sergey Ulanov7de7e9f2019-03-09 00:41:029#include "base/no_destructor.h"
Fabrice de Gans-Riberi8a2d723a2021-02-18 22:56:4910#include "base/notreached.h"
Sergey Ulanov7de7e9f2019-03-09 00:41:0211#include "base/synchronization/lock.h"
12#include "base/thread_annotations.h"
13#include "sql/vfs_wrapper.h"
14
15namespace sql {
16
17namespace {
18
19// Singleton that stores locks state.
20class FuchsiaFileLockManager {
21 public:
22 FuchsiaFileLockManager() = default;
23
24 // Returns lock manager for the current process.
25 static FuchsiaFileLockManager* Instance() {
26 static base::NoDestructor<FuchsiaFileLockManager> lock_manager;
27 return lock_manager.get();
28 }
29
30 // Return true if the file was locked successfully.
31 bool Lock(const std::string& name) {
32 base::AutoLock lock(lock_);
33
34 if (locked_files_.find(name) != locked_files_.end()) {
35 DLOG(WARNING) << "File " << name
36 << " is being used concurrently by multiple consumers.";
37 return false;
38 }
39
40 locked_files_.insert(name);
41 return true;
42 }
43
44 void Unlock(const std::string& name) {
45 base::AutoLock lock(lock_);
46
47 size_t removed = locked_files_.erase(name);
48 DCHECK_EQ(removed, 1U);
49 }
50
51 bool IsLocked(const std::string& name) {
52 base::AutoLock lock(lock_);
53 return locked_files_.find(name) != locked_files_.end();
54 }
55
56 private:
57 ~FuchsiaFileLockManager() = delete;
58
59 base::Lock lock_;
60
61 // Set of all currently locked files.
62 base::flat_set<std::string> locked_files_ GUARDED_BY(lock_);
63};
64
65} // namespace
66
67int FuchsiaVfsLock(sqlite3_file* sqlite_file, int file_lock) {
68 DCHECK(file_lock == SQLITE_LOCK_SHARED || file_lock == SQLITE_LOCK_RESERVED ||
69 file_lock == SQLITE_LOCK_PENDING ||
70 file_lock == SQLITE_LOCK_EXCLUSIVE);
71
72 VfsFile* vfs_file = reinterpret_cast<VfsFile*>(sqlite_file);
73
74 if (vfs_file->lock_level == SQLITE_LOCK_NONE) {
75 if (!FuchsiaFileLockManager::Instance()->Lock(vfs_file->file_name))
76 return SQLITE_BUSY;
77 }
78
79 vfs_file->lock_level = file_lock;
80
81 return SQLITE_OK;
82}
83
84int FuchsiaVfsUnlock(sqlite3_file* sqlite_file, int file_lock) {
85 VfsFile* vfs_file = reinterpret_cast<VfsFile*>(sqlite_file);
86
87 if (file_lock == SQLITE_LOCK_NONE) {
88 if (vfs_file->lock_level != SQLITE_LOCK_NONE)
89 FuchsiaFileLockManager::Instance()->Unlock(vfs_file->file_name);
90 } else {
91 // Keep the file locked for the shared lock.
92 DCHECK(file_lock == SQLITE_LOCK_SHARED);
93 DCHECK(FuchsiaFileLockManager::Instance()->IsLocked(vfs_file->file_name));
94 }
95 vfs_file->lock_level = file_lock;
96
97 return SQLITE_OK;
98}
99
100int FuchsiaVfsCheckReservedLock(sqlite3_file* sqlite_file, int* result) {
101 VfsFile* vfs_file = reinterpret_cast<VfsFile*>(sqlite_file);
Fabrice de Gans-Riberi8a2d723a2021-02-18 22:56:49102 switch (vfs_file->lock_level) {
103 case SQLITE_LOCK_NONE:
104 case SQLITE_LOCK_SHARED:
105 *result = 0;
106 return SQLITE_OK;
107 case SQLITE_LOCK_RESERVED:
108 case SQLITE_LOCK_PENDING:
109 case SQLITE_LOCK_EXCLUSIVE:
110 *result = 1;
111 return SQLITE_OK;
112 default:
113 NOTREACHED();
114 return SQLITE_IOERR_CHECKRESERVEDLOCK;
115 }
Sergey Ulanov7de7e9f2019-03-09 00:41:02116}
117
118} // namespace sql