File: sqlite_database_vfs_file_set.cc

package info (click to toggle)
chromium 146.0.7680.153-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,057,156 kB
  • sloc: cpp: 36,426,539; ansic: 7,626,206; javascript: 3,599,825; python: 1,658,592; xml: 842,302; asm: 722,011; pascal: 186,153; sh: 88,976; perl: 88,684; objc: 79,984; sql: 60,492; cs: 42,470; fortran: 24,101; makefile: 21,141; tcl: 15,277; php: 14,022; yacc: 9,154; ruby: 7,553; awk: 3,720; lisp: 3,233; lex: 1,328; ada: 727; jsp: 228; sed: 36
file content (152 lines) | stat: -rw-r--r-- 5,350 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/sqlite_vfs/sqlite_database_vfs_file_set.h"

#include <atomic>
#include <memory>
#include <string_view>
#include <utility>

#include "base/check.h"
#include "base/check_op.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/memory/writable_shared_memory_region.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "components/sqlite_vfs/file_type.h"
#include "components/sqlite_vfs/pending_file_set.h"
#include "components/sqlite_vfs/sandboxed_file.h"
#include "sql/database.h"

namespace {

std::atomic<uint64_t> g_file_set_id_generator(0);

// The base name of the virtual database files served by a file set.
constexpr base::FilePath::StringViewType kDbFileName =
    FILE_PATH_LITERAL("data");

}  // namespace

namespace sqlite_vfs {

// static
std::optional<SqliteVfsFileSet> SqliteVfsFileSet::Bind(
    Client client,
    PendingFileSet pending_file_set) {
  // Write-ahead logging requires single connection.
  CHECK(!pending_file_set.wal_file.IsValid() ||
        !pending_file_set.shared_lock.IsValid());
  // Write-ahead logging requires read-write access.
  CHECK(!pending_file_set.wal_file.IsValid() || pending_file_set.read_write);

  base::WritableSharedMemoryMapping mapped_shared_lock;
  if (pending_file_set.shared_lock.IsValid()) {
    mapped_shared_lock = pending_file_set.shared_lock.Map();
    if (!mapped_shared_lock.IsValid()) {
      return std::nullopt;  // Failed to map the shared lock.
    }
  }

  const auto access_rights = pending_file_set.read_write
                                 ? SandboxedFile::AccessRights::kReadWrite
                                 : SandboxedFile::AccessRights::kReadOnly;

  auto db_file = std::make_unique<SandboxedFile>(
      client, FileType::kMainDb, std::move(pending_file_set.db_file),
      access_rights, std::move(mapped_shared_lock));
  auto journal_file = std::make_unique<SandboxedFile>(
      client, FileType::kMainJournal, std::move(pending_file_set.journal_file),
      access_rights);
  std::unique_ptr<SandboxedFile> wal_file;
  if (pending_file_set.wal_file.IsValid()) {
    wal_file = std::make_unique<SandboxedFile>(
        client, FileType::kWal, std::move(pending_file_set.wal_file),
        access_rights);
  }
  return SqliteVfsFileSet(std::move(db_file), std::move(journal_file),
                          std::move(wal_file),
                          std::move(pending_file_set.shared_lock));
}

SqliteVfsFileSet::SqliteVfsFileSet(
    std::unique_ptr<SandboxedFile> db_file,
    std::unique_ptr<SandboxedFile> journal_file,
    std::unique_ptr<SandboxedFile> wal_journal_file,
    base::UnsafeSharedMemoryRegion shared_lock)
    : shared_lock_(std::move(shared_lock)),
      db_file_(std::move(db_file)),
      journal_file_(std::move(journal_file)),
      wal_journal_file_(std::move(wal_journal_file)),
      virtual_fs_path_(base::FilePath::FromASCII(
          base::NumberToString(g_file_set_id_generator.fetch_add(1)))),
      read_only_(db_file_->access_rights() ==
                 SandboxedFile::AccessRights::kReadOnly) {
  // It makes no sense to have one file writeable and not the other(s).
  CHECK_EQ(db_file_->access_rights(), journal_file_->access_rights());
  if (wal_journal_file_) {
    CHECK_EQ(db_file_->access_rights(), wal_journal_file_->access_rights());
  }
  // Write-ahead logging requires single connection.
  CHECK(!wal_journal_file_ || !shared_lock_.IsValid());
  // Write-ahead logging requires read-write access.
  CHECK(!wal_journal_file_ ||
        db_file_->access_rights() == SandboxedFile::AccessRights::kReadWrite);
}

SqliteVfsFileSet::SqliteVfsFileSet(SqliteVfsFileSet&& other) = default;
SqliteVfsFileSet& SqliteVfsFileSet::operator=(SqliteVfsFileSet&& other) =
    default;
SqliteVfsFileSet::~SqliteVfsFileSet() = default;

base::FilePath SqliteVfsFileSet::GetDbVirtualFilePath() const {
  return virtual_fs_path_.Append(kDbFileName);
}

base::FilePath SqliteVfsFileSet::GetJournalVirtualFilePath() const {
  return sql::Database::JournalPath(GetDbVirtualFilePath());
}

base::FilePath SqliteVfsFileSet::GetWalJournalVirtualFilePath() const {
  return sql::Database::WriteAheadLogPath(GetDbVirtualFilePath());
}

// static
std::string_view SqliteVfsFileSet::GetVirtualFileHistogramVariant(
    const base::FilePath& virtual_file_path) {
  auto base_name = virtual_file_path.BaseName();
  if (base_name.value() == kDbFileName) {
    return "DbFile";
  }
  auto db_path = base::FilePath(kDbFileName);
  if (base_name == sql::Database::JournalPath(db_path)) {
    return "JournalFile";
  }
  if (base_name == sql::Database::WriteAheadLogPath(db_path)) {
    return "WalJournalFile";
  }
  NOTREACHED();
}

const base::File& SqliteVfsFileSet::GetDbFile() const {
  return db_file_->GetFile();
}

const base::File& SqliteVfsFileSet::GetJournalFile() const {
  return journal_file_->GetFile();
}

const base::File& SqliteVfsFileSet::GetWalJournalFile() const {
  CHECK(wal_journal_mode());
  return wal_journal_file_->GetFile();
}

LockState SqliteVfsFileSet::Abandon() {
  return db_file_->Abandon();
}

}  // namespace sqlite_vfs