2014-12-10 16:48:00 +01:00
|
|
|
#pragma once
|
2014-12-13 17:48:02 +01:00
|
|
|
#ifndef BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATANODESTORE_DATANODEVIEW_H_
|
|
|
|
#define BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATANODESTORE_DATANODEVIEW_H_
|
2014-12-10 16:48:00 +01:00
|
|
|
|
2015-02-17 00:40:34 +01:00
|
|
|
#include "messmer/blockstore/interface/Block.h"
|
|
|
|
#include "../BlobStoreOnBlocks.h"
|
2015-02-25 22:30:48 +01:00
|
|
|
#include "DataInnerNode_ChildEntry.h"
|
2014-12-10 16:48:00 +01:00
|
|
|
|
2015-02-17 00:40:34 +01:00
|
|
|
#include "messmer/cpp-utils/macros.h"
|
2014-12-10 16:48:00 +01:00
|
|
|
|
|
|
|
#include <memory>
|
2015-02-25 22:30:48 +01:00
|
|
|
#include <stdexcept>
|
2014-12-10 16:48:00 +01:00
|
|
|
|
|
|
|
namespace blobstore {
|
|
|
|
namespace onblocks {
|
2014-12-13 19:17:08 +01:00
|
|
|
namespace datanodestore {
|
2014-12-10 16:48:00 +01:00
|
|
|
|
2015-02-25 22:30:48 +01:00
|
|
|
//TODO Move DataNodeLayout into own file
|
|
|
|
class DataNodeLayout {
|
2014-12-10 16:48:00 +01:00
|
|
|
public:
|
2015-02-25 22:30:48 +01:00
|
|
|
constexpr DataNodeLayout(uint32_t blocksizeBytes)
|
|
|
|
:_blocksizeBytes(
|
|
|
|
(HEADERSIZE_BYTES + 2*sizeof(DataInnerNode_ChildEntry) <= blocksizeBytes)
|
|
|
|
? blocksizeBytes
|
|
|
|
: throw std::logic_error("Blocksize too small, not enough space to store two children in an inner node")) {
|
2014-12-10 17:26:49 +01:00
|
|
|
}
|
2014-12-10 16:48:00 +01:00
|
|
|
|
|
|
|
//Total size of the header
|
2015-02-25 22:30:48 +01:00
|
|
|
static constexpr uint32_t HEADERSIZE_BYTES = 8;
|
2014-12-13 12:00:19 +01:00
|
|
|
//Where in the header is the depth field
|
2015-02-25 22:30:48 +01:00
|
|
|
static constexpr uint32_t DEPTH_OFFSET_BYTES = 0;
|
2014-12-10 16:48:00 +01:00
|
|
|
//Where in the header is the size field (for inner nodes: number of children, for leafs: content data size)
|
2015-02-25 22:30:48 +01:00
|
|
|
static constexpr uint32_t SIZE_OFFSET_BYTES = 4;
|
|
|
|
|
|
|
|
//Size of a block (header + data region)
|
|
|
|
constexpr uint32_t blocksizeBytes() const {
|
|
|
|
return _blocksizeBytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Number of bytes in the data region of a node
|
|
|
|
constexpr uint32_t datasizeBytes() const {
|
|
|
|
return _blocksizeBytes - HEADERSIZE_BYTES;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Maximum number of children an inner node can store
|
|
|
|
constexpr uint32_t maxChildrenPerInnerNode() const {
|
|
|
|
return datasizeBytes() / sizeof(DataInnerNode_ChildEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Maximum number of bytes a leaf can store
|
|
|
|
constexpr uint32_t maxBytesPerLeaf() const {
|
|
|
|
return datasizeBytes();
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
uint32_t _blocksizeBytes;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DataNodeView {
|
|
|
|
public:
|
|
|
|
DataNodeView(std::unique_ptr<blockstore::Block> block): _block(std::move(block)) {
|
|
|
|
}
|
|
|
|
virtual ~DataNodeView() {}
|
2014-12-10 16:48:00 +01:00
|
|
|
|
2015-02-25 22:30:48 +01:00
|
|
|
DataNodeView(DataNodeView &&rhs) = default;
|
2014-12-10 16:48:00 +01:00
|
|
|
|
2014-12-13 12:00:19 +01:00
|
|
|
const uint8_t *Depth() const {
|
2015-02-25 22:30:48 +01:00
|
|
|
return GetOffset<DataNodeLayout::DEPTH_OFFSET_BYTES, uint8_t>();
|
2014-12-10 16:48:00 +01:00
|
|
|
}
|
|
|
|
|
2014-12-13 12:00:19 +01:00
|
|
|
uint8_t *Depth() {
|
|
|
|
return const_cast<uint8_t*>(const_cast<const DataNodeView*>(this)->Depth());
|
2014-12-10 16:48:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const uint32_t *Size() const {
|
2015-02-25 22:30:48 +01:00
|
|
|
return GetOffset<DataNodeLayout::SIZE_OFFSET_BYTES, uint32_t>();
|
2014-12-10 16:48:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t *Size() {
|
|
|
|
return const_cast<uint32_t*>(const_cast<const DataNodeView*>(this)->Size());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Entry>
|
|
|
|
const Entry *DataBegin() const {
|
2015-02-25 22:30:48 +01:00
|
|
|
return GetOffset<DataNodeLayout::HEADERSIZE_BYTES, Entry>();
|
2014-12-10 16:48:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Entry>
|
|
|
|
Entry *DataBegin() {
|
|
|
|
return const_cast<Entry*>(const_cast<const DataNodeView*>(this)->DataBegin<Entry>());
|
|
|
|
}
|
|
|
|
|
2015-02-25 22:30:48 +01:00
|
|
|
DataNodeLayout layout() const {
|
|
|
|
return DataNodeLayout(_block->size());
|
|
|
|
}
|
|
|
|
|
2014-12-10 16:48:00 +01:00
|
|
|
template<typename Entry>
|
|
|
|
const Entry *DataEnd() const {
|
2015-02-25 22:30:48 +01:00
|
|
|
const unsigned int NUM_ENTRIES = layout().datasizeBytes() / sizeof(Entry);
|
2014-12-10 16:48:00 +01:00
|
|
|
return DataBegin<Entry>() + NUM_ENTRIES;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Entry>
|
|
|
|
Entry *DataEnd() {
|
|
|
|
return const_cast<Entry*>(const_cast<const DataNodeView*>(this)->DataEnd<Entry>());
|
|
|
|
}
|
|
|
|
|
2015-01-24 00:54:27 +01:00
|
|
|
std::unique_ptr<blockstore::Block> releaseBlock() {
|
|
|
|
return std::move(_block);
|
|
|
|
}
|
|
|
|
|
2015-01-24 01:59:42 +01:00
|
|
|
const blockstore::Block &block() const {
|
|
|
|
return *_block;
|
|
|
|
}
|
|
|
|
|
2015-01-24 22:27:14 +01:00
|
|
|
const blockstore::Key &key() const {
|
|
|
|
return _block->key();
|
|
|
|
}
|
|
|
|
|
2015-01-28 01:02:32 +01:00
|
|
|
void flush() const {
|
|
|
|
_block->flush();
|
|
|
|
}
|
|
|
|
|
2014-12-10 17:26:49 +01:00
|
|
|
private:
|
2014-12-10 16:48:00 +01:00
|
|
|
template<int offset, class Type>
|
|
|
|
const Type *GetOffset() const {
|
|
|
|
return (Type*)(((const int8_t*)_block->data())+offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<blockstore::Block> _block;
|
|
|
|
|
2014-12-10 17:26:49 +01:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(DataNodeView);
|
|
|
|
|
2014-12-10 16:48:00 +01:00
|
|
|
};
|
|
|
|
|
2014-12-13 19:17:08 +01:00
|
|
|
}
|
2014-12-10 16:48:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|