Skip to content

Commit

Permalink
Move the responsibility for moving serialized data into the flat file…
Browse files Browse the repository at this point in the history
… to the adapters. This results in a major simplification for writing UDT adapters, and simplifies internal index map and index set code.
  • Loading branch information
Beman committed Sep 11, 2013
1 parent 9dda3a5 commit ccf846d
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 200 deletions.
19 changes: 15 additions & 4 deletions doc/src/tutorial_source.html
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,16 @@ <h2><a name="User-defined-types">User defined types</a> (UDTs)</h2>
<blockquote>
<pre>$include "udt.hpp.html"</pre>
</blockquote>
<p>Ugh! The actual UDT is easy, but the index traits adapter is ugly.
There&#39;s a branch already being worked on to simplify that.</p>
<p>So now let&#39;s build an index set of type UDT. The code looks like this [<code><a href="../example/udt_index_set.cpp">udt_index_set.cpp</a></code>]:</p>
<p>A couple of things are worth point out:</p>
<ul>
<li>The &quot;<code>// specializations to support btree indexes</code>&quot; section
tells the B-tree index how to serialize and de-serialize type <code>UDT</code>
in the flat file.</li>
<li>The &quot;<code>// function objects for different orderings</code>&quot; section
is used only in the <a href="#UDT-three-index-set">UDT three index set</a>
example so can be ignore for now.</li>
</ul>
<p>So now let&#39;s build an index set of type <code>UDT</code>. The code looks like this [<code><a href="../example/udt_index_set.cpp">udt_index_set.cpp</a></code>]:</p>
<blockquote>
<pre>$include "udt_index_set.cpp.html"</pre>
</blockquote>
Expand All @@ -394,6 +401,10 @@ <h2><a name="User-defined-types">User defined types</a> (UDTs)</h2>
</pre>
</blockquote>
<h2><a name="UDT-three-index-set">UDT three index set</a></h2>
<p>One of the advantages of separating the index file from the flat file is
that you can have multiple index files. This example [<code><a href="../example/udt_3_index_set.cpp">udt_3_index_set.cpp</a></code>]
creates three indexes so that we can access using the ID, English, or Spanish
elements as the key.</p>
<blockquote>
<pre>$include "udt_3_index_set.cpp.html"</pre>
</blockquote>
Expand Down Expand Up @@ -579,7 +590,7 @@ <h2><a name="Preloading">Preloading</a></h2>
<hr>

<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->10 September 2013<!--webbot bot="Timestamp" endspan i-checksum="39617" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->11 September 2013<!--webbot bot="Timestamp" endspan i-checksum="39619" --></p>

<p>© Copyright Beman Dawes, 2013</p>

Expand Down
98 changes: 37 additions & 61 deletions doc/tutorial.html
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ <h2><a name="User-defined-types">User defined types</a> (UDTs)</h2>
#ifndef BOOST_BTREE_UDT_EXAMPLE_HPP
#define BOOST_BTREE_UDT_EXAMPLE_HPP

#include &lt;boost/btree/index_helpers.hpp&gt;
#include &lt;boost/btree/support/string_view.hpp&gt;
#include &lt;iosfwd&gt;

Expand All @@ -605,6 +606,7 @@ <h2><a name="User-defined-types">User defined types</a> (UDTs)</h2>
struct UDT
{
typedef int id_type;

id_type id;
string_view english;
string_view spanish;
Expand Down Expand Up @@ -639,75 +641,45 @@ <h2><a name="User-defined-types">User defined types</a> (UDTs)</h2>
{return x.spanish &lt; y.spanish;}
};

// specialization boost::btree::default_index_traits&lt;UDT&gt; ------------------//
// specializations to support btree indexes --------------------------------//

namespace boost
{
namespace btree
{
namespace btree
{
template &lt;&gt; struct index_reference&lt;UDT&gt; { typedef const UDT type; };

template &lt;&gt;
class default_index_traits&lt;UDT&gt;
{
typedef btree::support::size_t_codec codec;

public:
typedef UDT reference; // proxy
typedef endian::big_uint32_t index_position_type; // big enough

static std::size_t size(const UDT& x)
{
return sizeof(x.id)
+ default_index_traits&lt;boost::string_view&gt;::size(x.english)
+ default_index_traits&lt;boost::string_view&gt;::size(x.spanish);
}

static void build_flat_element(const UDT& x, char* dest,
std::size_t)
{
BOOST_ASSERT(dest);
std::memcpy(dest, &x.id, sizeof(x.id));
dest += sizeof(x.id);
std::size_t sz
= default_index_traits&lt;boost::string_view&gt;::size(x.english);
default_index_traits&lt;boost::string_view&gt;::build_flat_element(
x.english, dest, sz);
dest += sz;
default_index_traits&lt;boost::string_view&gt;::build_flat_element(
x.spanish, dest,
default_index_traits&lt;boost::string_view&gt;::size(x.spanish));
}

static reference dereference(const char* x)
{
return UDT
(default_index_traits&lt;int&gt;::dereference(x),
default_index_traits&lt;boost::string_view&gt;::dereference(
x + sizeof(UDT::id_type)),
default_index_traits&lt;boost::string_view&gt;::dereference(
x + sizeof(UDT::id_type)
+ default_index_traits&lt;boost::string_view&gt;::size(
x + sizeof(UDT::id_type))));
}
static std::size_t size(const char* x)
{
std::size_t sz = sizeof(UDT::id_type);
sz +=
default_index_traits&lt;boost::string_view&gt;::size(x + sz); // english
sz +=
default_index_traits&lt;boost::string_view&gt;::size(x + sz); // spanish
return sz;
}
};
template &lt;&gt;
inline void index_serialize&lt;UDT&gt;(const UDT& udt, flat_file_type& file)
{
index_serialize(udt.id, file);
index_serialize(udt.english, file);
index_serialize(udt.spanish, file);
}

template &lt;&gt;
inline index_reference&lt;UDT&gt;::type index_deserialize&lt;UDT&gt;(const char** flat)
{
UDT udt;
udt.id = index_deserialize&lt;UDT::id_type&gt;(flat);
udt.english = index_deserialize&lt;boost::string_view&gt;(flat);
udt.spanish = index_deserialize&lt;boost::string_view&gt;(flat);
return udt;
}
} // namespaces
}} // namespaces

