Commit 83940467 authored by Philipp Götze's avatar Philipp Götze
Browse files

Created PTuple and some adaptions to nvm related stuff

parent dd82db7a
/*
* Copyright (c) 2014-17 The PipeFabric team,
* All Rights Reserved.
*
* This file is part of the PipeFabric package.
*
* PipeFabric is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file LICENSE.
* If not you can find the GPL at http://www.gnu.org/copyleft/gpl.html
*/
#ifndef PTuple_hpp_
#define PTuple_hpp_
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include <core/PFabricTypes.hpp>
#include <libpmemobj++/persistent_ptr.hpp>
using nvml::obj::persistent_ptr;
namespace pfabric {
namespace nvm {
/* Positions in NVM_Block */
const int DDCRangePos1 = 0;
const int DDCRangePos2 = 4;
const int CountPos = 8;
const int FreeSpacePos = 12;
const int SmaOffsetPos = 14;
const int DataOffsetPos = 16;
/* Sizes/Lengths in NVM_Block */
const int FixedHeaderSize = 14;
const int AttrOffsetSize = 4;
const int OffsetSize = 2;
/** The size of a single block in persistent memory */
static constexpr uint16_t BlockSize = 1 << 10; // 32KB
/**
* \brief This type represents a byte array used for persistent structures.
*
* A NVM_Block is a PAX oriented data block with the following structure for 32KB:
* <ddc_range><ddc_cnt><sma_offset_0><data_offset_0> ...<sma_offset_n><data_offset_n>
* <sma_min_0><sma_max_0><data_vector_0> ... <sma_min_n><sma_max_n><data_vector_n>
* 0 ddc_range -> long (x2) - 8 Byte
* 8 ddc_cnt -> long - 4 Byte
* 12 free_space -> unsigned short
* for each attribute:
* 14 sma_offset_x -> unsigned short - 2 Byte (depends on block size)
* 16 data_offset_x -> unsigned short
* ...
*
* for each attribute (int, double):
* . sma_min_x -> size of attributes data type
* . sma_max_x -> size of attributes data type
* . data_vector -> size of attributes data type * ddc_cnt
* ...
*
* for each attribute (string - data starts at the end of the minipage):
* . sma_min_offset_x -> unsigned short
* . sma_max_offset_x -> unsigned short
* . data_offset_vector -> unsigned short * ddc_cnt
* . ...
* . data -> size of all strings + ddc_cnt (Nul termination)
*/
typedef typename std::array<uint8_t, BlockSize> NVM_Block;
namespace detail {
/**************************************************************************//**
* \brief get_helper is a helper function to receive an attribute of a PTuple.
*
* \tparam T
* the type of the requested attribute
* \tparam ID
* the index of the requested attribute
*****************************************************************************/
template<typename T, std::size_t ID>
struct get_helper;
/**************************************************************************//**
* \brief General overload for any type of attribute.
*
* \tparam T
* the type of the requested attribute
* \tparam ID
* the index of the requested attribute
*****************************************************************************/
template<typename T, std::size_t ID>
struct get_helper {
static T apply(persistent_ptr<NVM_Block> block, const std::vector<uint16_t>& offsets) {
T val;
uint8_t* ptr = reinterpret_cast<uint8_t*>(&val);
std::copy(block->begin() + offsets[ID], block->begin() + offsets[ID] + sizeof(T), ptr);
return val;
}
};
/**************************************************************************//**
* \brief Specialization for retrieving an attribute of type string.
*
* \tparam T
* the type of the requested attribute
* \tparam ID
* the index of the requested attribute
*****************************************************************************/
template<std::size_t ID>
struct get_helper<std::string, ID> {
static char (&( apply(persistent_ptr<NVM_Block> block, const std::vector<uint16_t>& offsets)))[] {
return reinterpret_cast<char (&)[]>(block->at(offsets[ID]));
}
};
/**************************************************************************//**
* \brief Specialization for retrieving an attribute of type 32 byte integer.
*
* \tparam T
* the type of the requested attribute
* \tparam ID
* the index of the requested attribute
*****************************************************************************/
template<std::size_t ID>
struct get_helper<int32_t, ID> {
static int32_t& apply(persistent_ptr<NVM_Block> block, const std::vector<uint16_t>& offsets) {
return reinterpret_cast<int32_t&>(block->at(offsets[ID]));
}
};
/**************************************************************************//**
* \brief Specialization for retrieving an attribute of type double.
*
* \tparam T
* the type of the requested attribute
* \tparam ID
* the index of the requested attribute
*****************************************************************************/
template<std::size_t ID>
struct get_helper<double, ID> {
static double& apply(persistent_ptr<NVM_Block> block, const std::vector<uint16_t>& offsets) {
return reinterpret_cast<double&>(block->at(offsets[ID]));
}
};
} /* end namespace detail */
/**************************************************************************//**
* \brief A persistent Tuple used for referencing tuples in a persistent table.
*
* A PTuple consist of a persistent pointer to the \c block where the
* underlying tuple is stored. The \c offsets are used to locate the individual
* attributes of the tuple within the \c block.
*
* \code
* persistent_ptr<NVM_Block> block;
* std::vector<uint16_t> tupleOffsets;
*
* // Insert into block and save the offsets ...
*
* PTuple<pfabric::Tuple<int, double, std::string>> ptp(block, tupleOffsets);
* \endcode
*
* Get reference to single attribute:
*
* \code
* auto attr1 = ptp.template get<0>;
* // or:
* auto attr1 = get<0>(ptp);
* \endcode
*
* \note string attributes are returned as reference to a char array
* \author Philipp Goetze <philipp.goetze@tu-ilmenau.de>
*****************************************************************************/
template<class Tuple>
class PTuple {
public:
persistent_ptr<NVM_Block> block;
std::vector<uint16_t> offsets;//!< TODO: Something else than a runtime eater like vector
/************************************************************************//**
* \brief the number of attributes for this tuple type.
***************************************************************************/
static const TupleSize NUM_ATTRIBUTES = Tuple::NUM_ATTRIBUTES;
/************************************************************************//**
* \brief Meta function returning the type of a specific tuple attribute.
*
* \tparam ID
* the index of the requested attribute.
***************************************************************************/
template<AttributeIdx ID>
struct getAttributeType {
typedef typename Tuple::template getAttributeType<ID>::type type;
};
/************************************************************************//**
* \brief Constructs a new persistent tuple using a persistent block and
* offsets for the tuple elements.
*
* \tparam Tuple
* the underlying tuple type used as base
* \param[in] _block
* the persistent block containing the tuple data (bytes)
* \param[in] _offsets
* the offsets for each tuple element
***************************************************************************/
PTuple(persistent_ptr<NVM_Block> _block, std::vector<uint16_t> _offsets) :
block(_block), offsets(_offsets) {
}
/************************************************************************//**
* \brief Get a specific attribute value from the persistent tuple.
*
* \tparam ID
* the index of the requested attribute.
* \return
* a reference to the persistent tuple's attribute with the requested \c ID
***************************************************************************/
template<std::size_t ID>
inline auto get() -> typename getAttributeType<ID>::type {
return detail::get_helper<typename getAttributeType<ID>::type, ID>::apply(block,
offsets);
}
}; /* class PTuplePtr */
} /* end namespace nvm */
/**************************************************************************//**
* \brief Get a specific attribute reference from the PTuple.
*
* A global accessor function to reduce boilerplate code that needs to be
* written to access a specific attribute of a PTuple.
* \tparam ID
* the index of the requested attribute.
* \tparam Tuple
* the underlying tuple type used as base
* \param[in] ptp
* the persistent tuple (PTuple) instance
* \return
* a reference to the persistent tuple's attribute with the requested \c ID
*****************************************************************************/
template<std::size_t ID, class Tuple>
auto get(
nvm::PTuple<Tuple> ptp) -> decltype(nvm::detail::get_helper<typename Tuple::template getAttributeType<ID>::type, ID>::apply(ptp.block, ptp.offsets)) {
return nvm::detail::get_helper<typename Tuple::template getAttributeType<ID>::type, ID>::apply(
ptp.block, ptp.offsets);
}
} /* end namespace pfabric */
#endif /* PTuple_hpp_ */
......@@ -60,26 +60,13 @@ using nvml::obj::make_persistent;
using nvml::obj::delete_persistent;
using nvml::obj::transaction;
/*
namespace detail
{
// Rebuild a tuple from a given ddc_block and position within this block
template <class T>
inline T retrievTuple(persistent_ptr<struct ddc_block> b, int32_t i)
{
b->StreamType buf(ptr, ptr + size);
return T(buf);
}
}
*/
template <typename RecordType, typename KeyType>
class NVMIterator
{
public:
typedef std::function<bool(const RecordType &)> Predicate;
typedef TuplePtr<RecordType> RecordTypePtr;
typedef pfabric::persistent_table<RecordType, KeyType> pTable_type;
typedef nvm::persistent_table<RecordType, KeyType> pTable_type;
explicit NVMIterator() {}
explicit NVMIterator(persistent_ptr<pTable_type> _pTable, Predicate _pred) : pTable(_pTable), pred(_pred)
......@@ -131,7 +118,7 @@ protected:
template <typename RecordType, typename KeyType>
inline NVMIterator<RecordType, KeyType> makeNVMIterator(
persistent_ptr<pfabric::persistent_table<RecordType, KeyType>> pTable,
persistent_ptr<nvm::persistent_table<RecordType, KeyType>> pTable,
typename NVMIterator<RecordType, KeyType>::Predicate pred)
{
return NVMIterator<RecordType, KeyType>(pTable, pred);
......@@ -155,7 +142,7 @@ class NVMTable : public BaseTable
{
public:
// TODO: - Index (volatile)
typedef pfabric::persistent_table<RecordType, KeyType> pTable_type;
typedef nvm::persistent_table<RecordType, KeyType> pTable_type;
struct root
{
......@@ -412,7 +399,7 @@ private:
std::string path = tableInfo.tableName() + ".db";
if (access(path.c_str(), F_OK) != 0)
{
pop = pool<root>::create(path, LAYOUT, (size_t)blockSize, 0666);
pop = pool<root>::create(path, LAYOUT);//, (size_t)blockSize, 0666);
//throw TableException("failed to create pool\n");
}
else
......
This diff is collapsed.
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do
// this in one cpp file
// this in one cpp file
#include "catch.hpp"
......@@ -15,8 +15,6 @@
#include "fmt/format.h"
//#define LAYOUT "test_persistent_table"
using namespace pfabric;
using nvml::obj::pool;
using nvml::obj::p;
......@@ -24,60 +22,48 @@ using nvml::obj::persistent_ptr;
using nvml::obj::make_persistent;
using nvml::obj::transaction;
const unsigned short blockSize = 1 << 15; // 32KB
typedef pfabric::Tuple<unsigned long, int, string, double> MyTuple;
typedef pfabric::persistent_table<MyTuple, uint64_t> pTable_type;
typedef pfabric::Tuple<int, int, string, double> MyTuple;
typedef pfabric::nvm::persistent_table<MyTuple, uint64_t> pTable_type;
struct root
{
struct root {
persistent_ptr<pTable_type> pTable;
};
TEST_CASE("Testing storing tuples in persistent_table", "[persistent_table]")
{
pool<root> pop;
const std::string path = "/tmp/testdb.db";
if (access(path.c_str(), F_OK) != 0)
{
pop = pool<root>::create(path, LAYOUT); //, (size_t)blockSize, 0666);
}
else
{
pop = pool<root>::open(path, LAYOUT);
}
std::cout << "Pool kreiert!" << std::endl;
auto q = pop.get_root();
if (!q->pTable)
{
auto tInfo = TableInfo("MyTable", {
ColumnInfo("a", ColumnInfo::Int_Type),
ColumnInfo("b", ColumnInfo::Int_Type),
ColumnInfo("c", ColumnInfo::String_Type),
ColumnInfo("d", ColumnInfo::Double_Type)
});
transaction::exec_tx(
pop, [&] { q->pTable = make_persistent<pTable_type>(tInfo); });
}
else
std::cerr << "WARNING: Table already exists" << std::endl;
std::cout << "Tabelle " << (*q->pTable->persistent_table::root->tInfo).tableName() << " persistiert!" << std::endl;
for (unsigned int i = 0; i < 8; i++)
{
auto tup = MyTuple((unsigned long)i + 1, (i + 1) * 100,
fmt::format("String #{0}", i), i * 12.345);
q->pTable->insert(tup, 0);
}
std::cout << "Alle Tupel eingefügt!" << std::endl;
transaction::exec_tx(
pop, [&] { delete_persistent<pTable_type>(q->pTable); });
pop.close();
std::remove(path.c_str());
TEST_CASE("Testing storing tuples in persistent_table", "[persistent_table]") {
pool<root> pop;
const std::string path = "/tmp/testdb.db";
std::remove(path.c_str());
if (access(path.c_str(), F_OK) != 0) {
pop = pool<root>::create(path, LAYOUT);
} else {
pop = pool<root>::open(path, LAYOUT);
}
auto q = pop.get_root();
if (!q->pTable) {
auto tInfo = TableInfo("MyTable", {
ColumnInfo("a", ColumnInfo::Int_Type),
ColumnInfo("b", ColumnInfo::Int_Type),
ColumnInfo("c", ColumnInfo::String_Type),
ColumnInfo("d", ColumnInfo::Double_Type)
});
transaction::exec_tx(pop,
[&] {q->pTable = make_persistent<pTable_type>(tInfo);});
} else {
std::cerr << "WARNING: Table already exists" << std::endl;
}
for (unsigned int i = 0; i < 10; i++) {
auto tup = MyTuple(i + 1,
(i + 1) * 100,
fmt::format("String #{0}", i),
i * 12.345);
q->pTable->insert(tup);
}
//q->pTable->print(true);
/* Clean up */
transaction::exec_tx(pop, [&] {delete_persistent<pTable_type>(q->pTable);});
pop.close();
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment