Coverage Report

Created: 2022-08-24 06:40

/src/duckdb/src/storage/storage_manager.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "duckdb/storage/storage_manager.hpp"
2
#include "duckdb/storage/checkpoint_manager.hpp"
3
#include "duckdb/storage/in_memory_block_manager.hpp"
4
#include "duckdb/storage/single_file_block_manager.hpp"
5
#include "duckdb/storage/object_cache.hpp"
6
7
#include "duckdb/catalog/catalog.hpp"
8
#include "duckdb/common/file_system.hpp"
9
#include "duckdb/main/database.hpp"
10
#include "duckdb/main/connection.hpp"
11
#include "duckdb/main/client_context.hpp"
12
#include "duckdb/function/function.hpp"
13
#include "duckdb/parser/parsed_data/create_schema_info.hpp"
14
#include "duckdb/transaction/transaction_manager.hpp"
15
#include "duckdb/common/serializer/buffered_file_reader.hpp"
16
17
namespace duckdb {
18
19
StorageManager::StorageManager(DatabaseInstance &db, string path, bool read_only)
20
10
    : db(db), path(move(path)), wal(db), read_only(read_only) {
21
10
}
22
23
10
StorageManager::~StorageManager() {
24
10
}
25
26
0
StorageManager &StorageManager::GetStorageManager(ClientContext &context) {
27
0
  return StorageManager::GetStorageManager(*context.db);
28
0
}
29
30
44
BufferManager &BufferManager::GetBufferManager(ClientContext &context) {
31
44
  return BufferManager::GetBufferManager(*context.db);
32
44
}
33
34
0
ObjectCache &ObjectCache::GetObjectCache(ClientContext &context) {
35
0
  return context.db->GetObjectCache();
36
0
}
37
38
0
bool ObjectCache::ObjectCacheEnabled(ClientContext &context) {
39
0
  return context.db->config.options.object_cache_enable;
40
0
}
41
42
60
bool StorageManager::InMemory() {
43
60
  return path.empty() || path == ":memory:";
44
60
}
45
46
10
void StorageManager::Initialize() {
47
10
  bool in_memory = InMemory();
48
10
  if (in_memory && read_only) {
49
0
    throw CatalogException("Cannot launch in-memory database in read-only mode!");
50
0
  }
51
10
  auto &config = DBConfig::GetConfig(db);
52
10
  auto &catalog = Catalog::GetCatalog(db);
53
10
  buffer_manager = make_unique<BufferManager>(db, config.options.temporary_directory, config.options.maximum_memory);
54
55
  // first initialize the base system catalogs
56
  // these are never written to the WAL
57
10
  Connection con(db);
58
10
  con.BeginTransaction();
59
60
  // create the default schema
61
10
  CreateSchemaInfo info;
62
10
  info.schema = DEFAULT_SCHEMA;
63
10
  info.internal = true;
64
10
  catalog.CreateSchema(*con.context, &info);
65
66
10
  if (config.options.initialize_default_database) {
67
    // initialize default functions
68
10
    BuiltinFunctions builtin(*con.context, catalog);
69
10
    builtin.Initialize();
70
10
  }
71
72
  // commit transactions
73
10
  con.Commit();
74
75
10
  if (!in_memory) {
76
    // create or load the database from disk, if not in-memory mode
77
0
    LoadDatabase();
78
10
  } else {
79
10
    block_manager = make_unique<InMemoryBlockManager>();
80
10
  }
81
10
}
82
83
0
void StorageManager::LoadDatabase() {
84
0
  string wal_path = path + ".wal";
85
0
  auto &fs = db.GetFileSystem();
86
0
  auto &config = db.config;
87
0
  bool truncate_wal = false;
88
  // first check if the database exists
89
0
  if (!fs.FileExists(path)) {
90
0
    if (read_only) {
91
0
      throw CatalogException("Cannot open database \"%s\" in read-only mode: database does not exist", path);
92
0
    }
93
    // check if the WAL exists
94
0
    if (fs.FileExists(wal_path)) {
95
      // WAL file exists but database file does not
96
      // remove the WAL
97
0
      fs.RemoveFile(wal_path);
98
0
    }
99
    // initialize the block manager while creating a new db file
100
0
    block_manager = make_unique<SingleFileBlockManager>(db, path, read_only, true, config.options.use_direct_io);
101
0
  } else {
102
    // initialize the block manager while loading the current db file
103
0
    auto sf_bm = make_unique<SingleFileBlockManager>(db, path, read_only, false, config.options.use_direct_io);
104
0
    auto sf = sf_bm.get();
105
0
    block_manager = move(sf_bm);
106
0
    sf->LoadFreeList();
107
108
    //! Load from storage
109
0
    CheckpointManager checkpointer(db);
110
0
    checkpointer.LoadFromStorage();
111
    // check if the WAL file exists
112
0
    if (fs.FileExists(wal_path)) {
113
      // replay the WAL
114
0
      truncate_wal = WriteAheadLog::Replay(db, wal_path);
115
0
    }
116
0
  }
117
  // initialize the WAL file
118
0
  if (!read_only) {
119
0
    wal.Initialize(wal_path);
120
0
    if (truncate_wal) {
121
0
      wal.Truncate(0);
122
0
    }
123
0
  }
124
0
}
125
126
0
void StorageManager::CreateCheckpoint(bool delete_wal, bool force_checkpoint) {
127
0
  if (InMemory() || read_only || !wal.initialized) {
128
0
    return;
129
0
  }
130
0
  if (wal.GetWALSize() > 0 || db.config.options.force_checkpoint || force_checkpoint) {
131
    // we only need to checkpoint if there is anything in the WAL
132
0
    CheckpointManager checkpointer(db);
133
0
    checkpointer.CreateCheckpoint();
134
0
  }
135
0
  if (delete_wal) {
136
0
    wal.Delete();
137
0
  }
138
0
}
139
140
} // namespace duckdb