#endif</pre>
</blockquote>
<p>Ugh! The actual UDT is easy, but the index traits adapter is ugly.
There&#39;s a branch already being worked on to simplify that.</p>
<p>So now let&#39;s build an index set of type UDT. The code looks like this [<code><a href="../example/udt_index_set.cpp">udt_index_set.cpp</a></code>]:</p>
<p>A couple of things are worth point out:</p>
<ul>
<li>The &quot;<code>// specializations to support btree indexes</code>&quot; section
tells the B-tree index how to serialize and de-serialize type <code>UDT</code>
in the flat file.</li>
<li>The &quot;<code>// function objects for different orderings</code>&quot; section
is used only in the <a href="#UDT-three-index-set">UDT three index set</a>
example so can be ignore for now.</li>
</ul>
<p>So now let&#39;s build an index set of type <code>UDT</code>. The code looks like this [<code><a href="../example/udt_index_set.cpp">udt_index_set.cpp</a></code>]:</p>
<blockquote>
<pre>
#include &lt;boost/btree/btree_index_set.hpp&gt;
Expand Down Expand Up @@ -742,6 +714,10 @@ <h2><a name="User-defined-types">User defined types</a> (UDTs)</h2>
</pre>
</blockquote>
<h2><a name="UDT-three-index-set">UDT three index set</a></h2>
<p>One of the advantages of separating the index file from the flat file is
that you can have multiple index files. This example [<code><a href="../example/udt_3_index_set.cpp">udt_3_index_set.cpp</a></code>]
creates three indexes so that we can access using the ID, English, or Spanish
elements as the key.</p>
<blockquote>
<pre>
#include &lt;boost/btree/btree_index_set.hpp&gt;
Expand Down Expand Up @@ -1090,7 +1066,7 @@ <h2><a name="Preloading">Preloading</a></h2>
<hr>

<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->10 September 2013<!--webbot bot="Timestamp" endspan i-checksum="39617" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->11 September 2013<!--webbot bot="Timestamp" endspan i-checksum="39619" --></p>

<p>© Copyright Beman Dawes, 2013</p>

Expand Down
79 changes: 22 additions & 57 deletions example/udt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef BOOST_BTREE_UDT_EXAMPLE_HPP
#define BOOST_BTREE_UDT_EXAMPLE_HPP

#include <boost/btree/index_helpers.hpp>
#include <boost/btree/support/string_view.hpp>
#include <iosfwd>

Expand All @@ -21,6 +22,7 @@ using boost::string_view;
struct UDT
{
typedef int id_type;

id_type id;
string_view english;
string_view spanish;
Expand Down Expand Up @@ -55,69 +57,32 @@ struct spanish_ordering
{return x.spanish < y.spanish;}
};

// specialization boost::btree::default_index_traits<UDT> ------------------//
// specializations to support btree indexes --------------------------------//

