OmniSciDB  c1a53651b2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LockMgr.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "LockMgr/LegacyLockMgr.h"
20 #include "LockMgr/LockMgrImpl.h"
21 
22 #include <map>
23 #include <memory>
24 #include <string>
25 
26 #include "Catalog/Catalog.h"
28 #include "Shared/types.h"
29 
30 namespace lockmgr {
31 
38 class TableSchemaLockMgr : public TableLockMgrImpl<TableSchemaLockMgr> {
39  public:
41  static TableSchemaLockMgr table_lock_mgr;
42  return table_lock_mgr;
43  }
44 
45  private:
47  static inline constexpr std::string_view kind = "schema";
48 };
49 
56 class InsertDataLockMgr : public TableLockMgrImpl<InsertDataLockMgr> {
57  public:
59  static InsertDataLockMgr insert_data_lock_mgr;
60  return insert_data_lock_mgr;
61  }
62 
63  protected:
65  static inline constexpr std::string_view kind = "insert";
66 };
67 
76 class TableDataLockMgr : public TableLockMgrImpl<TableDataLockMgr> {
77  public:
79  static TableDataLockMgr data_lock_mgr;
80  return data_lock_mgr;
81  }
82 
83  protected:
85  static inline constexpr std::string_view kind = "data";
86 };
87 
88 template <typename LOCK_TYPE>
90  : public LockContainerImpl<const TableDescriptor*, LOCK_TYPE> {
91  static_assert(std::is_same<LOCK_TYPE, ReadLock>::value ||
92  std::is_same<LOCK_TYPE, WriteLock>::value);
93 
94  public:
95  TableSchemaLockContainer(const TableSchemaLockContainer&) = delete; // non-copyable
96 };
97 
100  const std::string& table_name,
101  const bool populate_fragmenter) {
102  auto td_postlock = cat.getMetadataForTable(table_name, populate_fragmenter);
103  if (td_prelock != td_postlock) {
104  if (td_postlock == nullptr) {
105  throw std::runtime_error("Table/View ID " + table_name + " for catalog " +
106  cat.getCurrentDB().dbName + " does not exist");
107  } else {
108  // This should be very unusual case where a table has moved
109  // read DROP, CREATE kind of pattern
110  // but kept same name
111  // it is not safe to proceed here as the locking was based on the old
112  // chunk attributes of the table, which could belong to a different table now
113  throw std::runtime_error("Table/View ID " + table_name + " for catalog " +
114  cat.getCurrentDB().dbName +
115  " changed whilst attempting to acquire table lock");
116  }
117  }
118 }
119 
120 template <>
122  : public LockContainerImpl<const TableDescriptor*, ReadLock> {
123  public:
125  const std::string& table_name,
126  const bool populate_fragmenter = true) {
127  VLOG(1) << "Acquiring Table Schema Read Lock for table: " << table_name;
128  auto lock = TableSchemaLockMgr::getReadLockForTable(cat, table_name);
130  cat.getMetadataForTable(table_name, populate_fragmenter), std::move(lock));
131  validate_table_descriptor_after_lock(ret(), cat, table_name, populate_fragmenter);
132  return ret;
133  }
134 
136  const int table_id) {
137  const auto table_name = cat.getTableName(table_id);
138  if (!table_name.has_value()) {
139  throw std::runtime_error("Table/View ID " + std::to_string(table_id) +
140  " for catalog " + cat.getCurrentDB().dbName +
141  " does not exist. Cannot aquire read lock");
142  }
143  return acquireTableDescriptor(cat, table_name.value());
144  }
145 
146  private:
148  : LockContainerImpl<const TableDescriptor*, ReadLock>(obj, std::move(lock)) {}
149 };
150 
151 template <>
153  : public LockContainerImpl<const TableDescriptor*, WriteLock> {
154  public:
156  const std::string& table_name,
157  const bool populate_fragmenter = true) {
158  VLOG(1) << "Acquiring Table Schema Write Lock for table: " << table_name;
159  auto lock = TableSchemaLockMgr::getWriteLockForTable(cat, table_name);
161  cat.getMetadataForTable(table_name, populate_fragmenter), std::move(lock));
162  validate_table_descriptor_after_lock(ret(), cat, table_name, populate_fragmenter);
163  return ret;
164  }
165 
167  const int table_id) {
168  const auto table_name = cat.getTableName(table_id);
169  if (!table_name.has_value()) {
170  throw std::runtime_error("Table/View ID " + std::to_string(table_id) +
171  " for catalog " + cat.getCurrentDB().dbName +
172  " does not exist. Cannot aquire write lock");
173  }
174  return acquireTableDescriptor(cat, table_name.value());
175  }
176 
177  private:
180 };
181 
182 template <typename LOCK_TYPE>
184  : public LockContainerImpl<const TableDescriptor*, LOCK_TYPE> {
185  static_assert(std::is_same<LOCK_TYPE, ReadLock>::value ||
186  std::is_same<LOCK_TYPE, WriteLock>::value);
187 
188  public:
189  TableDataLockContainer(const TableDataLockContainer&) = delete; // non-copyable
190 };
191 
192 template <>
194  : public LockContainerImpl<const TableDescriptor*, WriteLock> {
195  public:
196  static auto acquire(const int db_id, const TableDescriptor* td) {
197  CHECK(td);
198  ChunkKey chunk_key{db_id, td->tableId};
199  VLOG(1) << "Acquiring Table Data Write Lock for table: " << td->tableName;
202  }
203 
204  private:
207 };
208 
209 template <>
211  : public LockContainerImpl<const TableDescriptor*, ReadLock> {
212  public:
213  static auto acquire(const int db_id, const TableDescriptor* td) {
214  CHECK(td);
215  ChunkKey chunk_key{db_id, td->tableId};
216  VLOG(1) << "Acquiring Table Data Read Lock for table: " << td->tableName;
219  }
220 
221  private:
223  : LockContainerImpl<const TableDescriptor*, ReadLock>(obj, std::move(lock)) {}
224 };
225 
226 template <typename LOCK_TYPE>
228  : public LockContainerImpl<const TableDescriptor*, LOCK_TYPE> {
229  static_assert(std::is_same<LOCK_TYPE, ReadLock>::value ||
230  std::is_same<LOCK_TYPE, WriteLock>::value);
231 
232  public:
233  TableInsertLockContainer(const TableInsertLockContainer&) = delete; // non-copyable
234 };
235 
236 template <>
238  : public LockContainerImpl<const TableDescriptor*, WriteLock> {
239  public:
240  static auto acquire(const int db_id, const TableDescriptor* td) {
241  CHECK(td);
242  ChunkKey chunk_key{db_id, td->tableId};
243  VLOG(1) << "Acquiring Table Insert Write Lock for table: " << td->tableName;
246  }
247 
248  private:
251 };
252 
253 template <>
255  : public LockContainerImpl<const TableDescriptor*, ReadLock> {
256  public:
257  static auto acquire(const int db_id, const TableDescriptor* td) {
258  CHECK(td);
259  ChunkKey chunk_key{db_id, td->tableId};
260  VLOG(1) << "Acquiring Table Insert Read Lock for table: " << td->tableName;
263  }
264 
265  private:
267  : LockContainerImpl<const TableDescriptor*, ReadLock>(obj, std::move(lock)) {}
268 };
269 
271  std::vector<std::unique_ptr<lockmgr::AbstractLockContainer<const TableDescriptor*>>>;
272 
273 } // namespace lockmgr
std::vector< int > ChunkKey
Definition: types.h:36
std::vector< std::unique_ptr< lockmgr::AbstractLockContainer< const TableDescriptor * >>> LockedTableDescriptors
Definition: LockMgr.h:271
Locks protecting a physical table object returned from the catalog. Table Metadata Locks prevent inco...
Definition: LockMgr.h:38
static TableSchemaLockMgr & instance()
Definition: LockMgr.h:40
static constexpr std::string_view kind
Definition: LockMgr.h:65
std::string cat(Ts &&...args)
static auto acquireTableDescriptor(Catalog_Namespace::Catalog &cat, const std::string &table_name, const bool populate_fragmenter=true)
Definition: LockMgr.h:155
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:132
Locks protecting table data. Read queries take a read lock, while write queries (update, delete) obtain a write lock. Note that insert queries do not currently take a write lock (to allow concurrent inserts). Instead, insert queries obtain a write lock on the table metadata to allow existing read queries to finish (and block new ones) before flushing the inserted data to disk.
Definition: LockMgr.h:76
TableInsertLockContainer(const TableInsertLockContainer &)=delete
std::string tableName
static WriteLock getWriteLockForTable(const Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:225
static auto acquire(const int db_id, const TableDescriptor *td)
Definition: LockMgr.h:196
static auto acquireTableDescriptor(Catalog_Namespace::Catalog &cat, const int table_id)
Definition: LockMgr.h:166
static constexpr std::string_view kind
Definition: LockMgr.h:85
static TableDataLockMgr & instance()
Definition: LockMgr.h:78
std::string to_string(char const *&&v)
void validate_table_descriptor_after_lock(const TableDescriptor *td_prelock, const Catalog_Namespace::Catalog &cat, const std::string &table_name, const bool populate_fragmenter)
Definition: LockMgr.h:98
static auto acquire(const int db_id, const TableDescriptor *td)
Definition: LockMgr.h:213
This file contains the class specification and related data structures for Catalog.
const DBMetadata & getCurrentDB() const
Definition: Catalog.h:248
static auto acquireTableDescriptor(Catalog_Namespace::Catalog &cat, const std::string &table_name, const bool populate_fragmenter=true)
Definition: LockMgr.h:124
static auto acquireTableDescriptor(Catalog_Namespace::Catalog &cat, const int table_id)
Definition: LockMgr.h:135
TableDataLockContainer(const TableDataLockContainer &)=delete
static ReadLock getReadLockForTable(Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:238
#define CHECK(condition)
Definition: Logger.h:291
static constexpr std::string_view kind
Definition: LockMgr.h:47
std::optional< std::string > getTableName(int32_t table_id) const
Definition: Catalog.cpp:1964
TableSchemaLockContainer(const TableSchemaLockContainer &)=delete
static auto acquire(const int db_id, const TableDescriptor *td)
Definition: LockMgr.h:240
static InsertDataLockMgr & instance()
Definition: LockMgr.h:58
static auto acquire(const int db_id, const TableDescriptor *td)
Definition: LockMgr.h:257
const TableDescriptor * getMetadataForTable(const std::string &tableName, const bool populateFragmenter=true) const
Returns a pointer to a const TableDescriptor struct matching the provided tableName.
Prevents simultaneous inserts into the same table. To allow concurrent Insert/Select queries...
Definition: LockMgr.h:56
#define VLOG(n)
Definition: Logger.h:387