/*------------------------------------------------------------------------------* * Architecture & Implementation of DBMS * *------------------------------------------------------------------------------* * Copyright 2022 Databases and Information Systems Group TU Dortmund * * Visit us at * * http://dbis.cs.tu-dortmund.de/cms/en/home/ * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * * OTHER DEALINGS IN THE SOFTWARE. * * * * Authors: * * Maximilian Berens * * Roland Kühn * * Jan Mühlig * *------------------------------------------------------------------------------* */ #pragma once #include "timestamp.h" #include #include #include namespace beedb::concurrency { /** * Information about a tuple, stored in front of the data on a page. * The information contains begin and end timestamp of the data and * also a pointer (in form of a record identifier) to the "original" * record. * The original record is the record placed in the table space while * versioned records are stored in the time travel space. */ class Metadata { public: explicit Metadata(const timestamp begin_timestamp) : _begin_timestamp(begin_timestamp), _end_timestamp(timestamp::make_infinity()) { } Metadata(const storage::RecordIdentifier original_record_identifier, const timestamp begin_timestamp) : _original_record_identifier(original_record_identifier), _begin_timestamp(begin_timestamp), _end_timestamp(timestamp::make_infinity()) { } Metadata(const Metadata &other) : _original_record_identifier(other._original_record_identifier), _begin_timestamp(timestamp::make_infinity()), _end_timestamp(timestamp::make_infinity()) { _begin_timestamp.store(other._begin_timestamp.load()); _end_timestamp.store(other._end_timestamp.load()); _next_in_version_chain = other._next_in_version_chain; } ~Metadata() = default; /** * @return Timestamp the related record was created. */ [[nodiscard]] timestamp begin_timestamp() const { return _begin_timestamp.load(); } /** * @return Timestamp the related record was removed * or overridden by an update. */ [[nodiscard]] timestamp end_timestamp() const { return _end_timestamp.load(); } /** * @return Pointer to the next record in the version chain. */ [[nodiscard]] storage::RecordIdentifier next_in_version_chain() const { return _next_in_version_chain; } /** * Set the creation timestamp. * @param timestamp Timestamp the related records gets alive. */ void begin_timestamp(const timestamp timestamp) { _begin_timestamp.store(timestamp); } /** * Tries to set the timestamp but if and only if * the timestamp holds the value given in the old_timestamp * argument. * @param old_timestamp Expected timestamp. * @param timestamp New timestamp. * @return True, if the timestamp could be set. */ bool try_begin_timestamp(timestamp old_timestamp, const timestamp timestamp) { return _begin_timestamp.compare_exchange_strong(old_timestamp, timestamp); } /** * Updates the end timestamp. * @param timestamp Timestamp the record ends. */ void end_timestamp(const timestamp timestamp) { _end_timestamp.store(timestamp); } /** * Tries to set the timestamp but if and only if * the timestamp holds the value given in the old_timestamp * argument. * @param old_timestamp Expected timestamp. * @param timestamp New timestamp. * @return True, if the timestamp could be set. */ bool try_end_timestamp(timestamp old_timestamp, const timestamp timestamp) { return _end_timestamp.compare_exchange_strong(old_timestamp, timestamp); } /** * Update the pointer to the next version in history. * @param next Pointer to the next version. */ void next_in_version_chain(const storage::RecordIdentifier next) { _next_in_version_chain = next; } /** * @return Pointer to the current version in the table space. */ [[nodiscard]] storage::RecordIdentifier original_record_identifier() const { return _original_record_identifier; } private: // Pointer to the record in the table space. storage::RecordIdentifier _original_record_identifier; // Timestamp the record begins living. std::atomic _begin_timestamp; // Timestamp the record dies. std::atomic _end_timestamp; // Pointer to the next record in version chain. storage::RecordIdentifier _next_in_version_chain; }; } // namespace beedb::concurrency