1
0
Fork 0
arangodb/arangod/MMFiles/MMFilesDatafileHelper.h

323 lines
15 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGOD_MMFILES_MMFILES_DATAFILE_HELPER_H
#define ARANGOD_MMFILES_MMFILES_DATAFILE_HELPER_H 1
#include "Basics/Common.h"
#include "Basics/encoding.h"
#include "MMFiles/MMFilesDatafile.h"
namespace arangodb {
namespace MMFilesDatafileHelper {
////////////////////////////////////////////////////////////////////////////////
/// @brief bit mask for datafile ids (fids) that indicates whether a file is
/// a WAL file (bit set) or a datafile (bit not set)
////////////////////////////////////////////////////////////////////////////////
constexpr inline uint64_t WalFileBitmask() { return 0x8000000000000000ULL; }
////////////////////////////////////////////////////////////////////////////////
/// @brief maximal size of a marker
////////////////////////////////////////////////////////////////////////////////
constexpr inline uint32_t MaximalMarkerSize() {
return 2UL * 1024UL * 1024UL * 1024UL; // 2 GB
}
////////////////////////////////////////////////////////////////////////////////
/// @brief journal overhead
////////////////////////////////////////////////////////////////////////////////
constexpr inline uint32_t JournalOverhead() {
return sizeof(MMFilesDatafileHeaderMarker) + sizeof(MMFilesDatafileFooterMarker);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the 8-byte aligned size for the marker
////////////////////////////////////////////////////////////////////////////////
template <typename T>
static inline T AlignedMarkerSize(MMFilesMarker const* marker) {
size_t value = marker->getSize();
return static_cast<T>((value + 7) - ((value + 7) & 7));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific offset to the vpack payload
/// note that this function is also used to determine the base length of a
/// marker type
////////////////////////////////////////////////////////////////////////////////
static inline size_t VPackOffset(MMFilesMarkerType type) noexcept {
if (type == TRI_DF_MARKER_VPACK_DOCUMENT || type == TRI_DF_MARKER_VPACK_REMOVE) {
// VPack is located after transaction id
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tid_t);
}
if (type == TRI_DF_MARKER_VPACK_CREATE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_DROP_COLLECTION || type == TRI_DF_MARKER_VPACK_RENAME_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CHANGE_COLLECTION || type == TRI_DF_MARKER_VPACK_CREATE_INDEX ||
type == TRI_DF_MARKER_VPACK_DROP_INDEX || type == TRI_DF_MARKER_VPACK_CREATE_VIEW ||
type == TRI_DF_MARKER_VPACK_DROP_VIEW || type == TRI_DF_MARKER_VPACK_CHANGE_VIEW) {
// VPack is located after database id and collection id
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tick_t) + sizeof(TRI_voc_cid_t);
}
if (type == TRI_DF_MARKER_VPACK_CREATE_DATABASE || type == TRI_DF_MARKER_VPACK_DROP_DATABASE) {
// VPack is located after database id
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tick_t);
}
if (type == TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_COMMIT_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_ABORT_TRANSACTION) {
// these marker types do not have any VPack
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tick_t) + sizeof(TRI_voc_tid_t);
}
if (type == TRI_DF_MARKER_PROLOGUE) {
// this type does not have any VPack
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tick_t) + sizeof(TRI_voc_cid_t);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific database id offset
////////////////////////////////////////////////////////////////////////////////
static inline size_t DatabaseIdOffset(MMFilesMarkerType type) noexcept {
if (type == TRI_DF_MARKER_PROLOGUE || type == TRI_DF_MARKER_VPACK_CREATE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_DROP_COLLECTION || type == TRI_DF_MARKER_VPACK_RENAME_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CHANGE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CREATE_INDEX || type == TRI_DF_MARKER_VPACK_DROP_INDEX ||
type == TRI_DF_MARKER_VPACK_CREATE_VIEW || type == TRI_DF_MARKER_VPACK_DROP_VIEW ||
type == TRI_DF_MARKER_VPACK_CHANGE_VIEW || type == TRI_DF_MARKER_VPACK_CREATE_DATABASE ||
type == TRI_DF_MARKER_VPACK_DROP_DATABASE || type == TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_COMMIT_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_ABORT_TRANSACTION) {
return sizeof(MMFilesMarker);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific database id
////////////////////////////////////////////////////////////////////////////////
static inline TRI_voc_tick_t DatabaseId(MMFilesMarker const* marker) noexcept {
MMFilesMarkerType type = marker->getType();
if (type == TRI_DF_MARKER_PROLOGUE || type == TRI_DF_MARKER_VPACK_CREATE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_DROP_COLLECTION || type == TRI_DF_MARKER_VPACK_RENAME_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CHANGE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CREATE_INDEX || type == TRI_DF_MARKER_VPACK_DROP_INDEX ||
type == TRI_DF_MARKER_VPACK_CREATE_VIEW || type == TRI_DF_MARKER_VPACK_DROP_VIEW ||
type == TRI_DF_MARKER_VPACK_CHANGE_VIEW || type == TRI_DF_MARKER_VPACK_CREATE_DATABASE ||
type == TRI_DF_MARKER_VPACK_DROP_DATABASE || type == TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_COMMIT_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_ABORT_TRANSACTION) {
return encoding::readNumber<TRI_voc_tick_t>(reinterpret_cast<uint8_t const*>(marker) +
DatabaseIdOffset(type),
sizeof(TRI_voc_tick_t));
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific collection id offset
////////////////////////////////////////////////////////////////////////////////
static inline size_t CollectionIdOffset(MMFilesMarkerType type) noexcept {
if (type == TRI_DF_MARKER_PROLOGUE || type == TRI_DF_MARKER_VPACK_CREATE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_DROP_COLLECTION || type == TRI_DF_MARKER_VPACK_RENAME_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CHANGE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CREATE_INDEX || type == TRI_DF_MARKER_VPACK_DROP_INDEX) {
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tick_t);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific collection id
////////////////////////////////////////////////////////////////////////////////
static inline TRI_voc_tick_t CollectionId(MMFilesMarker const* marker) noexcept {
MMFilesMarkerType type = marker->getType();
if (type == TRI_DF_MARKER_PROLOGUE || type == TRI_DF_MARKER_VPACK_CREATE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_DROP_COLLECTION || type == TRI_DF_MARKER_VPACK_RENAME_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CHANGE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CREATE_INDEX || type == TRI_DF_MARKER_VPACK_DROP_INDEX) {
return encoding::readNumber<TRI_voc_cid_t>(reinterpret_cast<uint8_t const*>(marker) +
CollectionIdOffset(type),
sizeof(TRI_voc_cid_t));
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific view id offset
////////////////////////////////////////////////////////////////////////////////
static inline size_t ViewIdOffset(MMFilesMarkerType type) noexcept {
if (type == TRI_DF_MARKER_VPACK_CREATE_VIEW || type == TRI_DF_MARKER_VPACK_DROP_VIEW ||
type == TRI_DF_MARKER_VPACK_CHANGE_VIEW) {
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tick_t);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific view id
////////////////////////////////////////////////////////////////////////////////
static inline TRI_voc_tick_t ViewId(MMFilesMarker const* marker) noexcept {
MMFilesMarkerType type = marker->getType();
if (type == TRI_DF_MARKER_VPACK_CREATE_VIEW || type == TRI_DF_MARKER_VPACK_DROP_VIEW ||
type == TRI_DF_MARKER_VPACK_CHANGE_VIEW) {
return encoding::readNumber<TRI_voc_cid_t>(reinterpret_cast<uint8_t const*>(marker) +
ViewIdOffset(type),
sizeof(TRI_voc_cid_t));
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific transaction id offset
////////////////////////////////////////////////////////////////////////////////
static inline TRI_voc_tick_t TransactionIdOffset(MMFilesMarkerType type) noexcept {
if (type == TRI_DF_MARKER_VPACK_DOCUMENT || type == TRI_DF_MARKER_VPACK_REMOVE) {
return sizeof(MMFilesMarker);
}
if (type == TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_COMMIT_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_ABORT_TRANSACTION) {
return sizeof(MMFilesMarker) + sizeof(TRI_voc_tick_t);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific transaction id
////////////////////////////////////////////////////////////////////////////////
static inline TRI_voc_tick_t TransactionId(MMFilesMarker const* marker) noexcept {
MMFilesMarkerType type = marker->getType();
if (type == TRI_DF_MARKER_VPACK_DOCUMENT || type == TRI_DF_MARKER_VPACK_REMOVE ||
type == TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_COMMIT_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_ABORT_TRANSACTION) {
return encoding::readNumber<TRI_voc_tid_t>(reinterpret_cast<uint8_t const*>(marker) +
TransactionIdOffset(type),
sizeof(TRI_voc_tid_t));
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief initializes a marker, using user-defined tick
////////////////////////////////////////////////////////////////////////////////
static inline void InitMarker(MMFilesMarker* marker, MMFilesMarkerType type,
uint32_t size, TRI_voc_tick_t tick) {
TRI_ASSERT(marker != nullptr);
TRI_ASSERT(type > TRI_DF_MARKER_MIN && type < TRI_DF_MARKER_MAX);
TRI_ASSERT(size > 0);
marker->setSize(size);
marker->setTypeAndTick(type, tick);
marker->setCrc(0);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief initializes a marker, using tick 0
////////////////////////////////////////////////////////////////////////////////
static inline void InitMarker(MMFilesMarker* marker, MMFilesMarkerType type, uint32_t size) {
InitMarker(marker, type, size, 0); // always use tick 0
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a header marker
////////////////////////////////////////////////////////////////////////////////
static inline MMFilesDatafileHeaderMarker CreateHeaderMarker(uint32_t maximalSize,
TRI_voc_tick_t fid) {
static_assert(sizeof(TRI_voc_tick_t) == sizeof(TRI_voc_fid_t),
"invalid tick/fid sizes");
MMFilesDatafileHeaderMarker header;
InitMarker(reinterpret_cast<MMFilesMarker*>(&header), TRI_DF_MARKER_HEADER,
sizeof(MMFilesDatafileHeaderMarker), fid);
header._version = TRI_DF_VERSION;
header._maximalSize = maximalSize;
header._fid = fid;
return header;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a prologue marker
////////////////////////////////////////////////////////////////////////////////
static inline MMFilesPrologueMarker CreatePrologueMarker(TRI_voc_tick_t databaseId,
TRI_voc_cid_t collectionId) {
MMFilesPrologueMarker header;
InitMarker(reinterpret_cast<MMFilesMarker*>(&header), TRI_DF_MARKER_PROLOGUE,
sizeof(MMFilesPrologueMarker));
encoding::storeNumber<decltype(databaseId)>(reinterpret_cast<uint8_t*>(&header) +
DatabaseIdOffset(TRI_DF_MARKER_PROLOGUE),
databaseId, sizeof(decltype(databaseId)));
encoding::storeNumber<decltype(collectionId)>(reinterpret_cast<uint8_t*>(&header) +
CollectionIdOffset(TRI_DF_MARKER_PROLOGUE),
collectionId,
sizeof(decltype(collectionId)));
return header;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a footer marker, using a user-defined tick
////////////////////////////////////////////////////////////////////////////////
static inline MMFilesDatafileFooterMarker CreateFooterMarker(TRI_voc_tick_t tick) {
MMFilesDatafileFooterMarker footer;
InitMarker(reinterpret_cast<MMFilesMarker*>(&footer), TRI_DF_MARKER_FOOTER,
sizeof(MMFilesDatafileFooterMarker), tick);
return footer;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a footer marker, using tick 0
////////////////////////////////////////////////////////////////////////////////
static inline MMFilesDatafileFooterMarker CreateFooterMarker() {
return CreateFooterMarker(0); // always use tick 0
}
} // namespace MMFilesDatafileHelper
} // namespace arangodb
#endif