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

Working version of insert for persistent tables

parent 784b28f5
......@@ -27,9 +27,9 @@
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include <core/PFabricTypes.hpp>
#include <core/Tuple.hpp>
#include <libpmemobj++/persistent_ptr.hpp>
......@@ -39,21 +39,23 @@ namespace pfabric {
namespace nvm {
//TODO: Find a more suitable position for these constants
/* 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;
const int gDDCRangePos1 = 0;
const int gDDCRangePos2 = 4;
const int gCountPos = 8;
const int gFreeSpacePos = 12;
const int gSmaOffsetPos = 14;
const int gDataOffsetPos = 16;
/* Sizes/Lengths in NVM_Block */
const int FixedHeaderSize = 14;
const int AttrOffsetSize = 4;
const int OffsetSize = 2;
const int gFixedHeaderSize = 14;
const int gDDCValueSize = 4;
const int gAttrOffsetSize = 4;
const int gOffsetSize = 2;
/** The size of a single block in persistent memory */
static constexpr uint16_t BlockSize = 1 << 15; // 32KB
static constexpr uint16_t gBlockSize = 1 << 15; // 32KB
/**
* \brief This type represents a byte array used for persistent structures.
......@@ -82,7 +84,7 @@ static constexpr uint16_t BlockSize = 1 << 15; // 32KB
* . ...
* . data -> size of all strings + ddc_cnt (Nul termination)
*/
typedef typename std::array<uint8_t, BlockSize> NVM_Block;
typedef typename std::array<uint8_t, gBlockSize> NVM_Block;
namespace detail {
......@@ -107,7 +109,7 @@ struct get_helper;
*****************************************************************************/
template<typename T, std::size_t ID>
struct get_helper {
static T apply(persistent_ptr<NVM_Block> block, const std::vector<uint16_t>& offsets) {
static T apply(persistent_ptr<NVM_Block> block, const 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);
......@@ -125,7 +127,7 @@ struct get_helper {
*****************************************************************************/
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)))[] {
static char (&( apply(persistent_ptr<NVM_Block> block, const uint16_t *offsets)))[] {
return reinterpret_cast<char (&)[]>(block->at(offsets[ID]));
}
};
......@@ -140,7 +142,7 @@ struct get_helper<std::string, ID> {
*****************************************************************************/
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) {
static int32_t& apply(persistent_ptr<NVM_Block> block, const uint16_t *offsets) {
return reinterpret_cast<int32_t&>(block->at(offsets[ID]));
}
};
......@@ -155,11 +157,76 @@ struct get_helper<int32_t, ID> {
*****************************************************************************/
template<std::size_t ID>
struct get_helper<double, ID> {
static double& apply(persistent_ptr<NVM_Block> block, const std::vector<uint16_t>& offsets) {
static double& apply(persistent_ptr<NVM_Block> block, const uint16_t *offsets) {
return reinterpret_cast<double&>(block->at(offsets[ID]));
}
};
/**************************************************************************//**
* \brief PTuplePrinter is a helper function to print a persistent tuple of any
* size.
*
* PTuplePrinter is a helper function to print a PTuple instance of any size
* and member types to std::ostream. This template should not be directly used,
* but only via the Tuple members.
*
* \tparam Tuple
* the tuple type
* \tparam CurrentIndex
* the index of the attribute value to be printed
*****************************************************************************/
template<class Tuple, std::size_t CurrentIndex>
struct PTuplePrinter;
/**************************************************************************//**
* \brief General overload for printing more than 1 element.
*
* This specialization will print the remaining elements first and appends the
* current one after a comma.
*
* \tparam Tuple
* the underlying tuple type
* \tparam CurrentIndex
* the index of the attribute value to be printed
*****************************************************************************/
template<class Tuple, std::size_t CurrentIndex>
struct PTuplePrinter {
static void print(std::ostream& os, persistent_ptr<NVM_Block> block, const uint16_t* offsets) {
PTuplePrinter<Tuple, CurrentIndex - 1>::print(os, block, offsets);
os << "," << get_helper<typename Tuple::template getAttributeType<CurrentIndex-1>::type, CurrentIndex - 1>::apply(block, offsets);
}
};
/**************************************************************************//**
* \brief Specialization for printing a persistent tuple with 1 element.
*
* This specialization will just print the element.
*
* \tparam Tuple
* the underlying tuple type having one element
*****************************************************************************/
template<class Tuple>
struct PTuplePrinter<Tuple, 1> {
static void print(std::ostream& os, persistent_ptr<NVM_Block> block, const uint16_t* offsets) {
os << get_helper<typename Tuple::template getAttributeType<0>::type, 0>::apply(block, offsets);
}
};
/**************************************************************************//**
* \brief Specialization for printing a persistent tuple with no elements.
*
* This specialization will do nothing.
*
* \tparam Tuple
* the underlying tuple type having no elements
*****************************************************************************/
template<class Tuple>
struct PTuplePrinter<Tuple, 0> {
static void print(std::ostream& os, persistent_ptr<NVM_Block> block, const uint16_t* offsets) {
}
};
} /* end namespace detail */
/**************************************************************************//**
......@@ -191,12 +258,6 @@ struct get_helper<double, ID> {
*****************************************************************************/
template<class Tuple>
class PTuple {
private:
persistent_ptr<NVM_Block> block;
std::vector<uint16_t> offsets;//!< TODO: Something else than a runtime eater like vector
public:
/************************************************************************//**
* \brief the number of attributes for this tuple type.
......@@ -225,7 +286,7 @@ public:
* \param[in] _offsets
* the offsets for each tuple element
***************************************************************************/
PTuple(persistent_ptr<NVM_Block> _block, std::vector<uint16_t> _offsets) :
PTuple(persistent_ptr<NVM_Block> _block, std::array<uint16_t, NUM_ATTRIBUTES> _offsets) :
block(_block), offsets(_offsets) {
}
......@@ -238,15 +299,64 @@ public:
* a reference to the persistent tuple's attribute with the requested \c ID
***************************************************************************/
template<std::size_t ID>
inline auto getAttribute() -> typename getAttributeType<ID>::type {
return detail::get_helper<typename getAttributeType<ID>::type, ID>::apply(block, offsets);
inline auto getAttribute() {
return detail::get_helper<typename getAttributeType<ID>::type, ID>::apply(block, offsets.data());
}
/************************************************************************//**
* \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);
inline auto get() {
return detail::get_helper<typename getAttributeType<ID>::type, ID>::apply(block, offsets.data());
}
/************************************************************************//**
* \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 getAttribute() const {
return detail::get_helper<typename getAttributeType<ID>::type, ID>::apply(block, offsets.data());
}
/************************************************************************//**
* \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() const {
return detail::get_helper<typename getAttributeType<ID>::type, ID>::apply(block, offsets.data());
}
/************************************************************************//**
* \brief Print this persistent tuple to an ostream.
*
* \param[in] os
* the output stream to print the tuple
***************************************************************************/
void print(std::ostream& os) {
detail::PTuplePrinter<Tuple, NUM_ATTRIBUTES>::print(os, block, offsets.data());
}
private:
persistent_ptr<NVM_Block> block;
std::array<uint16_t, NUM_ATTRIBUTES> offsets;
}; /* class PTuplePtr */
} /* end namespace nvm */
......@@ -267,10 +377,48 @@ public:
* 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(ptp.template get<ID>()) {
auto get(const nvm::PTuple<Tuple>& ptp) -> decltype((ptp.template get<ID>())) {
return ptp.template get<ID>();
}
/**************************************************************************//**
* \brief Print a persistent tuple to an ostream.
*
* \param[in] os
* the output stream to print the tuple
*****************************************************************************/
template<class Tuple>
void print(std::ostream& os, const nvm::PTuple<Tuple>& ptp) {
ptp.print(os);
}
} /* end namespace pfabric */
/**************************************************************************//**
* \brief Helper template for printing persistent tuples to an ostream
*
* \tparam Tuple
* the underlying Tuple of the PTuple
* \param[in] os
* the output stream to print the tuple
* \param[in] ptp
* PTuple instance to print
* \return
* the output stream
*****************************************************************************/
template<typename Tuple>
std::ostream& operator<<(std::ostream& os, pfabric::nvm::PTuple<Tuple>& ptp) {
ptp.print(os);
return os;
}
/*
namespace std {
template< std::size_t ID, typename Tuple >
auto get( pfabric::nvm::PTuple<Tuple>& ptp ) -> decltype(ptp.template getAttribute<ID>()) {
return ptp.template getAttribute<ID>();
}
}
*/
#endif /* PTuple_hpp_ */
/*
* 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 PTuplePrinter_hpp_
#define PTuplePrinter_hpp_
#include <ostream>
#include <core/PTuple.hpp>
namespace pfabric {
/**
* Forward declarations
*/
namespace nvm {
template<class Tuple> class PTuple;
}
template<std::size_t ID, class Tuple>
auto get(const nvm::PTuple<Tuple>& ptp) -> typename Tuple::template getAttributeType<ID>::type;
namespace nvm {
namespace detail {
template<class Tuple, std::size_t CurrentIndex>
struct PTuplePrinter;
template<class Tuple, std::size_t CurrentIndex>
struct PTuplePrinter {
static void print(std::ostream& os, const nvm::PTuple<Tuple>& ptp) {
PTuplePrinter<Tuple, CurrentIndex - 1>::print(os, ptp);
os << "," << pfabric::get<CurrentIndex - 1>(ptp);
}
};
template<class Tuple>
struct PTuplePrinter<Tuple, 1> {
static void print(std::ostream& os, const nvm::PTuple<Tuple>& ptp) {
os << pfabric::get<0>(ptp);
}
};
template<class Tuple>
struct PTuplePrinter<Tuple, 0> {
static void print(std::ostream& os, const nvm::PTuple<Tuple>& ptp) {
}
};
} /* end namespace detail */
template<class Tuple>
void print(std::ostream& os, const nvm::PTuple<Tuple>& ptp) {
detail::PTuplePrinter<Tuple, ptp.NUM_ATTRIBUTES>::print(os, ptp);
}
} /* end namespace nvm */
} /* end namespace pfabric */
#endif /* PTuplePrinter_hpp_ */
/*
* 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 BDCCInfo_hpp_
#define BDCCInfo_hpp_
namespace pfabric {
struct BDCCInfo {
typedef std::unordered_map<ColumnInfo, uint16_t> ColumnBitsMap;
//BDCCInfo() {}
BDCCInfo(ColumnBitsMap _bitMap) : bitMap(_bitMap),
numBins(std::accumulate(_bitMap.begin(), _bitMap.end(), 0,
[](const size_t sum, decltype(*_bitMap.begin()) p) { return sum + p.second; })) {}
const ColumnBitsMap bitMap;
const size_t numBins;
std::map<uint32_t, std::size_t> histogram;
};
typedef std::shared_ptr<TableInfo> TableInfoPtr;
}
#endif
......@@ -15,8 +15,51 @@ struct ColumnInfo {
std::string mColName;
ColumnType mColType;
bool operator==(const ColumnInfo& other) const {
return (mColName == other.mColName && mColType == other.mColType);
}
bool operator<(const ColumnInfo& other) const {
return mColName < other.mColName;
}
};
template< bool isFixedSize >
struct IsFixedSize {
static const bool IS_FIXED_SIZE = isFixedSize;
};
template < ColumnInfo::ColumnType ColType >
struct ColTypeTraits;
template <>
struct ColTypeTraits< ColumnInfo::Int_Type > : IsFixedSize<true> {
static const std::size_t COLUMN_SIZE = sizeof(int32_t);
};
template <>
struct ColTypeTraits< ColumnInfo::Double_Type > : IsFixedSize<true> {
static const std::size_t COLUMN_SIZE = sizeof(double);
};
template <>
struct ColTypeTraits< ColumnInfo::String_Type > : IsFixedSize<false>{};
using Offset = std::size_t;
template< ColumnInfo::ColumnType ColType, typename Col >
typename std::enable_if< not ColTypeTraits< ColType >::IS_FIXED_SIZE, Offset >::type getSize(const Col& t ) {
//TODO: runtime size calculation
}
template< ColumnInfo::ColumnType ColType, typename Col >
typename std::enable_if< ColTypeTraits< ColType >::IS_FIXED_SIZE, Offset >::type getSize(const Col& t ) {
using ColTraits = ColTypeTraits<ColType>;
return ColTraits::COLUMN_SIZE;
}
class TableInfo {
public:
typedef std::vector<ColumnInfo>::const_iterator ColumnIterator;
......@@ -43,6 +86,8 @@ class TableInfo {
ColumnIterator begin() const { return mColumns.begin(); }
ColumnIterator end() const { return mColumns.end(); }
std::size_t numColumns() const { return mColumns.size(); }
private:
std::string mName;
std::vector<ColumnInfo> mColumns;
......@@ -54,4 +99,13 @@ typedef std::shared_ptr<TableInfo> TableInfoPtr;
std::ostream& operator<<(std::ostream& os, pfabric::ColumnInfo::ColumnType ct);
namespace std {
template <>
struct hash<pfabric::ColumnInfo> {
std::size_t operator()(const pfabric::ColumnInfo& c) const {
return std::hash<std::string>()(c.mColName);
}
};
}
#endif
This diff is collapsed.
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do
// this in one cpp file
#include "catch.hpp"
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
#include "catch.hpp"
#include <unistd.h>
#include "fmt/format.h"
#include "table/TableInfo.hpp"
#include "table/persistent_table.hpp"
#include "core/Tuple.hpp"
#include "core/serialize.hpp"
#include "pfabric.hpp"
#include "fmt/format.h"
using namespace pfabric;
using nvml::obj::pool;
......@@ -31,6 +30,8 @@ struct root {
TEST_CASE("Testing storing tuples in persistent_table", "[persistent_table]") {
pool<root> pop;
std::chrono::high_resolution_clock::time_point start, end;
std::vector<typename std::chrono::duration<int64_t,micro>::rep> measures;
const std::string path = "/tmp/testdb.db";
std::remove(path.c_str());
......@@ -48,20 +49,39 @@ TEST_CASE("Testing storing tuples in persistent_table", "[persistent_table]") {
ColumnInfo("c", ColumnInfo::String_Type),
ColumnInfo("d", ColumnInfo::Double_Type)
});
auto dimInfo = BDCCInfo::ColumnBitsMap({
{ColumnInfo("b", ColumnInfo::Int_Type), 4},
{ColumnInfo("d", ColumnInfo::Double_Type), 6}
});
transaction::exec_tx(pop,
[&] {q->pTable = make_persistent<pTable_type>(tInfo);});
[&] {q->pTable = make_persistent<pTable_type>(tInfo, dimInfo);});
} else {
std::cerr << "WARNING: Table already exists" << std::endl;
}
for (unsigned int i = 0; i < 10; i++) {
for (unsigned int i = 0; i < 500; i++) {
auto tup = MyTuple(i + 1,
(i + 1) * 100,
fmt::format("String #{0}", i),
i * 12.345);
q->pTable->insert(tup);
start = std::chrono::high_resolution_clock::now();
q->pTable->insert(i+1, tup);
end = std::chrono::high_resolution_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
measures.push_back(diff);
}
//q->pTable->print(true);
auto avg = std::accumulate(measures.begin(), measures.end(), 0) / measures.size();
auto minmax = std::minmax_element(std::begin(measures), std::end(measures));
std::cout << "\nInsert Statistics in µs: "
<< "\n\tAverage: " << avg
<< "\n\tMin: " << *minmax.first
<< "\n\tMax: " << *minmax.second << '\n';
//q->pTable->print(false);
//auto ptp = q->pTable->getByKey(5);
//std::cout << "Tuple 5: " << ptp << '\n';
/* Clean up */
transaction::exec_tx(pop, [&] {delete_persistent<pTable_type>(q->pTable);});
......
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