18 #ifndef PSTORE_CORE_DATABASE_HPP 19 #define PSTORE_CORE_DATABASE_HPP 24 #include "pstore/core/storage.hpp" 27 #include "pstore/support/head_revision.hpp" 42 enum class access_mode { read_only, writable, writeable_no_create };
50 explicit database (std::string
const &
path, access_mode am,
51 bool access_tick_enabled =
true);
55 template <
typename File>
57 std::unique_ptr<system_page_size_interface> && page_size,
58 std::unique_ptr<region::factory> && region_factory,
59 bool access_tick_enabled =
true);
61 template <
typename File>
62 explicit database (std::shared_ptr<File> file,
bool access_tick_enabled =
true)
63 :
database (file, std::make_unique<system_page_size> (),
64 region::get_factory (file, storage::full_region_size,
65 storage::min_region_size),
66 access_tick_enabled) {}
80 std::uint64_t
size () const noexcept {
return size_.logical_size (); }
83 std::string
path ()
const {
return storage_.file ()->path (); }
96 void sync (
unsigned revision = head_revision);
108 static constexpr
bool small_files_enabled () noexcept {
109 return region::small_files_enabled ();
112 std::unique_lock<file::range_lock> * upgrade_to_write_lock ();
113 std::time_t latest_time ()
const {
114 auto lt = this->
file ()->latest_time ();
116 lt = std::max (lt, this->get_shared ()->time.load ());
120 bool is_writable ()
const noexcept {
return storage_.file ()->is_writable (); }
129 return this->
get (addr,
size,
true ,
false );
136 template <
typename T,
137 typename =
typename std::enable_if<std::is_standard_layout<T>::value>::type>
139 if (ex.
addr.to_address ().absolute () %
alignof (T) != 0) {
140 raise (error_code::bad_alignment);
145 return std::static_pointer_cast<T
const> (this->
getro (ex.
addr.to_address (), ex.
size));
153 template <
typename T,
154 typename =
typename std::enable_if<std::is_standard_layout<T>::value>::type>
156 return this->
getro (addr, std::size_t{1});
165 template <
typename T,
166 typename =
typename std::enable_if<std::is_standard_layout<T>::value>::type>
168 std::size_t
const elements)
const {
169 if (addr.to_address ().absolute () %
alignof (T) != 0) {
170 raise (error_code::bad_alignment);
172 return std::static_pointer_cast<T
const> (
173 this->
getro (addr.to_address (),
sizeof (T) * elements));
190 return std::const_pointer_cast<
void> (
191 this->
get (addr,
size,
true ,
true ));
198 template <
typename T,
199 typename =
typename std::enable_if<std::is_standard_layout<T>::value>::type>
201 if (ex.
addr.to_address ().absolute () %
alignof (T) != 0) {
202 raise (error_code::bad_alignment);
207 return std::static_pointer_cast<T> (this->
getrw (ex.
addr.to_address (), ex.
size));
214 template <
typename T,
215 typename =
typename std::enable_if<std::is_standard_layout<T>::value>::type>
217 return this->getrw<T> (addr, std::size_t{1});
225 template <
typename T,
226 typename =
typename std::enable_if<std::is_standard_layout<T>::value>::type>
228 if (addr.to_address ().absolute () %
alignof (T) != 0) {
229 raise (error_code::bad_alignment);
231 return std::static_pointer_cast<T> (
232 this->
getrw (addr.to_address (),
sizeof (T) * elements));
237 virtual auto get (
address addr, std::size_t
size,
bool initialized,
bool writable)
const 238 -> std::shared_ptr<void const>;
241 enum class vacuum_mode {
246 void set_vacuum_mode (vacuum_mode
const mode) noexcept { vacuum_mode_ = mode; }
247 vacuum_mode get_vacuum_mode ()
const noexcept {
return vacuum_mode_; }
257 header const & get_header ()
const noexcept {
return *header_; }
271 PSTORE_ASSERT (sync_name_.length () > 0);
275 std::string shared_memory_name ()
const {
return this->
get_sync_name () +
".pst"; }
292 virtual void truncate (std::uint64_t size);
298 void protect (
address const first,
address const last) { storage_.protect (first, last); }
307 void set_id (
uuid const &
id) noexcept { header_->set_id (
id); }
309 shared const * get_shared ()
const;
317 std::shared_ptr<index::index_base> &
319 return indices_[
static_cast<std::underlying_type<decltype (which)>::type
> (which)];
321 std::shared_ptr<trailer const> get_footer ()
const {
322 return this->
getro (this->footer_pos ());
327 std::shared_ptr<header> header_;
329 std::unique_lock<file::range_lock> lock_;
331 vacuum_mode vacuum_mode_ = vacuum_mode::disabled;
332 bool modified_ =
false;
333 bool closed_ =
false;
345 sizes () noexcept =
default;
347 : footer_pos_{footer_pos}
348 , logical_{footer_pos_.absolute () +
sizeof (
trailer)} {}
351 std::uint64_t logical_size ()
const noexcept {
return logical_; }
354 PSTORE_ASSERT (new_footer_pos.absolute () >= leader_size);
355 footer_pos_ = new_footer_pos;
356 logical_ = std::max (logical_, footer_pos_.absolute () +
sizeof (
trailer));
359 void update_logical_size (std::uint64_t
const new_logical_size) noexcept {
360 PSTORE_ASSERT (new_logical_size >= footer_pos_.absolute () +
sizeof (
trailer));
361 logical_ = std::max (logical_, new_logical_size);
364 void truncate_logical_size (std::uint64_t
const new_logical_size) noexcept {
365 PSTORE_ASSERT (new_logical_size >= footer_pos_.absolute () +
sizeof (
trailer));
366 logical_ = new_logical_size;
373 std::uint64_t logical_ = 0;
377 mutable std::array<std::shared_ptr<index::index_base>,
378 static_cast<unsigned> (trailer::indices::last)>
380 std::string sync_name_;
381 static constexpr
auto const sync_name_length = std::size_t{20};
385 std::shared_ptr<heartbeat> heartbeat_;
389 void clear_index_cache ();
392 address first_writable_address ()
const;
398 auto get_spanning (
address addr, std::size_t size,
bool initialized,
bool writable)
const 399 -> std::shared_ptr<void const>;
403 template <
typename File>
406 static std::string build_sync_name (
header const &
header);
411 void map_bytes (std::uint64_t new_size);
422 static auto open (std::string
const & path, access_mode am)
423 -> std::shared_ptr<file::file_handle>;
427 void finish_init (
bool access_tick_enabled);
433 template <
typename File>
435 std::unique_ptr<system_page_size_interface> && page_size,
436 std::unique_ptr<region::factory> && region_factory,
437 bool const access_tick_enabled)
438 : storage_{std::move (file), std::move (page_size), std::move (region_factory)}
439 , size_{database::get_footer_pos (*
file)} {
441 this->finish_init (access_tick_enabled);
447 template <
typename File>
449 static_assert (std::is_base_of<file::file_base, File>::value,
450 "File type must be derived from file::file_base");
451 PSTORE_ASSERT (file.is_open ());
453 std::aligned_storage<sizeof (header), alignof (header)>::type header_storage{};
454 auto h =
reinterpret_cast<header *
> (&header_storage);
458 auto const dtor = [] (
header *
const p) { p->~header (); };
459 std::unique_ptr<header, decltype (dtor)>
deleter (h, dtor);
461 #if PSTORE_SIGNATURE_CHECKS_ENABLED 462 if (h->a.signature1 != header::file_signature1 ||
463 h->a.signature2 != header::file_signature2) {
464 raise (error_code::header_corrupt, file.path ());
467 if (h->a.header_size != sizeof (
class header) || h->a.version[0] != header::major_version ||
468 h->a.version[1] != header::minor_version) {
469 raise (error_code::header_version_mismatch, file.path ());
471 if (!h->is_valid ()) {
472 raise (pstore::error_code::header_corrupt, file.path ());
476 std::uint64_t
const footer_offset = result.absolute ();
477 std::uint64_t
const file_size = file.size ();
478 if (footer_offset < leader_size || file_size < leader_size +
sizeof (
trailer) ||
479 footer_offset > file_size -
sizeof (
trailer)) {
480 raise (error_code::header_corrupt, file.path ());
487 #endif // PSTORE_CORE_DATABASE_HPP Implements sstring_view, a class which is based on std::string_view but holds a pointer which may be ...
std::shared_ptr< index::index_base > & get_mutable_index(enum pstore::trailer::indices const which) const
Returns a pointer to an index base.
Definition: database.hpp:318
std::shared_ptr< T > getrw(typed_address< T > const addr, std::size_t const elements)
Returns a pointer to a mutable array of instances of type T.
Definition: database.hpp:227
typed_address< trailer > older_revision_footer_pos(unsigned revision) const
Returns the address of the footer of a specified revision.
Definition: database.cpp:147
std::shared_ptr< void const > getro(address const addr, std::size_t const size) const
Definition: database.hpp:128
typed_address< T > addr
The address of the data associated with this extent.
Definition: address.hpp:456
An extent is a contiguous area of storage reserved for a data BLOB, represented as a range...
Definition: address.hpp:441
Opens a shared memory object containing type Ty with the given name.
Definition: shared_memory.hpp:92
The transaction footer structure.
Definition: file_header.hpp:206
virtual void truncate(std::uint64_t size)
Definition: database.cpp:435
Definition: address.hpp:81
class storage const & storage() const noexcept
For unit testing.
Definition: database.hpp:251
std::string path() const
Returns the path of the file in which this database is contained.
Definition: database.hpp:83
posix::deleter deleter
The cross-platform name for the deleter class.
Definition: file_posix.hpp:54
file::file_base const * file() const
Returns the file in which this database is contained.
Definition: database.hpp:87
void sync(unsigned revision=head_revision)
Update to a specified revision of the data.
Definition: database.cpp:176
Definition: address.hpp:231
std::shared_ptr< T > getrw(extent< T > const &ex)
Loads a block of storage at the address and size given by ex.
Definition: database.hpp:200
std::shared_ptr< void > getrw(address const addr, std::size_t const size)
Load a block of data starting at address addr and of size bytes.
Definition: database.hpp:189
void set_new_footer(typed_address< trailer > new_footer_pos)
Call as part of completing a transaction.
Definition: database.cpp:452
A synchronization object that can be used to protect data in a file from being simultaneously accesse...
Definition: file.hpp:382
static bool crc_checks_enabled()
Returns true if CRC checks are enabled.
Definition: database.cpp:40
unsigned get_current_revision() const
Returns the generation number to which the database is synced.
Definition: database.hpp:262
std::uint64_t size
The size of the data associated with this extent.
Definition: address.hpp:461
Definition: storage.hpp:58
std::shared_ptr< T const > getro(typed_address< T > const addr, std::size_t const elements) const
Returns a pointer to a read-only array of instances of type T.
Definition: database.hpp:167
std::string get_sync_name() const
Returns the name of the store's synchronisation object.
Definition: database.hpp:270
Definition: nonpod2.cpp:40
std::uint64_t size() const noexcept
Returns the logical size of the data store.
Definition: database.hpp:80
std::shared_ptr< T const > getro(extent< T > const &ex) const
Load a block of data starting at the address and size specified by ex.
Definition: database.hpp:138
Definition: database.hpp:40
static void build_new_store(file::file_base &file)
Constructs the basic data store structures in an empty file.
Definition: database.cpp:248
std::shared_ptr< T > getrw(typed_address< T > addr)
Returns a pointer to a mutable instance of type T.
Definition: database.hpp:216
std::shared_ptr< T const > getro(typed_address< T > const addr) const
Returns a pointer to a immutable instance of type T.
Definition: database.hpp:155
virtual address allocate(std::uint64_t bytes, unsigned align)
Appends an amount of storage to the database.
Definition: database.cpp:403
Definition: vacuum_intf.hpp:43
The uuid class is used to represent Universally Unique Identifiers (UUID) as defined by RFC 4122...
Definition: uuid.hpp:40
An abstract file class. Provides the interface for file access.
Definition: file.hpp:176
database(std::string const &path, access_mode am, bool access_tick_enabled=true)
Creates a database instance give the path of the file to use.
Definition: database.cpp:61