namespace boost
{
namespace btree
{
namespace btree
{
template <> struct index_reference<UDT> { typedef const UDT type; };

template <>
class default_index_traits<UDT>
{
typedef btree::support::size_t_codec codec;

public:
typedef UDT reference; // proxy
typedef endian::big_uint32_t index_position_type; // big enough

static std::size_t size(const UDT& x)
{
return sizeof(x.id)
+ default_index_traits<boost::string_view>::size(x.english)
+ default_index_traits<boost::string_view>::size(x.spanish);
}

static void build_flat_element(const UDT& x, char* dest,
std::size_t)
{
BOOST_ASSERT(dest);
std::memcpy(dest, &x.id, sizeof(x.id));
dest += sizeof(x.id);
std::size_t sz
= default_index_traits<boost::string_view>::size(x.english);
default_index_traits<boost::string_view>::build_flat_element(
x.english, dest, sz);
dest += sz;
default_index_traits<boost::string_view>::build_flat_element(
x.spanish, dest,
default_index_traits<boost::string_view>::size(x.spanish));
}

static reference dereference(const char* x)
{
return UDT
(default_index_traits<int>::dereference(x),
default_index_traits<boost::string_view>::dereference(
x + sizeof(UDT::id_type)),
default_index_traits<boost::string_view>::dereference(
x + sizeof(UDT::id_type)
+ default_index_traits<boost::string_view>::size(
x + sizeof(UDT::id_type))));
}
static std::size_t size(const char* x)
{
std::size_t sz = sizeof(UDT::id_type);
sz +=
default_index_traits<boost::string_view>::size(x + sz); // english
sz +=
default_index_traits<boost::string_view>::size(x + sz); // spanish
return sz;
}
};
template <>
inline void index_serialize<UDT>(const UDT& udt, flat_file_type& file)
{
index_serialize(udt.id, file);
index_serialize(udt.english, file);
index_serialize(udt.spanish, file);
}

template <>
inline index_reference<UDT>::type index_deserialize<UDT>(const char** flat)
{
UDT udt;
udt.id = index_deserialize<UDT::id_type>(flat);
udt.english = index_deserialize<boost::string_view>(flat);
udt.spanish = index_deserialize<boost::string_view>(flat);
return udt;
}
} // namespaces
}} // namespaces

#endif
///$endid
32 changes: 8 additions & 24 deletions include/boost/btree/btree_index_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,8 @@ class btree_index_map
// Effects: unconditional push_back into file(); index unaffected
{
file_position pos = base::file()->file_size();
std::size_t key_sz = index_serialize_size(x.first);
std::size_t mapped_sz = index_serialize_size(x.second);
base::file()->increment_file_size(key_sz + mapped_sz); // will resize if needed
char* p = base::file()->template data<char>() + pos;
index_serialize(x.first, &p, key_sz);
index_serialize(x.second, &p, mapped_sz);
index_serialize(x.first, *base::file());
index_serialize(x.second, *base::file());
return pos;
}

Expand Down Expand Up @@ -175,12 +171,8 @@ class btree_index_map
if (base::find(key) == base::end())
{
file_position pos = base::file()->file_size();
std::size_t key_sz = index_serialize_size(key);
std::size_t mapped_sz = index_serialize_size(mapped_value);
base::file()->increment_file_size(key_sz + mapped_sz); // will resize if needed
char* p = base::file()->template data<char>() + pos;
index_serialize(key, &p, key_sz);
index_serialize(mapped_value, &p, mapped_sz);
index_serialize(key, *base::file());
index_serialize(mapped_value,*base::file());
return insert_file_position(pos);
}
return std::pair<const_iterator, bool>(const_iterator(), false);
Expand Down Expand Up @@ -274,12 +266,8 @@ class btree_index_multimap
// Effects: unconditional push_back into file(); index unaffected
{
file_position pos = base::file()->file_size();
std::size_t key_sz = index_serialize_size(x.first);
std::size_t mapped_sz = index_serialize_size(x.second);
base::file()->increment_file_size(key_sz + mapped_sz); // will resize if needed
char* p = base::file()->template data<char>() + pos;
index_serialize(x.first, &p, key_sz);
index_serialize(x.second, &p, mapped_sz);
index_serialize(x.first, *base::file());
index_serialize(x.second, *base::file());
return pos;
}

Expand All @@ -302,12 +290,8 @@ class btree_index_multimap
{
BOOST_ASSERT((base::flags() & flags::read_only) == 0);
file_position pos = base::file()->file_size();
std::size_t key_sz = index_serialize_size(key);
std::size_t mapped_sz = index_serialize_size(mapped_value);
base::file()->increment_file_size(key_sz + mapped_sz); // will resize if needed
char* p = base::file()->template data<char>() + pos;
index_serialize(key, &p, key_sz);
index_serialize(mapped_value, &p, mapped_sz);
index_serialize(key, *base::file());
index_serialize(mapped_value,*base::file());
return insert_file_position(pos);
}
};
Expand Down
10 changes: 2 additions & 8 deletions include/boost/btree/btree_index_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,7 @@ class btree_index_set
// Effects: unconditional push_back into file(); index unaffected
{
file_position pos = base::file()->file_size();
std::size_t element_sz = index_serialize_size(x);
base::file()->increment_file_size(element_sz); // will resize if needed
char* p = base::file()->template data<char>() + pos;
index_serialize(x, &p, element_sz);
index_serialize(x, *base::file());
return pos;
}

Expand Down Expand Up @@ -251,10 +248,7 @@ class btree_index_multiset
// Effects: unconditional push_back into file(); index unaffected
{
file_position pos = base::file()->file_size();
std::size_t element_sz = index_serialize_size(x);
base::file()->increment_file_size(element_sz); // will resize if needed
char* p = base::file()->template data<char>() + pos;
index_serialize(x, &p, element_sz);
index_serialize(x, *base::file());
return pos;
}

Expand Down
Loading

0 comments on commit ccf846d

Please sign in to comment.