libcryfs/implementations/onblocks/datanodestore/DataNodeView.h

141 lines
3.7 KiB
C
Raw Normal View History

2014-12-10 16:48:00 +01:00
#pragma once
2015-10-15 13:10:20 +02:00
#ifndef MESSMER_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATANODESTORE_DATANODEVIEW_H_
#define MESSMER_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"
#include "DataInnerNode_ChildEntry.h"
2014-12-10 16:48:00 +01:00
#include <messmer/cpp-utils/pointer/unique_ref.h>
2014-12-10 16:48:00 +01:00
#include <memory>
#include <stdexcept>
#include <type_traits>
2014-12-10 16:48:00 +01:00
namespace blobstore {
namespace onblocks {
namespace datanodestore {
2014-12-10 16:48:00 +01:00
//TODO Move DataNodeLayout into own file
class DataNodeLayout final {
2014-12-10 16:48:00 +01:00
public:
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
static constexpr uint32_t HEADERSIZE_BYTES = 8;
//Where in the header is the depth field
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)
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
//We are returning uint64_t here, because calculations involving maxBytesPerLeaf most probably should use 64bit integers to support blobs >4GB.
constexpr uint64_t maxBytesPerLeaf() const {
return datasizeBytes();
}
private:
uint32_t _blocksizeBytes;
};
class DataNodeView final {
public:
DataNodeView(cpputils::unique_ref<blockstore::Block> block): _block(std::move(block)) {
}
~DataNodeView() {}
2014-12-10 16:48:00 +01:00
DataNodeView(DataNodeView &&rhs) = default;
2014-12-10 16:48:00 +01:00
uint8_t Depth() const {
return *((uint8_t*)_block->data()+DataNodeLayout::DEPTH_OFFSET_BYTES);
}
void setDepth(uint8_t value) {
_block->write(&value, DataNodeLayout::DEPTH_OFFSET_BYTES, sizeof(value));
2014-12-10 16:48:00 +01:00
}
uint32_t Size() const {
return *(uint32_t*)((uint8_t*)_block->data()+DataNodeLayout::SIZE_OFFSET_BYTES);
2014-12-10 16:48:00 +01:00
}
void setSize(uint32_t value) {
_block->write(&value, DataNodeLayout::SIZE_OFFSET_BYTES, sizeof(value));
2014-12-10 16:48:00 +01:00
}
const void *data() const {
return (uint8_t*)_block->data() + DataNodeLayout::HEADERSIZE_BYTES;
}
void write(const void *source, uint64_t offset, uint64_t size) {
_block->write(source, offset + DataNodeLayout::HEADERSIZE_BYTES, size);
2014-12-10 16:48:00 +01:00
}
template<typename Entry>
const Entry *DataBegin() const {
return GetOffset<DataNodeLayout::HEADERSIZE_BYTES, Entry>();
2014-12-10 16:48:00 +01:00
}
template<typename Entry>
const Entry *DataEnd() const {
const unsigned int NUM_ENTRIES = layout().datasizeBytes() / sizeof(Entry);
2014-12-10 16:48:00 +01:00
return DataBegin<Entry>() + NUM_ENTRIES;
}
DataNodeLayout layout() const {
return DataNodeLayout(_block->size());
}
cpputils::unique_ref<blockstore::Block> releaseBlock() {
return std::move(_block);
}
const blockstore::Block &block() const {
return *_block;
}
const blockstore::Key &key() const {
return _block->key();
}
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);
}
cpputils::unique_ref<blockstore::Block> _block;
2014-12-10 16:48:00 +01:00
2014-12-10 17:26:49 +01:00
DISALLOW_COPY_AND_ASSIGN(DataNodeView);
2014-12-10 16:48:00 +01:00
};
}
2014-12-10 16:48:00 +01:00
}
}
#endif