Commit a062735d authored by Antony T Curtis's avatar Antony T Curtis

Cleanup, simplify and optimize. Change makefile a little so that we have debug...

Cleanup, simplify and optimize. Change makefile a little so that we have debug symbols for the graph core.
parent b27a83d5
...@@ -59,9 +59,9 @@ noinst_HEADERS = ha_oqgraph.h \ ...@@ -59,9 +59,9 @@ noinst_HEADERS = ha_oqgraph.h \
graphcore-graph.h graphcore-types.h graphcore.h graphcore-graph.h graphcore-types.h graphcore.h
# oqgraph_probes.h # oqgraph_probes.h
noinst_LTLIBRARIES = libgraphcore.la #noinst_LTLIBRARIES = libgraphcore.la
libgraphcore_la_SOURCES = graphcore.cc graphcore-graph.cc oqgraph_shim.cc oqgraph_thunk.cc #libgraphcore_la_SOURCES = graphcore.cc graphcore-graph.cc oqgraph_shim.cc oqgraph_thunk.cc
libgraphcore_la_CXXFLAGS = $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS) #libgraphcore_la_CXXFLAGS = $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS)
if BUILD_OQGRAPH_FOR_MYSQL if BUILD_OQGRAPH_FOR_MYSQL
...@@ -73,8 +73,27 @@ endif !BUILD_OQGRAPH_STANDALONE ...@@ -73,8 +73,27 @@ endif !BUILD_OQGRAPH_STANDALONE
EXTRA_LTLIBRARIES = ha_oqgraph.la EXTRA_LTLIBRARIES = ha_oqgraph.la
mysqlplugin_LTLIBRARIES = @plugin_oqgraph_shared_target@ mysqlplugin_LTLIBRARIES = @plugin_oqgraph_shared_target@
ha_oqgraph_la_SOURCES = ha_oqgraph.cc oqgraph_judy.cc ha_oqgraph_la_SOURCES = ha_oqgraph.cc oqgraph_judy.cc \
ha_oqgraph_la_LIBADD = libgraphcore.la graphcore.cc graphcore-graph.cc \
oqgraph_thunk.cc oqgraph_shim.cc
#ha_oqgraph_la_LIBADD = libgraphcore.la
ha_oqgraph_la-graphcore.lo: graphcore.cc
$(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS) $(CXXFLAGS) -MT ha_oqgraph_la-graphcore.lo -MD -MP -MF $(DEPDIR)/ha_oqgraph_la-graphcore.Tpo -c -o ha_oqgraph_la-graphcore.lo `test -f 'graphcore.cc' || echo '$(srcdir)/'`graphcore.cc
mv -f $(DEPDIR)/ha_oqgraph_la-graphcore.Tpo $(DEPDIR)/ha_oqgraph_la-graphcore.Plo
ha_oqgraph_la-graphcore-graph.lo: graphcore-graph.cc
$(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS) $(CXXFLAGS) -MT ha_oqgraph_la-graphcore-graph.lo -MD -MP -MF $(DEPDIR)/ha_oqgraph_la-graphcore-graph.Tpo -c -o ha_oqgraph_la-graphcore-graph.lo `test -f 'graphcore.cc' || echo '$(srcdir)/'`graphcore-graph.cc
mv -f $(DEPDIR)/ha_oqgraph_la-graphcore-graph.Tpo $(DEPDIR)/ha_oqgraph_la-graphcore-graph.Plo
ha_oqgraph_la-oqgraph_shim.lo: oqgraph_shim.cc
$(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS) $(CXXFLAGS) -MT ha_oqgraph_la-oqgraph_shim.lo -MD -MP -MF $(DEPDIR)/ha_oqgraph_la-oqgraph_shim.Tpo -c -o ha_oqgraph_la-oqgraph_shim.lo `test -f 'oqgraph_shim.cc' || echo '$(srcdir)/'`oqgraph_shim.cc
mv -f $(DEPDIR)/ha_oqgraph_la-oqgraph_shim.Tpo $(DEPDIR)/ha_oqgraph_la-oqgraph_shim.Plo
ha_oqgraph_la-oqgraph_thunk.lo: oqgraph_thunk.cc
$(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS) $(CXXFLAGS) -MT ha_oqgraph_la-oqgraph_thunk.lo -MD -MP -MF $(DEPDIR)/ha_oqgraph_la-oqgraph_thunk.Tpo -c -o ha_oqgraph_la-oqgraph_thunk.lo `test -f 'oqgraph_thunk.cc' || echo '$(srcdir)/'`oqgraph_thunk.cc
mv -f $(DEPDIR)/ha_oqgraph_la-oqgraph_thunk.Tpo $(DEPDIR)/ha_oqgraph_la-oqgraph_thunk.Plo
# if HAVE_DTRACE # if HAVE_DTRACE
# ha_oqgraph_la_LIBADD += oqgraph_probes.o # ha_oqgraph_la_LIBADD += oqgraph_probes.o
......
...@@ -35,18 +35,6 @@ namespace boost ...@@ -35,18 +35,6 @@ namespace boost
{ {
typedef oqgraph3::graph Graph; typedef oqgraph3::graph Graph;
template <>
struct hash<graph_traits<oqgraph3::graph>::vertex_descriptor>
: public std::unary_function<
graph_traits<oqgraph3::graph>::vertex_descriptor, std::size_t>
{
std::size_t operator()(
const graph_traits<oqgraph3::graph>::vertex_descriptor& v) const
{
return boost::hash_value(v->id);
}
};
template<typename IndexMap = identity_property_map> template<typename IndexMap = identity_property_map>
struct two_bit_judy_map struct two_bit_judy_map
{ {
...@@ -175,61 +163,6 @@ namespace boost ...@@ -175,61 +163,6 @@ namespace boost
make_lazy_property_map(Container& c, Generator g) make_lazy_property_map(Container& c, Generator g)
{ return lazy_property_map<Container, Generator>(c, g); } { return lazy_property_map<Container, Generator>(c, g); }
#if 0
struct map_wra
struct property_traits< unordered_map_wrapper<K,T,H,P,A
template <class K, class T, class H, class P, class A>
struct property_traits< unordered_map<K,T,H,P,A> > {
typedef T value_type;
typedef K key_type;
typedef T& reference;
struct category
: public read_write_property_map_tag
, public lvalue_property_map_tag
{ };
friend reference get(
unordered_map<K,T,H,P,A>& m,
const key_type& k)
{
return m[k];
}
friend void put(
unordered_map<K,T,H,P,A>& m,
const key_type& k,
const value_type& v)
{
m[k]= v;
}
};
//template <class K, class T, class H, class P, class A>
//property_traits< unordered_map<K,T,H,P,A> >::reference
//get(unordered_map<K,T,H,P,A>& m,
// const property_traits< unordered_map<K,T,H,P,A> >::key_type& k)
//{ return m[ k ]; }
//template <class K, class T, class H, class P, class A>
//void put(
// unordered_map<K,T,H,P,A>& m,
// const property_traits< unordered_map<K,T,H,P,A> >::key_type& k,
// const property_traits< unordered_map<K,T,H,P,A> >::value_type& v)
//{ m[ k ] = v; }
//template <class K, class T, class H, class P, class A>
//property_traits< unordered_map<K,T,H,P,A>::reference
//get(unordered_map<K,T,H,P,A>& m,
// const graph_traits<oqgraph3::graph>::vertex_descriptor& v)
//{ return m[ v->id ]; }
#endif
} }
#endif #endif
...@@ -1060,9 +1060,8 @@ int edges_cursor::fetch_row(const row &row_info, row &result) ...@@ -1060,9 +1060,8 @@ int edges_cursor::fetch_row(const row &row_info, row &result)
{ {
edge_iterator it, end; edge_iterator it, end;
reference ref; reference ref;
size_t count= position; tie(it, end)= edges(share->g);
for (tie(it, end)= edges(share->g); count && it != end; ++it, --count) it+= position;
;
if (it != end) if (it != end)
ref= reference(position+1, *it); ref= reference(position+1, *it);
if (int res= fetch_row(row_info, result, ref)) if (int res= fetch_row(row_info, result, ref))
......
...@@ -90,6 +90,19 @@ open_query::judy_bitset::size_type open_query::judy_bitset::count() const ...@@ -90,6 +90,19 @@ open_query::judy_bitset::size_type open_query::judy_bitset::count() const
return rc; return rc;
} }
open_query::judy_bitset& open_query::judy_bitset::set(const judy_bitset& src)
{
if (!src.empty())
{
for (size_type pos= src.find_first(); pos != npos; pos= src.find_next(pos))
{
set(pos);
}
}
return *this;
}
open_query::judy_bitset::size_type open_query::judy_bitset::find_first() const open_query::judy_bitset::size_type open_query::judy_bitset::find_first() const
{ {
int rc; int rc;
......
...@@ -41,9 +41,21 @@ namespace open_query ...@@ -41,9 +41,21 @@ namespace open_query
: array(0) : array(0)
{ } { }
judy_bitset(const judy_bitset& src)
: array(0)
{
set(src);
}
~judy_bitset() ~judy_bitset()
{ clear(); } { clear(); }
judy_bitset& operator=(const judy_bitset& src)
{
clear();
return set(src);
}
void clear(); void clear();
bool empty() const { return !array; } bool empty() const { return !array; }
bool none() const { return npos == find_first(); } bool none() const { return npos == find_first(); }
...@@ -56,6 +68,8 @@ namespace open_query ...@@ -56,6 +68,8 @@ namespace open_query
return setbit(n); return setbit(n);
} }
judy_bitset& set(const judy_bitset& src);
judy_bitset& reset(size_type n); judy_bitset& reset(size_type n);
judy_bitset& flip(size_type n); judy_bitset& flip(size_type n);
bool test(size_type) const; bool test(size_type) const;
......
...@@ -26,3 +26,51 @@ ...@@ -26,3 +26,51 @@
#include "oqgraph_shim.h" #include "oqgraph_shim.h"
bool oqgraph3::edge_iterator::seek()
{
if (!_graph->_cursor ||
_graph->_rnd_pos > _offset ||
_graph->_cursor != _graph->_rnd_cursor.operator->())
{
_graph->_rnd_pos= 0;
_graph->_rnd_cursor= new cursor(_graph);
if (_graph->_rnd_cursor->seek_to(boost::none, boost::none))
_graph->_rnd_pos= size_t(-1);
}
while (_graph->_rnd_pos < _offset)
{
if (_graph->_rnd_cursor->seek_next())
{
_offset = size_t(-1);
return true;
}
_graph->_rnd_pos++;
}
return false;
}
oqgraph3::edge_iterator::value_type oqgraph3::edge_iterator::operator*()
{
seek();
return *_graph->_rnd_cursor;
}
bool oqgraph3::edge_iterator::operator==(const self& x)
{
if (_offset == size_t(-1) && x._offset != size_t(-1))
return const_cast<edge_iterator&>(x).seek();
if (_offset != size_t(-1) && x._offset == size_t(-1))
return seek();
return _offset == x._offset;
}
bool oqgraph3::edge_iterator::operator!=(const self& x)
{
if (_offset == size_t(-1) && x._offset != size_t(-1))
return !const_cast<edge_iterator&>(x).seek();
if (_offset != size_t(-1) && x._offset == size_t(-1))
return !seek();
return _offset != x._offset;
}
...@@ -53,62 +53,73 @@ namespace oqgraph3 ...@@ -53,62 +53,73 @@ namespace oqgraph3
struct edge_iterator struct edge_iterator
{ {
typedef edge_iterator self; typedef edge_iterator self;
typedef edge_descriptor value_type; typedef edge_info value_type;
typedef edge_descriptor& reference; typedef edge_info& reference;
typedef edge_descriptor pointer; typedef edge_info pointer;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category; typedef std::input_iterator_tag iterator_category;
edge_iterator() { } edge_iterator() { }
edge_iterator(row_cursor iter) : _iter(iter) { } edge_iterator(const graph_ptr& graph, size_t offset=0)
edge_descriptor operator*() { return _iter->_current; } : _graph(graph)
self& operator++() { ++(*_iter); return *this; } , _offset(offset) { }
self operator++(int) { self t= *this; ++(*this); return t; } edge_iterator(const edge_iterator& pos)
bool operator==(const self& x) { return _iter == x._iter; } : _graph(pos._graph)
bool operator!=(const self& x) { return _iter != x._iter; } , _offset(pos._offset) { }
boost::optional<row_cursor> _iter; value_type operator*();
self& operator+=(size_t n) { _offset+= n; return *this; }
self& operator++() { ++_offset; return *this; }
self operator++(int)
{ size_t temp= _offset++; return edge_iterator(_graph, temp); }
bool seek();
bool operator==(const self& x);
bool operator!=(const self& x);
graph_ptr _graph;
size_t _offset;
}; };
struct vertex_iterator struct vertex_iterator
{ {
typedef vertex_iterator self; typedef vertex_iterator self;
typedef vertex_descriptor value_type; typedef vertex_id value_type;
typedef vertex_descriptor& reference; typedef vertex_id& reference;
typedef vertex_descriptor pointer; typedef vertex_id pointer;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category; typedef std::input_iterator_tag iterator_category;
vertex_iterator() { } vertex_iterator() { }
vertex_iterator(edge_iterator iter) : _iter(iter) { } vertex_iterator(const cursor_ptr& pos) : _cursor(pos.operator->()) { }
vertex_descriptor operator*() vertex_id operator*() const
{ {
if (!_seen.test(_iter._iter->operator*().first)) edge_info edge(*_cursor);
return _iter._iter->_cache->vertex(_iter._iter->operator*().first); if (!_seen.test(edge.origid()))
return edge.origid();
else else
return _iter._iter->_cache->vertex(_iter._iter->operator*().second); return edge.destid();
} }
self& operator++() self& operator++()
{ {
if (!_seen.test(_iter._iter->operator*().first)) edge_info edge(*_cursor);
if (!_seen.test(edge.origid()))
{ {
_seen.set(_iter._iter->operator*().first); _seen.set(edge.origid());
} }
else else
{ {
_seen.set(_iter._iter->operator*().second); _seen.set(edge.destid());
} }
while (_iter._iter->_current && while (_seen.test(edge.origid()) && _seen.test(edge.destid()))
_seen.test(_iter._iter->operator*().first) &&
_seen.test(_iter._iter->operator*().second))
{ {
++_iter; if (_cursor->seek_next())
break;
edge= _cursor;
} }
return *this; return *this;
} }
self operator++(int) { self t= *this; ++(*this); return t; } self operator++(int) { cursor* t(new cursor(*_cursor)); ++(*this); return vertex_iterator(t); }
bool operator==(const self& x) { return _iter == x._iter; } bool operator==(const self& x) { return *_cursor == *x._cursor; }
bool operator!=(const self& x) { return _iter != x._iter; } bool operator!=(const self& x) { return *_cursor != *x._cursor; }
edge_iterator _iter; cursor_ptr _cursor;
open_query::judy_bitset _seen; open_query::judy_bitset _seen;
}; };
...@@ -116,64 +127,60 @@ namespace oqgraph3 ...@@ -116,64 +127,60 @@ namespace oqgraph3
struct out_edge_iterator struct out_edge_iterator
{ {
typedef out_edge_iterator self; typedef out_edge_iterator self;
typedef vertex_info::edge_list_type::const_iterator iter_type; typedef edge_info value_type;
typedef edge_info& reference;
typedef edge_descriptor value_type; typedef edge_info pointer;
typedef edge_descriptor& reference;
typedef edge_descriptor pointer;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category; typedef std::input_iterator_tag iterator_category;
out_edge_iterator() { } out_edge_iterator() { }
out_edge_iterator(iter_type iter, const vertex_descriptor& v) out_edge_iterator(const cursor_ptr& cursor) : _cursor(cursor) { }
: _iter(iter), _v(v) { } value_type operator*() { return value_type(_cursor); }
edge_descriptor operator*() self& operator++() { _cursor->seek_next(); return *this; }
{ return _v->_cache->edge(edge_key(*_iter)); } self operator++(int)
self& operator++() { ++_iter; return *this; } { cursor_ptr t(new cursor(*_cursor)); ++(*this); return out_edge_iterator(t); }
self operator++(int) { self t= *this; ++(*this); return t; } bool operator==(const self& x) { return _cursor == x._cursor; }
bool operator==(const self& x) { return _iter == x._iter; } bool operator!=(const self& x) { return _cursor != x._cursor; }
bool operator!=(const self& x) { return _iter != x._iter; } cursor_ptr _cursor;
iter_type _iter;
vertex_descriptor _v;
}; };
struct in_edge_iterator struct in_edge_iterator
{ {
typedef in_edge_iterator self; typedef in_edge_iterator self;
typedef vertex_info::edge_list_type::const_iterator iter_type; typedef edge_info value_type;
typedef edge_info& reference;
typedef edge_descriptor value_type; typedef edge_info pointer;
typedef edge_descriptor& reference;
typedef edge_descriptor pointer;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category; typedef std::input_iterator_tag iterator_category;
in_edge_iterator() { } in_edge_iterator() { }
in_edge_iterator(iter_type iter, const vertex_descriptor& v) in_edge_iterator(const cursor_ptr& cursor) : _cursor(cursor) { }
: _iter(iter), _v(v) { } value_type operator*() { return value_type(_cursor); }
edge_descriptor operator*() self& operator++() { _cursor->seek_next(); return *this; }
{ return _v->_cache->edge(edge_key(*_iter)); } self operator++(int)
self& operator++() { ++_iter; return *this; } { cursor_ptr t(new cursor(*_cursor)); ++(*this); return in_edge_iterator(t); }
self operator++(int) { self t= *this; ++(*this); return t; } bool operator==(const self& x) { return _cursor == x._cursor; }
bool operator==(const self& x) { return _iter == x._iter; } bool operator!=(const self& x) { return _cursor != x._cursor; }
bool operator!=(const self& x) { return _iter != x._iter; } cursor_ptr _cursor;
iter_type _iter;
vertex_descriptor _v;
}; };
struct vertex_index_property_map struct vertex_index_property_map
{ {
typedef vertex_id value_type; typedef vertex_id value_type;
typedef value_type reference; typedef value_type reference;
typedef vertex_descriptor key_type; typedef vertex_id key_type;
typedef boost::readable_property_map_tag category; typedef boost::readable_property_map_tag category;
vertex_index_property_map(const graph& g) : _g(g) { } vertex_index_property_map(const graph& g) : _g(g) { }
const graph& _g; const graph& _g;
friend inline reference
get(const vertex_index_property_map&, key_type key)
{ return key; }
}; };
struct edge_weight_property_map struct edge_weight_property_map
{ {
typedef weight_t value_type; typedef weight_t value_type;
typedef value_type reference; typedef value_type reference;
typedef edge_descriptor key_type; typedef edge_info key_type;
typedef boost::readable_property_map_tag category; typedef boost::readable_property_map_tag category;
edge_weight_property_map(const graph& g) : _g(g) { } edge_weight_property_map(const graph& g) : _g(g) { }
const graph& _g; const graph& _g;
...@@ -181,9 +188,9 @@ namespace oqgraph3 ...@@ -181,9 +188,9 @@ namespace oqgraph3
struct edge_index_property_map struct edge_index_property_map
{ {
typedef edge_key::ref_type value_type; typedef cursor_ptr value_type;
typedef const edge_key::ref_type& reference; typedef cursor_ptr reference;
typedef edge_descriptor key_type; typedef edge_info key_type;
typedef boost::readable_property_map_tag category; typedef boost::readable_property_map_tag category;
edge_index_property_map(const graph& g) : _g(g) { } edge_index_property_map(const graph& g) : _g(g) { }
const graph& _g; const graph& _g;
...@@ -196,11 +203,11 @@ namespace boost ...@@ -196,11 +203,11 @@ namespace boost
template<> template<>
struct graph_traits<oqgraph3::graph> struct graph_traits<oqgraph3::graph>
{ {
typedef oqgraph3::vertex_descriptor vertex_descriptor; typedef oqgraph3::vertex_id vertex_descriptor;
typedef oqgraph3::edge_descriptor edge_descriptor; typedef oqgraph3::edge_info edge_descriptor;
typedef boost::adjacency_iterator_generator< typedef boost::adjacency_iterator_generator<
oqgraph3::graph, oqgraph3::graph,
oqgraph3::vertex_descriptor, oqgraph3::vertex_id,
oqgraph3::out_edge_iterator>::type adjacency_iterator; oqgraph3::out_edge_iterator>::type adjacency_iterator;
typedef oqgraph3::out_edge_iterator out_edge_iterator; typedef oqgraph3::out_edge_iterator out_edge_iterator;
typedef oqgraph3::in_edge_iterator in_edge_iterator; typedef oqgraph3::in_edge_iterator in_edge_iterator;
...@@ -215,8 +222,8 @@ namespace boost ...@@ -215,8 +222,8 @@ namespace boost
typedef oqgraph3::edges_size_type edges_size_type; typedef oqgraph3::edges_size_type edges_size_type;
typedef oqgraph3::degree_size_type degree_size_type; typedef oqgraph3::degree_size_type degree_size_type;
static inline vertex_descriptor null_vertex() static inline oqgraph3::vertex_id null_vertex()
{ return oqgraph3::vertex_descriptor(); } { return oqgraph3::vertex_id(-1); }
}; };
template<> template<>
...@@ -260,46 +267,103 @@ namespace boost ...@@ -260,46 +267,103 @@ namespace boost
typedef no_edge_bundle type; typedef no_edge_bundle type;
}; };
inline graph_traits<oqgraph3::graph>::vertex_descriptor
source(
const graph_traits<oqgraph3::graph>::edge_descriptor& e,
const oqgraph3::graph&)
{ return e.origid(); }
inline graph_traits<oqgraph3::graph>::vertex_descriptor
target(
const graph_traits<oqgraph3::graph>::edge_descriptor& e,
const oqgraph3::graph&)
{ return e.destid(); }
inline std::pair< inline std::pair<
graph_traits<oqgraph3::graph>::out_edge_iterator, graph_traits<oqgraph3::graph>::out_edge_iterator,
graph_traits<oqgraph3::graph>::out_edge_iterator> graph_traits<oqgraph3::graph>::out_edge_iterator>
out_edges( out_edges(
graph_traits<oqgraph3::graph>::vertex_descriptor v, graph_traits<oqgraph3::graph>::vertex_descriptor v,
const oqgraph3::graph&) const oqgraph3::graph& g)
{ {
const oqgraph3::vertex_info::edge_list_type& oqgraph3::cursor*
iter= v->out_edges(); end= new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g));
oqgraph3::cursor*
start= new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g));
start->seek_to(v, boost::none);
return std::make_pair( return std::make_pair(
graph_traits<oqgraph3::graph>::out_edge_iterator(iter.begin(), v), graph_traits<oqgraph3::graph>::out_edge_iterator(start),
graph_traits<oqgraph3::graph>::out_edge_iterator(iter.end(), v)); graph_traits<oqgraph3::graph>::out_edge_iterator(end));
} }
inline graph_traits<oqgraph3::graph>::degree_size_type
out_degree(
graph_traits<oqgraph3::graph>::vertex_descriptor v,
const oqgraph3::graph& g)
{
std::size_t count = 0;
for (std::pair<
graph_traits<oqgraph3::graph>::out_edge_iterator,
graph_traits<oqgraph3::graph>::out_edge_iterator> i= out_edges(v, g);
i.first != i.second; ++i.first)
{
++count;
}
return count;
}
inline std::pair< inline std::pair<
graph_traits<oqgraph3::graph>::in_edge_iterator, graph_traits<oqgraph3::graph>::in_edge_iterator,
graph_traits<oqgraph3::graph>::in_edge_iterator> graph_traits<oqgraph3::graph>::in_edge_iterator>
in_edges( in_edges(
graph_traits<oqgraph3::graph>::vertex_descriptor v, graph_traits<oqgraph3::graph>::vertex_descriptor v,
const oqgraph3::graph&) const oqgraph3::graph& g)
{ {
const oqgraph3::vertex_info::edge_list_type& oqgraph3::cursor*
iter= v->out_edges(); end= new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g));
oqgraph3::cursor*
start= new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g));
start->seek_to(boost::none, v);
return std::make_pair( return std::make_pair(
graph_traits<oqgraph3::graph>::in_edge_iterator(iter.begin(), v), graph_traits<oqgraph3::graph>::in_edge_iterator(start),
graph_traits<oqgraph3::graph>::in_edge_iterator(iter.end(), v)); graph_traits<oqgraph3::graph>::in_edge_iterator(end));
} }
inline graph_traits<oqgraph3::graph>::degree_size_type
in_degree(
graph_traits<oqgraph3::graph>::vertex_descriptor v,
const oqgraph3::graph& g)
{
std::size_t count = 0;
for (std::pair<
graph_traits<oqgraph3::graph>::in_edge_iterator,
graph_traits<oqgraph3::graph>::in_edge_iterator> it= in_edges(v, g);
it.first != it.second; ++it.first)
{
++count;
}
return count;
}
// EdgeListGraph concepts // EdgeListGraph concepts
inline std::pair< inline std::pair<
graph_traits<oqgraph3::graph>::edge_iterator, graph_traits<oqgraph3::graph>::edge_iterator,
graph_traits<oqgraph3::graph>::edge_iterator> graph_traits<oqgraph3::graph>::edge_iterator>
edges(const oqgraph3::graph& _g) edges(const oqgraph3::graph& g)
{ {
oqgraph3::graph& g= const_cast<oqgraph3::graph&>(_g); std::size_t end= std::size_t(-1);
std::size_t start= end;
if (g.num_edges())
start= 0;
return std::make_pair( return std::make_pair(
graph_traits<oqgraph3::graph>::edge_iterator( graph_traits<oqgraph3::graph>::edge_iterator(
oqgraph3::row_cursor(&g).first()), const_cast<oqgraph3::graph*>(&g), start),
graph_traits<oqgraph3::graph>::edge_iterator( graph_traits<oqgraph3::graph>::edge_iterator(
oqgraph3::row_cursor(&g).end())); const_cast<oqgraph3::graph*>(&g), end));
} }
inline std::pair< inline std::pair<
...@@ -307,12 +371,13 @@ namespace boost ...@@ -307,12 +371,13 @@ namespace boost
graph_traits<oqgraph3::graph>::vertex_iterator> graph_traits<oqgraph3::graph>::vertex_iterator>
vertices(const oqgraph3::graph& g) vertices(const oqgraph3::graph& g)
{ {
std::pair< oqgraph3::cursor*
graph_traits<oqgraph3::graph>::edge_iterator, start= new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g));
graph_traits<oqgraph3::graph>::edge_iterator> epair= edges(g); start->seek_to(boost::none, boost::none);
return std::make_pair( return std::make_pair(
graph_traits<oqgraph3::graph>::vertex_iterator(epair.first), graph_traits<oqgraph3::graph>::vertex_iterator(start),
graph_traits<oqgraph3::graph>::vertex_iterator(epair.second)); graph_traits<oqgraph3::graph>::vertex_iterator(
new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g))));
} }
inline graph_traits<oqgraph3::graph>::vertices_size_type inline graph_traits<oqgraph3::graph>::vertices_size_type
...@@ -359,7 +424,7 @@ namespace boost ...@@ -359,7 +424,7 @@ namespace boost
const property_map< const property_map<
oqgraph3::graph, oqgraph3::graph,
edge_weight_t>::const_type::key_type& key) edge_weight_t>::const_type::key_type& key)
{ return oqgraph3::row_cursor(key, const_cast<oqgraph3::graph*>(&g))->_weight; } { return key.weight(); }
inline property_map< inline property_map<
oqgraph3::graph, oqgraph3::graph,
...@@ -371,13 +436,12 @@ namespace boost ...@@ -371,13 +436,12 @@ namespace boost
inline property_map< inline property_map<
oqgraph3::graph, oqgraph3::graph,
edge_weight_t>::const_type::reference edge_weight_t>::const_type::reference
get(property_map<oqgraph3::graph, get(const property_map<oqgraph3::graph,
edge_weight_t>::const_type p, edge_weight_t>::const_type& p,
const property_map< const property_map<
oqgraph3::graph, oqgraph3::graph,
edge_weight_t>::const_type::key_type& key) edge_weight_t>::const_type::key_type& key)
{ return oqgraph3::row_cursor( { return key.weight(); }
key, const_cast<oqgraph3::graph*>(&p._g))->_weight; }
inline property_map< inline property_map<
oqgraph3::graph, oqgraph3::graph,
...@@ -387,349 +451,33 @@ namespace boost ...@@ -387,349 +451,33 @@ namespace boost
const property_map< const property_map<
oqgraph3::graph, oqgraph3::graph,
edge_index_t>::const_type::key_type& key) edge_index_t>::const_type::key_type& key)
{ return key->_ref; } { return key._cursor; }
inline property_map<oqgraph3::graph, edge_index_t>::const_type inline property_map<oqgraph3::graph, edge_index_t>::const_type
get(edge_index_t, const oqgraph3::graph& g) get(edge_index_t, const oqgraph3::graph& g)
{ return property_map<oqgraph3::graph, edge_index_t>::const_type(g); } { return property_map<oqgraph3::graph, edge_index_t>::const_type(g); }
inline property_map<oqgraph3::graph, edge_index_t>::const_type::reference inline property_map<oqgraph3::graph, edge_index_t>::const_type::reference
get(property_map<oqgraph3::graph, edge_index_t>::const_type, get(const property_map<oqgraph3::graph, edge_index_t>::const_type&,
const property_map<oqgraph3::graph, const property_map<oqgraph3::graph,
edge_index_t>::const_type::key_type& key) edge_index_t>::const_type::key_type& key)
{ return key->_ref; } { return key._cursor; }
inline property_map<oqgraph3::graph, vertex_index_t>::const_type::reference inline property_map<oqgraph3::graph, vertex_index_t>::const_type::reference
get(vertex_index_t, const oqgraph3::graph&, get(vertex_index_t, const oqgraph3::graph&,
const property_map<oqgraph3::graph, const property_map<oqgraph3::graph,
vertex_index_t>::const_type::key_type& key) vertex_index_t>::const_type::key_type& key)
{ return key->id; } { return key; }
inline property_map<oqgraph3::graph, vertex_index_t>::const_type inline property_map<oqgraph3::graph, vertex_index_t>::const_type
get(vertex_index_t, const oqgraph3::graph& g) get(vertex_index_t, const oqgraph3::graph& g)
{ return property_map<oqgraph3::graph, vertex_index_t>::const_type(g); } { return property_map<oqgraph3::graph, vertex_index_t>::const_type(g); }
inline property_map<oqgraph3::graph, vertex_index_t>::const_type::reference
get(property_map<oqgraph3::graph, vertex_index_t>::const_type,
const property_map<oqgraph3::graph,
vertex_index_t>::const_type::key_type& key)
{ return key->id; }
inline optional<graph_traits<oqgraph3::graph>::vertex_descriptor> inline optional<graph_traits<oqgraph3::graph>::vertex_descriptor>
find_vertex(oqgraph3::vertex_id id, const oqgraph3::graph& g) find_vertex(oqgraph3::vertex_id id, const oqgraph3::graph& g)
{ {
graph_traits<oqgraph3::graph>::vertex_descriptor tmp( return id;
const_cast<oqgraph3::graph&>(g).vertex(id));
if (tmp)
return tmp;
else
return none;
}
}
#if 0
class OQGraph
{
public:
typedef OQGraph graph_type;
// more commonly used graph types
typedef void stored_vertex;
typedef std::size_t vertices_size_type;
typedef std::size_t edges_size_type;
typedef std::size_t degree_size_type;
typedef oqgraph3::vertex_descriptor vertex_descriptor;
typedef oqgraph3::edge_descriptor edge_descriptor;
// iterator types
typedef boost::adjacency_iterator_generator<
OQGraph,
vertex_descriptor,
out_edge_iterator>::type adjacency_iterator;
// miscellaneous types
typedef boost::directed_graph_tag graph_tag;
typedef boost::directed_tag directed_category;
typedef boost::allow_parallel_edge_tag edge_parallel_category;
typedef OQGraphTraversalCategory traversal_category;
typedef oqgraph3::vertex_id vertex_index_type;
typedef oqgraph3::edge_key::ref_type edge_index_type;
typedef void edge_property_type;
typedef void vertex_property_type;
typedef void graph_property_type;
// Graph concepts
static vertex_descriptor null_vertex()
{ return vertex_descriptor(); }
oqgraph3::graph_cache_ptr _cache;
vertex_descriptor source(edge_descriptor e) const
{ return _cache->vertex(oqgraph3::row_cursor(e)->first); }
vertex_descriptor target(edge_descriptor e) const
{ return _cache->vertex(oqgraph3::row_cursor(e)->second); }
degree_size_type out_degree(vertex_descriptor v) const
{ return v->out_edges().size(); }
std::pair<out_edge_iterator,out_edge_iterator>
out_edges(vertex_descriptor v) const
{
const oqgraph3::vertex_info::edge_list_type&
iter= v->out_edges();
return std::make_pair(
out_edge_iterator(iter.begin(), v),
out_edge_iterator(iter.end(), v));
}
degree_size_type in_degree(vertex_descriptor v) const
{ return v->in_edges().size(); }
std::pair<in_edge_iterator,in_edge_iterator>
in_edges(vertex_descriptor v) const
{
const oqgraph3::vertex_info::edge_list_type&
iter= v->out_edges();
return std::make_pair(
in_edge_iterator(iter.begin(), v),
in_edge_iterator(iter.end(), v));
}
degree_size_type degree(vertex_descriptor v) const
{ return v->degree(); }
vertex_descriptor vertex() const
{ return null_vertex(); }
std::pair<edge_descriptor, bool> edge(
vertex_descriptor u, vertex_descriptor v) const
{ edge_descriptor result= _cache->edge(u, v);
return std::make_pair(result, bool(result)); }
edges_size_type num_edges() const
{ return _cache->num_edges(); }
std::pair<edge_iterator,edge_iterator>
edges() const
{
return std::make_pair(
edge_iterator(oqgraph3::row_cursor(_cache).first()),
edge_iterator(oqgraph3::row_cursor(_cache).end()));
} }
};
struct vertex_index_property_map
{
typedef oqgraph3::vertex_id value_type;
typedef value_type reference;
typedef OQGraph::vertex_descriptor key_type;
typedef boost::readable_property_map_tag category;
};
struct edge_weight_property_map
{
typedef oqgraph3::weight_t value_type;
typedef value_type reference;
typedef OQGraph::edge_descriptor key_type;
typedef boost::readable_property_map_tag category;
};
struct edge_index_property_map
{
typedef oqgraph3::edge_key::ref_type value_type;
typedef const oqgraph3::edge_key::ref_type& reference;
typedef OQGraph::edge_descriptor key_type;
typedef boost::readable_property_map_tag category;
};
}
namespace boost
{
template<>
struct property_map<open_query::OQGraph, edge_weight_t>
{
typedef void type;
typedef open_query::edge_weight_property_map const_type;
};
template<>
struct property_map<open_query::OQGraph, vertex_index_t>
{
typedef void type;
typedef open_query::vertex_index_property_map const_type;
};
template<>
struct property_map<open_query::OQGraph, edge_index_t>
{
typedef void type;
typedef open_query::edge_index_property_map const_type;
};
property_map<
open_query::OQGraph,
edge_weight_t>::const_type::reference
get(
edge_weight_t,
const open_query::OQGraph&,
const property_map<
open_query::OQGraph,
edge_weight_t>::const_type::key_type& key)
{ return oqgraph3::row_cursor(key)->_weight; }
property_map<
open_query::OQGraph,
edge_weight_t>::const_type
get(edge_weight_t,
const open_query::OQGraph&)
{ return property_map<open_query::OQGraph, edge_weight_t>::const_type(); }
property_map<
open_query::OQGraph,
edge_weight_t>::const_type::reference
get(property_map<open_query::OQGraph,
edge_weight_t>::const_type,
const property_map<
open_query::OQGraph,
edge_weight_t>::const_type::key_type& key)
{ return oqgraph3::row_cursor(key)->_weight; }
property_map<
open_query::OQGraph,
edge_index_t>::const_type::reference
get(edge_index_t,
const open_query::OQGraph&,
const property_map<
open_query::OQGraph,
edge_index_t>::const_type::key_type& key)
{ return key->_ref; }
property_map<open_query::OQGraph, edge_index_t>::const_type
get(edge_index_t, const open_query::OQGraph&)
{ return property_map<open_query::OQGraph, edge_index_t>::const_type(); }
property_map<open_query::OQGraph, edge_index_t>::const_type::reference
get(property_map<open_query::OQGraph, edge_index_t>::const_type,
const property_map<open_query::OQGraph, edge_index_t>::const_type::key_type& key)
{ return key->_ref; }
property_map<open_query::OQGraph, vertex_index_t>::const_type::reference
get(vertex_index_t, const open_query::OQGraph&,
const property_map<open_query::OQGraph, vertex_index_t>::const_type::key_type& key)
{ return key->id; }
property_map<open_query::OQGraph, vertex_index_t>::const_type
get(vertex_index_t, const open_query::OQGraph&)
{ return property_map<open_query::OQGraph, vertex_index_t>::const_type(); }
property_map<open_query::OQGraph, vertex_index_t>::const_type::reference
get(property_map<open_query::OQGraph, vertex_index_t>::const_type,
const property_map<open_query::OQGraph, vertex_index_t>::const_type::key_type& key)
{ return key->id; }
optional<open_query::OQGraph::vertex_descriptor>
find_vertex(oqgraph3::vertex_id id, const open_query::OQGraph& g)
{ open_query::OQGraph::vertex_descriptor tmp(g._cache->vertex(id));
if (tmp)
return tmp;
else
return none;
}
// IncidenceGraph concepts
inline open_query::OQGraph::vertex_descriptor
source(
open_query::OQGraph::edge_descriptor e,
open_query::OQGraph const& g)
{ return g.source(e); }
inline open_query::OQGraph::vertex_descriptor
target(
open_query::OQGraph::edge_descriptor e,
open_query::OQGraph const& g)
{ return g.target(e); }
inline open_query::OQGraph::degree_size_type
out_degree(
open_query::OQGraph::vertex_descriptor v,
open_query::OQGraph const& g)
{ return g.out_degree(v); }
inline std::pair<
open_query::OQGraph::out_edge_iterator,
open_query::OQGraph::out_edge_iterator
>
out_edges(
open_query::OQGraph::vertex_descriptor v,
open_query::OQGraph const& g)
{ return g.out_edges(v); }
// BidirectionalGraph concepts
inline open_query::OQGraph::degree_size_type
in_degree(
open_query::OQGraph::vertex_descriptor v,
open_query::OQGraph const& g)
{ return g.in_degree(v); }
inline std::pair<
open_query::OQGraph::in_edge_iterator,
open_query::OQGraph::in_edge_iterator
>
in_edges(
open_query::OQGraph::vertex_descriptor v,
open_query::OQGraph const& g)
{ return g.in_edges(v); }
inline open_query::OQGraph::degree_size_type
degree(
open_query::OQGraph::vertex_descriptor v,
open_query::OQGraph const& g)
{ return g.degree(v); }
// AdjacencyGraph concepts
//inline std::pair<
// open_query::OQGraph::adjacency_iterator,
// open_query::OQGraph::adjacency_iterator
// >
//adjacent_vertices(
// open_query::OQGraph::vertex_descriptor v,
// open_query::OQGraph const& g)
//{ return g.adjacent_vertices(v, g.impl()); }
open_query::OQGraph::vertex_descriptor
vertex(
open_query::OQGraph::vertices_size_type n,
open_query::OQGraph const& g)
{ return g.vertex(); }
std::pair<open_query::OQGraph::edge_descriptor, bool>
edge(
open_query::OQGraph::vertex_descriptor u,
open_query::OQGraph::vertex_descriptor v,
open_query::OQGraph const& g)
{ return g.edge(u, v); }
// Vertex index management
inline open_query::OQGraph::vertex_index_type
get_vertex_index(
open_query::OQGraph::vertex_descriptor v,
open_query::OQGraph const& g)
{ return get(boost::vertex_index, g, v); }
// Edge index management
inline const open_query::OQGraph::edge_index_type&
get_edge_index(
open_query::OQGraph::edge_descriptor v,
open_query::OQGraph const& g)
{ return get(boost::edge_index, g, v); }
} }
#endif
...@@ -31,982 +31,523 @@ ...@@ -31,982 +31,523 @@
#define MYSQL_SERVER #define MYSQL_SERVER
#include "mysql_priv.h" #include "mysql_priv.h"
oqgraph3::vertex_info::~vertex_info() static int debugid = 0;
{ }
void oqgraph3::vertex_info::release() oqgraph3::vertex_id oqgraph3::edge_info::origid() const
{ { return _cursor->get_origid(); }
if (!--(_ref_count))
{
oqgraph3::graph& cache= *_cache;
oqgraph3::graph::vertex_cache_type::const_iterator it;
if (!_on_gc) oqgraph3::vertex_id oqgraph3::edge_info::destid() const
{ { return _cursor->get_destid(); }
cache._gc_vertices.push(this);
_on_gc= true;
}
while (!cache._gc_running && cache._gc_vertices.size() > 64) oqgraph3::weight_t oqgraph3::edge_info::weight() const
{ { return _cursor->get_weight(); }
cache._gc_running= true;
if (cache._gc_vertices.front()->_ref_count ||
(it= cache._cache_vertices.find(*cache._gc_vertices.front()))
== cache._cache_vertices.end())
{
cache._gc_vertices.front()->_on_gc= false;
}
else
{
cache._cache_vertices.quick_erase(it);
}
cache._gc_vertices.pop();
cache._gc_running= false;
}
}
}
oqgraph3::edge_key::~edge_key() bool oqgraph3::cursor_ptr::operator==(const cursor_ptr& x) const
{ }
void oqgraph3::edge_key::release() const
{ {
if (!--(_ref_count)) if (get() == x.get())
{ return true;
oqgraph3::graph& cache= *_cache; return (*this)->record_position() == x->_position;
oqgraph3::graph::edge_cache_type::const_iterator it;
if (!_on_gc)
{
cache._gc_edges.push(const_cast<edge_key*>(this));
_on_gc= true;
}
while (!cache._gc_running && cache._gc_edges.size() > 512)
{
cache._gc_running= true;
if (cache._gc_edges.front()->_ref_count ||
(it= cache._cache_edges.find(*cache._gc_edges.front()))
== cache._cache_edges.end())
{
cache._gc_edges.front()->_on_gc= false;
}
else
{
cache._cache_edges.quick_erase(it);
}
cache._gc_edges.pop();
cache._gc_running= false;
}
}
} }
oqgraph3::graph::graph( bool oqgraph3::cursor_ptr::operator!=(const cursor_ptr& x) const
::TABLE* table,
::Field* source,
::Field* target,
::Field* weight)
: _gc_running(false)
, _ref_count(0)
, _table(table)
, _source(source)
, _target(target)
, _weight(weight)
{ {
bitmap_set_bit(table->read_set, source->field_index); if (get() == x.get())
bitmap_set_bit(table->read_set, target->field_index); return false;
if (weight) return (*this)->record_position() != x->_position;
bitmap_set_bit(table->read_set, weight->field_index);
table->file->column_bitmaps_signal();
} }
oqgraph3::graph::~graph() oqgraph3::cursor::cursor(const graph_ptr& graph)
: _ref_count(0)
, _graph(graph)
, _index(-1)
, _parts(0)
, _key()
, _position()
, _debugid(++debugid)
{ } { }
oqgraph3::row_cursor& oqgraph3::row_cursor::operator++() oqgraph3::cursor::cursor(const cursor& src)
{ : _ref_count(0)
printf("%s:%d\n", __func__, __LINE__); , _graph(src._graph)
if (!_current) , _index(src._index)
return *this; , _parts(src._parts)
, _key(src._key)
graph::edge_cache_type::iterator , _position(src.record_position())
current= _cache->_cache_edges.find(*_current); , _debugid(++debugid)
{ }
if (current->second._next)
{
graph::edge_cache_type::iterator next=
_cache->_cache_edges.find(edge_key(*current->second._next));
if (_cache->_cache_edges.end() != next)
{
_current.reset(&next->first);
return *this;
}
}
TABLE& table= *_cache->_table;
table.file->ha_index_init(0, 1);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); oqgraph3::cursor::~cursor()
if (table.file->ha_index_read_map( {
table.record[0], if (this == _graph->_cursor)
reinterpret_cast<const uchar*>(current->first._ref.data()),
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_AFTER_KEY))
{ {
table.file->ha_index_end(); if (_graph->_cursor->_index >= 0)
_current.reset(0); _graph->_table->file->ha_index_end();
return *this; else
_graph->_table->file->ha_rnd_end();
_graph->_cursor= 0;
_graph->_stale= false;
} }
update_virtual_fields(table.in_use, &table);
table.file->ha_index_end();
edge_key tmp(table.key_info->key_length, _cache);
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator
found= _cache->_cache_edges.find(tmp);
if (_cache->_cache_edges.end() != found)
{
// we already had a row, link them together
found->second._prev= &current->first._ref;
current->second._next= &found->first._ref;
_current.reset(&found->first);
return *this;
}
_current.reset(&_cache->_cache_edges.insert(
std::make_pair(
tmp,
row_info(
_cache->_source->val_int(),
_cache->_target->val_int(),
_cache->_weight ? _cache->_weight->val_real() : 1.0,
&_current->_ref,
0
)
)).first->first);
return *this;
} }
oqgraph3::row_cursor& oqgraph3::row_cursor::first() const std::string& oqgraph3::cursor::record_position() const
{ {
printf("%s:%d\n", __func__, __LINE__); if (_graph->_stale && _graph->_cursor)
TABLE& table= *_cache->_table;
table.file->ha_index_init(0, 1);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_first");
if (!table.file->ha_index_first(table.record[0]))
{ {
update_virtual_fields(table.in_use, &table); TABLE& table= *_graph->_table;
table.file->position(table.record[0]);
_graph->_cursor->_position.assign(
(const char*) table.file->ref, table.file->ref_length);
edge_key tmp(table.key_info->key_length, _cache); if (_graph->_cursor->_index >= 0)
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator
found= _cache->_cache_edges.find(tmp);
if (found != _cache->_cache_edges.end())
{
// we already had a row
_current.reset(&found->first);
}
else
{ {
_current.reset(&_cache->_cache_edges.insert( key_copy((uchar*) _graph->_cursor->_key.data(), table.record[0],
std::make_pair( table.s->key_info + _index, table.s->key_info[_index].key_length, true);
tmp,
row_info(
_cache->_source->val_int(),
_cache->_target->val_int(),
_cache->_weight ? _cache->_weight->val_real() : 1.0,
0,
0
)
)).first->first);
} }
}
table.file->ha_index_end();
return *this; _graph->_stale= false;
}
return _position;
} }
oqgraph3::row_cursor& oqgraph3::row_cursor::last() void oqgraph3::cursor::clear_position()
{ {
printf("%s:%d\n", __func__, __LINE__); _position.clear();
TABLE& table= *_cache->_table; if (this == _graph->_cursor)
table.file->ha_index_init(0, 1);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_last");
if (!table.file->ha_index_last(table.record[0]))
{
update_virtual_fields(table.in_use, &table);
edge_key tmp(table.key_info->key_length, _cache);
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator
found= _cache->_cache_edges.find(tmp);
if (found != _cache->_cache_edges.end())
{
// we already had a row
_current.reset(&found->first);
}
else
{ {
_current.reset(&_cache->_cache_edges.insert( _graph->_cursor= 0;
std::make_pair( _graph->_stale= false;
tmp,
row_info(
_cache->_source->val_int(),
_cache->_target->val_int(),
_cache->_weight ? _cache->_weight->val_real() : 1.0,
0,
0
)
)).first->first);
} }
}
table.file->ha_index_end();
return *this;
} }
oqgraph3::row_cursor& oqgraph3::row_cursor::operator--() void oqgraph3::cursor::save_position()
{ {
printf("%s:%d\n", __func__, __LINE__); record_position();
if (!_current)
return last();
graph::edge_cache_type::iterator
current= _cache->_cache_edges.find(*_current);
if (current->second._prev) if (this == _graph->_cursor)
{ {
graph::edge_cache_type::iterator prev= TABLE& table= *_graph->_table;
_cache->_cache_edges.find(edge_key(*current->second._prev));
if (_cache->_cache_edges.end() != prev)
{
_current.reset(&prev->first);
return *this;
}
}
TABLE& table= *_cache->_table;
table.file->ha_index_init(0, 1);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); if (_graph->_cursor->_index >= 0)
if (table.file->ha_index_read_map(
table.record[0],
reinterpret_cast<const uchar*>(current->first._ref.data()),
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_BEFORE_KEY))
{
table.file->ha_index_end(); table.file->ha_index_end();
_current.reset(); else
return *this; table.file->ha_rnd_end();
_graph->_cursor= 0;
_graph->_stale= false;
} }
update_virtual_fields(table.in_use, &table);
table.file->ha_index_end();
edge_key tmp(table.key_info->key_length, _cache);
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator
found= _cache->_cache_edges.find(tmp);
if (_cache->_cache_edges.end() != found)
{
// we already had a row, link them together
found->second._next= &current->first._ref;
current->second._prev= &found->first._ref;
_current.reset(&found->first);
return *this;
}
_current.reset(&_cache->_cache_edges.insert(
std::make_pair(
tmp,
row_info(
_cache->_source->val_int(),
_cache->_target->val_int(),
_cache->_weight ? _cache->_weight->val_real() : 1.0,
0,
&_current->_ref
)
)).first->first);
return *this;
} }
oqgraph3::row_cursor& oqgraph3::row_cursor::operator+=(difference_type delta) int oqgraph3::cursor::restore_position()
{ {
printf("%s:%d\n", __func__, __LINE__); TABLE& table= *_graph->_table;
if (!delta || !_current)
return *this;
if (delta < 0) if (!_position.size())
return *this -= (-delta); return ENOENT;
graph::edge_cache_type::iterator if (this == _graph->_cursor)
current= _cache->_cache_edges.find(*_current); return 0;
bool index_started= false; if (_graph->_cursor)
TABLE& table= *_cache->_table; _graph->_cursor->save_position();
while (delta-- > 0) if (_origid || _destid)
{
if (_cache->_cache_edges.end() != current)
{ {
if (current->second._next) if (int rc= table.file->ha_index_init(_index, 1))
{ return rc;
graph::edge_cache_type::iterator
next= _cache->_cache_edges.find(edge_key(*current->second._next));
if (_cache->_cache_edges.end() != next) restore_record(&table, s->default_values);
if (_origid)
{ {
current= next; bitmap_set_bit(table.write_set, _graph->_source->field_index);
continue; _graph->_source->store(*_origid, 1);
bitmap_clear_bit(table.write_set, _graph->_source->field_index);
} }
if (!index_started) if (_destid)
{ {
table.file->ha_index_init(0, 1); bitmap_set_bit(table.write_set, _graph->_target->field_index);
index_started= true; _graph->_target->store(*_destid, 1);
bitmap_clear_bit(table.write_set, _graph->_target->field_index);
} }
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); if (int rc= table.file->ha_index_init(_index, 1))
if (table.file->ha_index_read_map( return rc;
table.record[0],
reinterpret_cast<const uchar*>(current->second._next->data()), if (int rc= table.file->ha_index_read_map(
(key_part_map)((1 << table.key_info->key_parts) - 1), table.record[0], (const uchar*) _key.data(),
HA_READ_KEY_OR_NEXT)) (key_part_map)(1 << _parts) - 1,
table.s->key_info[_index].key_parts == _parts ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{ {
table.file->ha_index_end(); table.file->ha_index_end();
_current.reset(); return rc;
return *this;
}
} }
else
update_virtual_fields(table.in_use, &table);
table.file->position(table.record[0]);
while (memcmp(table.file->ref, _position.data(), table.file->ref_length))
{ {
if (!index_started) if (int rc= table.file->ha_index_next(table.record[0]))
{ {
table.file->ha_index_init(0, 1); table.file->ha_index_end();
index_started= true; return rc;
} }
update_virtual_fields(table.in_use, &table);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); if ((_origid && vertex_id(_graph->_source->val_int()) != *_origid) ||
if (table.file->ha_index_read_map( (_destid && vertex_id(_graph->_target->val_int()) != *_destid))
table.record[0],
reinterpret_cast<const uchar*>(current->first._ref.data()),
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_AFTER_KEY))
{ {
table.file->ha_index_end(); table.file->ha_index_end();
_current.reset(); return ENOENT;
return *this;
} }
table.file->position(table.record[0]);
} }
update_virtual_fields(table.in_use, &table);
edge_key tmp(table.key_info->key_length);
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator
found= _cache->_cache_edges.find(tmp);
if (found != _cache->_cache_edges.end())
{
// we already had a row, link them together
found->second._next= &current->first._ref;
current->second._prev= &found->first._ref;
}
current= found;
} }
else else
{ {
if (!index_started) if (int rc= table.file->ha_rnd_init(1))
return *this; return rc;
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_next"); if (int rc= table.file->ha_rnd_pos(
if (table.file->ha_index_next(table.record[0])) table.record[0], (uchar*) _position.data()))
{ {
table.file->ha_index_end(); table.file->ha_rnd_end();
_current.reset(); return rc;
return *this; }
update_virtual_fields(table.in_use, &table);
} }
edge_key tmp(table.key_info->key_length); _graph->_cursor= this;
_graph->_stale= false;
key_copy( return 0;
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())), }
table.record[0],
table.key_info,
tmp._ref.size(), true);
current= _cache->_cache_edges.find(tmp); oqgraph3::vertex_id oqgraph3::cursor::get_origid()
} {
} if (_origid)
return *_origid;
if (index_started) if (this != _graph->_cursor)
{ {
table.file->ha_index_end(); if (restore_position())
return -1;
} }
return static_cast<vertex_id>(_graph->_source->val_int());
return *this;
} }
oqgraph3::row_cursor& oqgraph3::row_cursor::operator-=(difference_type delta) oqgraph3::vertex_id oqgraph3::cursor::get_destid()
{ {
printf("%s:%d\n", __func__, __LINE__); if (_destid)
if (!delta || !_current) return *_destid;
return *this;
if (delta < 0)
return *this += (-delta);
graph::edge_cache_type::iterator
current= _cache->_cache_edges.find(*_current);
bool index_started= false;
TABLE& table= *_cache->_table;
while (delta-- > 0) if (this != _graph->_cursor)
{ {
if (_cache->_cache_edges.end() != current) if (restore_position())
{ return -1;
if (current->second._next)
{
graph::edge_cache_type::iterator next=
_cache->_cache_edges.find(edge_key(*current->second._next));
if (_cache->_cache_edges.end() != next)
{
current= next;
continue;
} }
return static_cast<vertex_id>(_graph->_target->val_int());
}
if (!index_started)
{
table.file->ha_index_init(0, 1);
index_started= true;
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); oqgraph3::weight_t oqgraph3::cursor::get_weight()
if (table.file->ha_index_read_map( {
table.record[0], if (!_graph->_weight)
reinterpret_cast<const uchar*>(current->second._next->data()), return 1.0;
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_KEY_OR_PREV)) if (this != _graph->_cursor)
{
table.file->ha_index_end();
return first();
}
}
else
{
if (!index_started)
{ {
table.file->ha_index_init(0, 1); if (restore_position())
index_started= true; return -1;
} }
return static_cast<vertex_id>(_graph->_weight->val_int());
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); int oqgraph3::cursor::seek_next()
if (table.file->ha_index_read_map( {
table.record[0], if (this != _graph->_cursor)
reinterpret_cast<const uchar*>(current->first._ref.data()),
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_BEFORE_KEY))
{ {
table.file->ha_index_end(); if (int rc= restore_position())
return first(); return rc;
}
} }
edge_key tmp(table.key_info->key_length); TABLE& table= *_graph->_table;
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator if (_index < 0)
found= _cache->_cache_edges.find(tmp);
if (_cache->_cache_edges.end() != found)
{ {
// we already had a row, link them together if (int rc= table.file->ha_rnd_next(table.record[0]))
found->second._next= &current->first._ref; {
current->second._prev= &found->first._ref; table.file->ha_rnd_end();
return clear_position(rc);
} }
current= found; return 0;
} }
else
{
if (!index_started)
return first();
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_prev"); if (int rc= table.file->ha_index_next(table.record[0]))
if (table.file->ha_index_prev(table.record[0]))
{ {
table.file->ha_index_end(); table.file->ha_index_end();
return first(); return clear_position(rc);
} }
edge_key tmp(table.key_info->key_length); update_virtual_fields(table.in_use, &table);
_graph->_stale= true;
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
current= _cache->_cache_edges.find(tmp);
}
}
if (index_started) if ((_origid && vertex_id(_graph->_source->val_int()) != *_origid) ||
(_destid && vertex_id(_graph->_target->val_int()) != *_destid))
{ {
table.file->ha_index_end(); table.file->ha_index_end();
return clear_position(ENOENT);
} }
return *this; return 0;
} }
oqgraph3::vertex_descriptor oqgraph3::graph::vertex(vertex_id id) int oqgraph3::cursor::seek_prev()
{ {
printf("%s:%d\n", __func__, __LINE__); if (this != _graph->_cursor)
vertex_cache_type::const_iterator {
found= _cache_vertices.find(vertex_info(id)); if (int rc= restore_position())
return rc;
if (_cache_vertices.end() != found) }
return vertex_descriptor(const_cast<vertex_info*>(found.operator->()));
return vertex_descriptor(const_cast<vertex_info*>(
_cache_vertices.insert(vertex_info(id, this)).first.operator->()));
}
oqgraph3::edge_descriptor oqgraph3::graph::edge(const edge_key& key)
{
printf("%s:%d\n", __func__, __LINE__);
edge_cache_type::const_iterator
found= _cache_edges.find(key);
if (_cache_edges.end() != found)
return edge_descriptor(&found->first);
TABLE& table= *_table; TABLE& table= *_graph->_table;
table.file->ha_index_init(0, 0); if (_index < 0)
{
return -1; // not supported
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); if (int rc= table.file->ha_index_prev(table.record[0]))
if (table.file->ha_index_read_map(
table.record[0],
reinterpret_cast<const uchar*>(key._ref.data()),
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_KEY_EXACT))
{ {
table.file->ha_index_end(); table.file->ha_index_end();
return edge_descriptor(); return clear_position(rc);
} }
update_virtual_fields(table.in_use, &table); update_virtual_fields(table.in_use, &table);
_graph->_stale= true;
if ((_origid && vertex_id(_graph->_source->val_int()) != *_origid) ||
(_destid && vertex_id(_graph->_target->val_int()) != *_destid))
{
table.file->ha_index_end(); table.file->ha_index_end();
return clear_position(ENOENT);
}
return edge_descriptor(&_cache_edges.insert( return 0;
std::make_pair(
edge_key(key, this),
row_info(
_source->val_int(),
_target->val_int(),
_weight ? _weight->val_real() : 1.0,
0,
0
)
)).first->first);
} }
oqgraph3::edge_descriptor oqgraph3::graph::edge(
const vertex_descriptor& source, int oqgraph3::cursor::seek_to(
const vertex_descriptor& target) boost::optional<vertex_id> origid,
boost::optional<vertex_id> destid)
{ {
printf("%s:%d\n", __func__, __LINE__); if (_graph->_cursor && this != _graph->_cursor)
vertex_cache_type::const_iterator xsource= _cache_vertices.find(*source); _graph->_cursor->save_position();
if (_cache_vertices.end() != xsource && xsource->_out_edges) TABLE& table= *_graph->_table;
{ _index= -1;
const vertex_info::edge_list_type& edges= *xsource->_out_edges; _origid= origid;
for (vertex_info::edge_list_type::const_iterator _destid= destid;
it= edges.begin(), end= edges.end(); end != it; ++it)
{
edge_cache_type::const_iterator
found= _cache_edges.find(edge_key(*it));
if (_cache_edges.end() != found && if (origid || destid)
target->id == found->second.second)
{ {
return edge_descriptor(&found->first); Field *source= _graph->_source;
} Field *target= _graph->_target;
}
return edge_descriptor();
}
vertex_cache_type::const_iterator xtarget= _cache_vertices.find(*target); uint source_fieldpos= _graph->_source->offset(table.record[0]);
uint target_fieldpos= _graph->_target->offset(table.record[0]);
if (_cache_vertices.end() != xtarget && xtarget->_in_edges) if (!destid)
{ {
const vertex_info::edge_list_type& edges= *xtarget->_in_edges;
for (vertex_info::edge_list_type::const_iterator
it= edges.begin(), end= edges.end(); end != it; ++it)
{
edge_cache_type::const_iterator
found= _cache_edges.find(edge_key(*it));
if (_cache_edges.end() != found &&
source->id == found->second.first)
{
return edge_descriptor(&found->first);
}
}
return edge_descriptor();
}
// If we have an index which has both key parts, we can use that
// to quickly retrieve the edge descriptor.
TABLE& table= *_table;
uint source_fieldpos= _source->offset(table.record[0]);
uint target_fieldpos= _target->offset(table.record[0]);
int i= 0; int i= 0;
for( ::KEY *key_info= table.s->key_info, for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys; *key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i) key_info < key_end; ++key_info, ++i)
{ {
if (key_info->key_parts < 2) if (key_info->key_part[0].offset != source_fieldpos)
continue; continue;
if ((key_info->key_part[0].offset == source_fieldpos &&
key_info->key_part[1].offset == target_fieldpos) ||
(key_info->key_part[0].offset == target_fieldpos &&
key_info->key_part[1].offset == source_fieldpos))
{
// we can use this key
restore_record(&table, s->default_values);
bitmap_set_bit(table.write_set, _source->field_index);
bitmap_set_bit(table.write_set, _target->field_index);
_source->store(source->id, 1);
_target->store(target->id, 1);
bitmap_clear_bit(table.write_set, _source->field_index);
bitmap_clear_bit(table.write_set, _target->field_index);
uint key_len= key_info->key_length;
uchar* key_prefix= (uchar*) my_alloca(key_len);
table.file->ha_index_init(i, 0); if (table.file->ha_index_init(i, 1))
continue;
key_copy(key_prefix, table.record[0], key_info, key_len, 1);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
if (!table.file->ha_index_read_map(
table.record[0], key_prefix, (key_part_map)3,
key_info->key_parts == 2 ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT) &&
_source->val_int() == source->id &&
_target->val_int() == target->id)
{
// We have found the edge,
update_virtual_fields(table.in_use, &table);
table.file->ha_index_end(); restore_record(&table, s->default_values);
my_afree(key_prefix);
edge_key tmp(table.key_info->key_length, this); bitmap_set_bit(table.write_set, source->field_index);
source->store(*_origid, 1);
bitmap_clear_bit(table.write_set, source->field_index);
key_copy( uchar* buff= (uchar*) my_alloca(source->pack_length());
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())), source->get_key_image(buff, source->pack_length(), Field::itRAW);
table.record[0], _key.clear();
table.key_info, _key.append((char*) buff, source->pack_length());
tmp._ref.size(), true); _key.resize(key_info->key_length, '\0');
my_afree(buff);
graph::edge_cache_type::iterator _parts= 1;
found= _cache_edges.find(tmp); _index= i;
if (_cache_edges.end() != found) break;
{
// we already had the edge
return edge_descriptor(&found->first);
}
return edge_descriptor(&_cache_edges.insert(
std::make_pair(
tmp,
row_info(
_source->val_int(),
_target->val_int(),
_weight ? _weight->val_real() : 1.0,
0,
0
)
)).first->first);
}
}
}
const vertex_info::edge_list_type& edges= vertex(source->id)->out_edges();
for (vertex_info::edge_list_type::const_iterator
it= edges.begin(), end= edges
.end(); end != it; ++it)
{
edge_cache_type::const_iterator
found= _cache_edges.find(edge_key(*it));
if (_cache_edges.end() != found &&
target->id == found->second.second)
{
return edge_descriptor(&found->first);
} }
} }
else if (!origid)
return edge_descriptor();
}
oqgraph3::edges_size_type oqgraph3::graph::num_edges() const
{
return _table->file->stats.records;
}
const oqgraph3::vertex_info::edge_list_type&
oqgraph3::vertex_info::out_edges()
{
printf("%s:%d id=%lld\n", __func__, __LINE__, id);
if (!_out_edges)
{ {
_out_edges = edge_list_type();
TABLE& table= *_cache->_table;
uint source_fieldpos= _cache->_source->offset(table.record[0]);
int i= 0; int i= 0;
for( ::KEY *key_info= table.s->key_info, for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys; *key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i) key_info < key_end; ++key_info, ++i)
{ {
if (key_info->key_part[0].offset == source_fieldpos) if (key_info->key_part[0].offset != target_fieldpos)
{ continue;
// we can use this key
restore_record(&table, s->default_values);
bitmap_set_bit(table.write_set, _cache->_source->field_index);
_cache->_source->store(id, 1);
bitmap_clear_bit(table.write_set, _cache->_source->field_index);
uint key_len= key_info->key_length;
uchar* key= (uchar*) my_alloca(key_len);
table.file->ha_index_init(i, 1);
key_copy(key, table.record[0], key_info, key_len, true);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
if (!table.file->ha_index_read_map(
table.record[0], key, (key_part_map)1,
key_info->key_parts == 1 ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{
// We have found an edge,
do
{
update_virtual_fields(table.in_use, &table);
edge_key tmp(table.key_info->key_length, _cache); if (table.file->ha_index_init(i, 1))
continue;
key_copy( restore_record(&table, s->default_values);
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator bitmap_set_bit(table.write_set, target->field_index);
found= _cache->_cache_edges.find(tmp); target->store(*_destid, 1);
if (_cache->_cache_edges.end() == found) bitmap_clear_bit(table.write_set, target->field_index);
{
found= _cache->_cache_edges.insert(
std::make_pair(
tmp,
row_info(
_cache->_source->val_int(),
_cache->_target->val_int(),
_cache->_weight ? _cache->_weight->val_real() : 1.0,
0,
0
)
)).first;
}
_out_edges->push_back(found->first._ref);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_next"); uchar* buff= (uchar*) my_alloca(target->pack_length());
if (table.file->ha_index_next(table.record[0])) target->get_key_image(buff, target->pack_length(), Field::itRAW);
{ _key.clear();
break; _key.append((char*) buff, target->pack_length());
} _key.resize(key_info->key_length, '\0');
} my_afree(buff);
while (_cache->_source->val_int() == id);
table.file->ha_index_end(); _parts= 1;
my_afree(key); _index= i;
break; break;
} }
table.file->ha_index_end();
} }
} else
}
return *_out_edges;
}
const oqgraph3::vertex_info::edge_list_type&
oqgraph3::vertex_info::in_edges()
{
printf("%s:%d\n", __func__, __LINE__);
if (!_in_edges)
{ {
_in_edges = edge_list_type();
TABLE& table= *_cache->_table;
uint target_fieldpos= _cache->_target->offset(table.record[0]);
int i= 0; int i= 0;
for( ::KEY *key_info= table.s->key_info, for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys; *key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i) key_info < key_end; ++key_info, ++i)
{ {
if (key_info->key_part[0].offset == target_fieldpos) if (key_info->key_parts < 2)
{ continue;
// we can use this key if (!((key_info->key_part[0].offset == target_fieldpos &&
restore_record(&table, s->default_values); key_info->key_part[1].offset == source_fieldpos) ||
(key_info->key_part[1].offset == target_fieldpos &&
bitmap_set_bit(table.write_set, _cache->_target->field_index); key_info->key_part[0].offset == source_fieldpos)))
_cache->_target->store(id, 1); continue;
bitmap_clear_bit(table.write_set, _cache->_target->field_index);
uint key_len= key_info->key_length; if (table.file->ha_index_init(i, 1))
uchar* key= (uchar*) my_alloca(key_len); continue;
table.file->ha_index_init(i, 1); restore_record(&table, s->default_values);
key_copy(key, table.record[0], key_info, key_len, true); bitmap_set_bit(table.write_set, source->field_index);
source->store(*_origid, 1);
bitmap_clear_bit(table.write_set, source->field_index);
bitmap_set_bit(table.write_set, target->field_index);
target->store(*_destid, 1);
bitmap_clear_bit(table.write_set, target->field_index);
Field* first=
key_info->key_part[0].offset == source_fieldpos ?
source : target;
Field* second=
key_info->key_part[0].offset == target_fieldpos ?
target : source;
uchar* buff= (uchar*) my_alloca(
source->pack_length() + target->pack_length());
first->get_key_image(buff, first->pack_length(), Field::itRAW);
second->get_key_image(buff + first->pack_length(), second->pack_length(), Field::itRAW);
_key.clear();
_key.append((char*) buff, source->pack_length() + target->pack_length());
_key.resize(key_info->key_length, '\0');
my_afree(buff);
_parts= 2;
_index= i;
break;
}
}
if (_index < 0)
{
// no suitable index found
return clear_position(ENXIO);
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map"); if (int rc= table.file->ha_index_read_map(
if (!table.file->ha_index_read_map( table.record[0], (uchar*) _key.data(),
table.record[0], key, (key_part_map)1, (key_part_map) ((1U << _parts) - 1),
key_info->key_parts == 1 ? table.s->key_info[_index].key_parts == _parts ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT)) HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{ {
// We have found an edge, table.file->ha_index_end();
do return clear_position(rc);
{
update_virtual_fields(table.in_use, &table);
edge_key tmp(table.key_info->key_length, _cache);
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
graph::edge_cache_type::iterator
found= _cache->_cache_edges.find(tmp);
if (_cache->_cache_edges.end() == found)
{
found= _cache->_cache_edges.insert(
std::make_pair(
tmp,
row_info(
_cache->_source->val_int(),
_cache->_target->val_int(),
_cache->_weight ? _cache->_weight->val_real() : 1.0,
0,
0
)
)).first;
}
_in_edges->push_back(found->first._ref);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_next");
if (table.file->ha_index_next(table.record[0]))
break;
} }
while (_cache->_target->val_int() == id);
update_virtual_fields(table.in_use, &table);
if ((_origid && vertex_id(_graph->_source->val_int()) != *_origid) ||
(_destid && vertex_id(_graph->_target->val_int()) != *_destid))
{
table.file->ha_index_end(); table.file->ha_index_end();
my_afree(key); return clear_position(ENOENT);
break;
} }
table.file->ha_index_end();
} }
else
{
if (int rc= table.file->ha_rnd_init(true))
return clear_position(rc);
if (int rc= table.file->ha_rnd_next(table.record[0]))
{
table.file->ha_rnd_end();
return clear_position(rc);
} }
} }
return *_in_edges;
}
std::size_t oqgraph3::vertex_info::degree() _graph->_cursor= this;
{ _graph->_stale= true;
printf("%s:%d\n", __func__, __LINE__); return 0;
return out_edges().size() + in_edges().size();
} }
oqgraph3::degree_size_type oqgraph3::vertex_descriptor::in_degree() const bool oqgraph3::cursor::operator==(const cursor& x) const
{ {
printf("%s:%d\n", __func__, __LINE__); return record_position() == x._position;
return (*this)->in_edges().size();
} }
oqgraph3::degree_size_type oqgraph3::vertex_descriptor::out_degree() const bool oqgraph3::cursor::operator!=(const cursor& x) const
{ {
printf("%s:%d\n", __func__, __LINE__); return record_position() != x._position;
return (*this)->out_edges().size();
} }
oqgraph3::vertex_descriptor oqgraph3::edge_descriptor::source() const oqgraph3::graph::graph(
::TABLE* table,
::Field* source,
::Field* target,
::Field* weight)
: _ref_count(0)
, _cursor(0)
, _stale(false)
, _table(table)
, _source(source)
, _target(target)
, _weight(weight)
{ {
printf("%s:%d\n", __func__, __LINE__); bitmap_set_bit(table->read_set, source->field_index);
return (*this)->_cache->vertex( bitmap_set_bit(table->read_set, target->field_index);
oqgraph3::row_cursor(*this, (*this)->_cache)->first); if (weight)
bitmap_set_bit(table->read_set, weight->field_index);
table->file->column_bitmaps_signal();
} }
oqgraph3::vertex_descriptor oqgraph3::edge_descriptor::target() const oqgraph3::graph::~graph()
{ }
oqgraph3::edges_size_type oqgraph3::graph::num_edges() const
{ {
printf("%s:%d\n", __func__, __LINE__); return _table->file->stats.records;
return (*this)->_cache->vertex(
oqgraph3::row_cursor(*this, (*this)->_cache)->second);
} }
...@@ -50,268 +50,96 @@ namespace oqgraph3 ...@@ -50,268 +50,96 @@ namespace oqgraph3
typedef size_t degree_size_type; typedef size_t degree_size_type;
struct graph; struct graph;
struct vertex_info; struct cursor;
typedef boost::intrusive_ptr<graph> graph_ptr; typedef boost::intrusive_ptr<graph> graph_ptr;
struct edge_key struct cursor_ptr : public boost::intrusive_ptr<cursor>
{ {
typedef std::string ref_type; cursor_ptr() : boost::intrusive_ptr<cursor>() { }
cursor_ptr(cursor* pos) : boost::intrusive_ptr<cursor>(pos) { }
ref_type _ref; operator const std::string&() const;
mutable int _ref_count; bool operator==(const cursor_ptr&) const;
bool operator!=(const cursor_ptr&) const;
graph_ptr _cache;
mutable bool _on_gc;
operator const ref_type&() const { return _ref; }
explicit edge_key(
std::size_t length,
const graph_ptr& cache= graph_ptr())
: _ref(length, '\0')
, _ref_count(0)
, _cache(cache)
{ }
template <typename C, typename T, typename A>
explicit edge_key(const std::basic_string<C,T,A>& ref)
: _ref(ref.begin(), ref.end())
, _ref_count(0)
, _cache(0)
{ }
edge_key(const edge_key& src)
: _ref(src._ref)
, _ref_count(0)
, _cache(src._cache)
{ }
edge_key(const edge_key& src, const graph_ptr& cache)
: _ref(src._ref)
, _ref_count(0)
, _cache(cache)
{ }
~edge_key();
void release() const;
friend void intrusive_ptr_add_ref(const edge_key* ptr)
{ ++ptr->_ref_count; }
friend void intrusive_ptr_release(const edge_key* ptr)
{ ptr->release(); }
}; };
struct vertex_info struct edge_info
{ {
typedef vertex_id vertex_id_type; cursor_ptr _cursor;
typedef std::list<edge_key::ref_type> edge_list_type;
const vertex_id_type id;
mutable int _ref_count;
boost::optional<edge_list_type> _in_edges;
boost::optional<edge_list_type> _out_edges;
graph_ptr _cache;
mutable bool _on_gc;
explicit vertex_info(
vertex_id_type i,
const graph_ptr& cache= graph_ptr())
: id(i)
, _ref_count(0)
, _cache(cache)
, _on_gc(false)
{ }
~vertex_info();
const edge_list_type& out_edges(); edge_info() : _cursor(0) { }
const edge_list_type& in_edges(); explicit edge_info(const cursor_ptr& pos) : _cursor(pos) { }
std::size_t degree(); edge_info& operator=(const cursor_ptr& pos) { _cursor= pos; return *this; }
void release(); vertex_id origid() const;
vertex_id destid() const;
weight_t weight() const;
friend void intrusive_ptr_add_ref(vertex_info* ptr) bool operator==(const edge_info&) const;
{ ++ptr->_ref_count; } bool operator!=(const edge_info&) const;
friend void intrusive_ptr_release(vertex_info* ptr)
{ ptr->release(); }
}; };
struct vertex_descriptor struct cursor
: public boost::intrusive_ptr<vertex_info>
{ {
vertex_descriptor() mutable int _ref_count;
: boost::intrusive_ptr<vertex_info>() graph_ptr _graph;
{ }
vertex_descriptor(vertex_info* v) int _index;
: boost::intrusive_ptr<vertex_info>(v) unsigned _parts;
{ } std::string _key;
std::string _position;
vertex_descriptor(const vertex_descriptor& v) int _debugid;
: boost::intrusive_ptr<vertex_info>(v)
{ }
degree_size_type in_degree() const; boost::optional<vertex_id> _origid;
degree_size_type out_degree() const; boost::optional<vertex_id> _destid;
friend degree_size_type in_degree(const vertex_descriptor& v, const graph&) cursor(const graph_ptr& graph);
{ return v.in_degree(); } cursor(const cursor& src);
friend degree_size_type out_degree(const vertex_descriptor& v, const graph&)
{ return v.out_degree(); }
};
struct edge_descriptor ~cursor();
: public boost::intrusive_ptr<const edge_key>
{
edge_descriptor()
: boost::intrusive_ptr<const edge_key>()
{ }
edge_descriptor(const edge_key* e) operator bool() const
: boost::intrusive_ptr<const edge_key>(e) { return !_position.empty(); }
{ }
edge_descriptor(const edge_descriptor& e) operator edge_info() const
: boost::intrusive_ptr<const edge_key>(e) { return edge_info(const_cast<cursor*>(this)); }
{ }
vertex_descriptor source() const; vertex_id get_origid();
vertex_descriptor target() const; vertex_id get_destid();
weight_t get_weight();
friend vertex_descriptor source(const edge_descriptor& e, const graph&) int seek_to(
{ return e.source(); } boost::optional<vertex_id> origid,
boost::optional<vertex_id> destid);
friend vertex_descriptor target(const edge_descriptor& e, const graph&) int seek_next();
{ return e.target(); } int seek_prev();
};
struct row_info void save_position();
: public std::pair<vertex_id, vertex_id> int restore_position();
{ const std::string& record_position() const;
weight_t _weight; void clear_position();
int clear_position(int rc) { clear_position(); return rc; }
const edge_key::ref_type* _prev;
const edge_key::ref_type* _next;
row_info(
first_type source,
second_type target,
weight_t weight,
const edge_key::ref_type* prev,
const edge_key::ref_type* next)
: std::pair<first_type, second_type>(source, target)
, _weight(weight)
, _prev(prev)
, _next(next)
{ printf("row_info(%lld,%lld,%f)\n", source, target, weight);}
};
namespace internal
{
template <typename Value> struct hash
: public std::unary_function<Value, std::size_t>
{
boost::hash<Value> ref_hasher;
std::size_t operator()(const Value& v) const
{
return ref_hasher(v);
}
};
template <typename Value> struct equal_to bool operator==(const cursor& x) const;
: public std::binary_function<Value, Value, bool> bool operator!=(const cursor& x) const;
{
std::equal_to<Value> ref_equals;
bool operator()(const Value& x, const Value& y) const
{
return ref_equals(x, y);
}
};
template <> struct hash<edge_key> friend void intrusive_ptr_add_ref(cursor* ptr)
: public std::unary_function<edge_key, std::size_t> { ++ptr->_ref_count; }
{ friend void intrusive_ptr_release(cursor* ptr)
boost::hash<edge_key::ref_type> ref_hasher; { if (!--(ptr->_ref_count)) delete ptr; }
std::size_t operator()(edge_key const& v) const
{
return ref_hasher(v._ref);
}
};
template <> struct hash<const edge_key*>
: public std::unary_function<const edge_key*, std::size_t>
{
boost::hash<edge_key::ref_type> ref_hasher;
std::size_t operator()(const edge_key* const& v) const
{
return ref_hasher(v->_ref);
}
};
template <> struct hash<vertex_info>
: public std::unary_function<vertex_info, std::size_t>
{
boost::hash<vertex_info::vertex_id_type> id_hasher;
std::size_t operator()(vertex_info const& v) const
{
return id_hasher(v.id);
}
};
template <> struct equal_to<edge_key>
: public std::binary_function<edge_key, edge_key, bool>
{
std::equal_to<edge_key::ref_type> ref_equals;
bool operator()(const edge_key& x, const edge_key& y) const
{
return ref_equals(x._ref, y._ref);
}
};
template <> struct equal_to<const edge_key*>
: public std::binary_function<const edge_key*, edge_key, bool>
{
std::equal_to<edge_key::ref_type> ref_equals;
bool operator()(const edge_key*& x, const edge_key*& y) const
{
return ref_equals(x->_ref, y->_ref);
}
};
template <> struct equal_to<vertex_info>
: public std::binary_function<vertex_info, vertex_info, bool>
{
std::equal_to<vertex_info::vertex_id_type> id_equals;
bool operator()(const vertex_info& x, const vertex_info& y) const
{
return id_equals(x.id, y.id);
}
}; };
}
struct graph struct graph
{ {
typedef boost::unordered_map<
edge_key,
row_info,
internal::hash<edge_key>,
internal::equal_to<edge_key> > edge_cache_type;
typedef boost::unordered_set<
vertex_info,
internal::hash<vertex_info>,
internal::equal_to<vertex_info> > vertex_cache_type;
bool _gc_running;
mutable int _ref_count; mutable int _ref_count;
cursor* _cursor;
bool _stale;
edge_cache_type _cache_edges; cursor_ptr _rnd_cursor;
boost::queue<edge_key*> _gc_edges; size_t _rnd_pos;
vertex_cache_type _cache_vertices;
boost::queue<vertex_info*> _gc_vertices;
::TABLE* _table; ::TABLE* _table;
::Field* _source; ::Field* _source;
...@@ -325,12 +153,6 @@ namespace oqgraph3 ...@@ -325,12 +153,6 @@ namespace oqgraph3
::Field* weight= 0); ::Field* weight= 0);
~graph(); ~graph();
vertex_descriptor vertex(vertex_id);
edge_descriptor edge(const edge_key&);
edge_descriptor edge(
const vertex_descriptor&,
const vertex_descriptor&);
edges_size_type num_edges() const; edges_size_type num_edges() const;
friend edges_size_type num_edges(const graph& g) friend edges_size_type num_edges(const graph& g)
...@@ -343,73 +165,5 @@ namespace oqgraph3 ...@@ -343,73 +165,5 @@ namespace oqgraph3
{ ptr->_ref_count--; } { ptr->_ref_count--; }
}; };
struct row_cursor
{
typedef std::random_access_iterator_tag iterator_category;
typedef graph::edge_cache_type::value_type::second_type value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef graph::edge_cache_type::size_type size_type;
typedef graph::edge_cache_type::difference_type difference_type;
graph_ptr _cache;
edge_descriptor _current;
explicit row_cursor(graph* cache)
: _cache(cache)
{ }
explicit row_cursor(const graph_ptr& cache)
: _cache(cache)
{ }
explicit row_cursor(const edge_descriptor& e, const graph_ptr& cache)
: _cache(cache)
, _current(e)
{ }
reference operator*() const
{ return _cache->_cache_edges.find(*_current)->second; }
pointer operator->() const
{ return &_cache->_cache_edges.find(*_current)->second; }
row_cursor& operator++();
row_cursor operator++(int)
{ row_cursor tmp= *this; ++*this; return tmp; }
row_cursor& operator--();
row_cursor operator--(int)
{ row_cursor tmp= *this; --*this; return tmp; }
row_cursor& operator+=(difference_type delta);
row_cursor operator+(difference_type delta) const
{ row_cursor tmp= *this; return tmp += delta; }
row_cursor& operator-=(difference_type delta);
row_cursor operator-(difference_type delta) const
{ row_cursor tmp= *this; return tmp -= delta; }
reference operator[](difference_type offset) const
{ return *(*this + offset); }
row_cursor& first();
row_cursor& last();
row_cursor& end()
{ _current.reset(); return *this; }
bool operator==(const row_cursor& x) const
{ return _current == x._current; }
bool operator!=(const row_cursor& x) const
{ return _current != x._current; }
};
} }
Markdown is supported
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