Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
code
pfabric
Commits
83940467
Commit
83940467
authored
Mar 03, 2017
by
Philipp Götze
Browse files
Created PTuple and some adaptions to nvm related stuff
parent
dd82db7a
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
src/core/PTuple.hpp
0 → 100644
View file @
83940467
/*
* 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_ */
src/table/NVMTable.hpp
View file @
83940467
...
...
@@ -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
...
...
src/table/persistent_table.hpp
View file @
83940467
This diff is collapsed.
Click to expand it.
src/test/persistent_tableTest.cpp
View file @
83940467
#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
();
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment