164 lines
5.8 KiB
C++
164 lines
5.8 KiB
C++
/*------------------------------------------------------------------------------*
|
|
* 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 <maximilian.berens@tu-dortmund.de> *
|
|
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
|
|
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
|
|
*------------------------------------------------------------------------------*
|
|
*/
|
|
|
|
#pragma once
|
|
#include "timestamp.h"
|
|
#include <atomic>
|
|
#include <storage/page.h>
|
|
#include <storage/record_identifier.h>
|
|
|
|
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<timestamp> _begin_timestamp;
|
|
|
|
// Timestamp the record dies.
|
|
std::atomic<timestamp> _end_timestamp;
|
|
|
|
// Pointer to the next record in version chain.
|
|
storage::RecordIdentifier _next_in_version_chain;
|
|
};
|
|
} // namespace beedb::concurrency
|