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 \
graphcore-graph.h graphcore-types.h graphcore.h
# oqgraph_probes.h
noinst_LTLIBRARIES = libgraphcore.la
libgraphcore_la_SOURCES = graphcore.cc graphcore-graph.cc oqgraph_shim.cc oqgraph_thunk.cc
libgraphcore_la_CXXFLAGS = $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS)
#noinst_LTLIBRARIES = libgraphcore.la
#libgraphcore_la_SOURCES = graphcore.cc graphcore-graph.cc oqgraph_shim.cc oqgraph_thunk.cc
#libgraphcore_la_CXXFLAGS = $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS)
if BUILD_OQGRAPH_FOR_MYSQL
......@@ -73,8 +73,27 @@ endif !BUILD_OQGRAPH_STANDALONE
EXTRA_LTLIBRARIES = ha_oqgraph.la
mysqlplugin_LTLIBRARIES = @plugin_oqgraph_shared_target@
ha_oqgraph_la_SOURCES = ha_oqgraph.cc oqgraph_judy.cc
ha_oqgraph_la_LIBADD = libgraphcore.la
ha_oqgraph_la_SOURCES = ha_oqgraph.cc oqgraph_judy.cc \
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
# ha_oqgraph_la_LIBADD += oqgraph_probes.o
......
......@@ -35,18 +35,6 @@ namespace boost
{
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>
struct two_bit_judy_map
{
......@@ -54,15 +42,15 @@ namespace boost
typedef two_bit_color_type value_type;
typedef void reference;
typedef read_write_property_map_tag category;
open_query::judy_bitset msb;
open_query::judy_bitset lsb;
IndexMap index;
two_bit_judy_map(const IndexMap& i)
: index(i)
{ }
friend two_bit_color_type get(
const two_bit_judy_map<IndexMap>& pm,
typename property_traits<IndexMap>::key_type key)
......@@ -70,7 +58,7 @@ namespace boost
typename property_traits<IndexMap>::value_type i = get(pm.index, key);
return two_bit_color_type((2*int(pm.msb.test(i))) | int(pm.lsb.test(i)));
}
friend void put(
two_bit_judy_map<IndexMap>& pm,
typename property_traits<IndexMap>::key_type key,
......@@ -81,7 +69,7 @@ namespace boost
pm.lsb.set(i, value & 1);
}
};
template<typename IndexMap>
inline two_bit_judy_map<IndexMap>
make_two_bit_judy_map(const IndexMap& index)
......@@ -89,7 +77,7 @@ namespace boost
return two_bit_judy_map<IndexMap>(index);
}
template <typename Type>
struct default_lazy_initializer
{
......@@ -119,11 +107,11 @@ namespace boost
const Type& operator()(const Key&) const { return _; }
const Type _;
};
template <typename Type>
value_initializer<Type> make_value_initializer(const Type& value)
{ return value_initializer<Type>(value); }
template <typename Key>
struct identity_initializer
......@@ -139,12 +127,12 @@ namespace boost
typedef typename Container::value_type::second_type value_type;
typedef value_type& reference;
typedef lvalue_property_map_tag category;
lazy_property_map(Container& m, Generator g= Generator())
: _m(m)
, _g(g)
{ }
reference operator[](const key_type& k) const
{
typename Container::iterator found= _m.find(k);
......@@ -154,7 +142,7 @@ namespace boost
}
return found->second;
}
void set(const key_type& k, const value_type& v)
{ _m[k] = v; }
......@@ -162,7 +150,7 @@ namespace boost
{
return s[k];
}
friend void put(self& s, const key_type& k, const value_type& v)
{ s.set(k, v); }
......@@ -175,61 +163,6 @@ namespace boost
make_lazy_property_map(Container& c, Generator 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
......@@ -345,7 +345,7 @@ namespace open_query {
oqgraph_visit_dist<P,D>
make_oqgraph_visit_dist(const P& p, const D& d, stack_cursor *cursor)
{ return oqgraph_visit_dist<P,D>(p, d, cursor); }
template<bool record_weight, typename goal_filter, typename P>
struct GRAPHCORE_INTERNAL oqgraph_goal
......@@ -402,7 +402,7 @@ namespace open_query {
stack_cursor &m_cursor;
P m_p;
};
template<bool record_weight, typename goal_filter, typename P>
oqgraph_goal<record_weight, goal_filter, P>
make_oqgraph_goal(const Vertex& goal, const P& p, stack_cursor *cursor)
......@@ -820,7 +820,7 @@ namespace open_query
)
),
make_two_bit_judy_map(get(vertex_index, share->g)));
break;
break;
case BREADTH_FIRST:
breadth_first_visit(share->g, *orig, Q,
make_bfs_visitor(
......@@ -1060,9 +1060,8 @@ int edges_cursor::fetch_row(const row &row_info, row &result)
{
edge_iterator it, end;
reference ref;
size_t count= position;
for (tie(it, end)= edges(share->g); count && it != end; ++it, --count)
;
tie(it, end)= edges(share->g);
it+= position;
if (it != end)
ref= reference(position+1, *it);
if (int res= fetch_row(row_info, result, ref))
......
......@@ -274,13 +274,13 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
reinterpret_cast<oqgraph_table_option_struct*>(table->s->option_struct);
error_message.length(0);
const char* p= strend(name)-1;
while (p > name && *p != '\\' && *p != '/')
--p;
init_tmp_table_share(
thd, share, table->s->db.str, table->s->db.length,
thd, share, table->s->db.str, table->s->db.length,
options->table_name, "");
size_t tlen= strlen(options->table_name);
......@@ -303,7 +303,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
free_table_share(share);
return thd->main_da.sql_errno();
}
if (ha_create_table_from_engine(thd, table->s->db.str, options->table_name))
{
free_table_share(share);
......@@ -313,7 +313,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
thd->clear_error();
continue;
}
if (int err= share->error)
{
open_table_error(share, share->error, share->open_errno, share->errarg);
......@@ -341,7 +341,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
}
edges->reginfo.lock_type= TL_READ;
edges->tablenr= thd->current_tablenr++;
edges->status= STATUS_NO_RECORD;
edges->file->ha_start_of_new_statement();
......@@ -349,18 +349,18 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
edges->pos_in_table_list= 0;
edges->clear_column_bitmaps();
bfill(table->record[0], table->s->null_bytes, 255);
bfill(table->record[1], table->s->null_bytes, 255);
bfill(table->record[1], table->s->null_bytes, 255);
// We expect fields origid, destid and optionally weight
origid= destid= weight= 0;
if (!edges->file)
{
print_error("Some error occurred opening table '%s'", options->table_name);
free_table_share(share);
return -1;
}
for (Field **field= edges->field; *field; ++field)
{
if (strcmp(options->origid, (*field)->field_name))
......@@ -377,7 +377,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
origid = *field;
break;
}
for (Field **field= edges->field; *field; ++field)
{
if (strcmp(options->destid, (*field)->field_name))
......@@ -394,7 +394,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
destid = *field;
break;
}
for (Field **field= edges->field; options->weight && *field; ++field)
{
if (strcmp(options->weight, (*field)->field_name))
......@@ -411,7 +411,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
weight = *field;
break;
}
if (!origid || !destid || (!weight && options->weight))
{
print_error("Data columns missing on table '%s'", options->table_name);
......@@ -419,7 +419,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
free_table_share(share);
return -1;
}
if (!(graph_share = oqgraph::create(edges, origid, destid, weight)))
{
print_error("Unable to create graph instance.");
......@@ -428,9 +428,9 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
return -1;
}
ref_length= oqgraph::sizeof_ref;
graph = oqgraph::create(graph_share);
return 0;
}
......
......@@ -111,11 +111,11 @@ class ha_oqgraph: public handler
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
int cmp_ref(const byte *ref1, const byte *ref2);
bool get_error_message(int error, String* buf);
void print_error(const char* fmt, ...);
private:
void update_key_stats();
String error_message;
......
......@@ -90,6 +90,19 @@ open_query::judy_bitset::size_type open_query::judy_bitset::count() const
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
{
int rc;
......
......@@ -41,9 +41,21 @@ namespace open_query
: array(0)
{ }
judy_bitset(const judy_bitset& src)
: array(0)
{
set(src);
}
~judy_bitset()
{ clear(); }
judy_bitset& operator=(const judy_bitset& src)
{
clear();
return set(src);
}
void clear();
bool empty() const { return !array; }
bool none() const { return npos == find_first(); }
......@@ -56,6 +68,8 @@ namespace open_query
return setbit(n);
}
judy_bitset& set(const judy_bitset& src);
judy_bitset& reset(size_type n);
judy_bitset& flip(size_type n);
bool test(size_type) const;
......@@ -85,7 +99,7 @@ namespace open_query
{ if (value) j.flip(n); return *this; }
reference& operator-=(bool value)
{ if (value) j.reset(n); return *this; }
bool operator~() const { return !j.test(n); }
operator bool() const { return j.test(n); }
reference& flip() { j.flip(n); return *this; }
......@@ -94,10 +108,10 @@ namespace open_query
judy_bitset& j;
size_type n;
};
reference operator[](size_type n) { return reference(*this, n); }
bool operator[](size_type n) const { return test(n); }
size_type find_first() const;
size_type find_next(size_type n) const;
private:
......
......@@ -26,3 +26,51 @@
#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
struct edge_iterator
{
typedef edge_iterator self;
typedef edge_descriptor value_type;
typedef edge_descriptor& reference;
typedef edge_descriptor pointer;
typedef edge_info value_type;
typedef edge_info& reference;
typedef edge_info pointer;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
edge_iterator() { }
edge_iterator(row_cursor iter) : _iter(iter) { }
edge_descriptor operator*() { return _iter->_current; }
self& operator++() { ++(*_iter); return *this; }
self operator++(int) { self t= *this; ++(*this); return t; }
bool operator==(const self& x) { return _iter == x._iter; }
bool operator!=(const self& x) { return _iter != x._iter; }
boost::optional<row_cursor> _iter;
edge_iterator(const graph_ptr& graph, size_t offset=0)
: _graph(graph)
, _offset(offset) { }
edge_iterator(const edge_iterator& pos)
: _graph(pos._graph)
, _offset(pos._offset) { }
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
{
typedef vertex_iterator self;
typedef vertex_descriptor value_type;
typedef vertex_descriptor& reference;
typedef vertex_descriptor pointer;
typedef vertex_id value_type;
typedef vertex_id& reference;
typedef vertex_id pointer;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
vertex_iterator() { }
vertex_iterator(edge_iterator iter) : _iter(iter) { }
vertex_descriptor operator*()
vertex_iterator(const cursor_ptr& pos) : _cursor(pos.operator->()) { }
vertex_id operator*() const
{
if (!_seen.test(_iter._iter->operator*().first))
return _iter._iter->_cache->vertex(_iter._iter->operator*().first);
edge_info edge(*_cursor);
if (!_seen.test(edge.origid()))
return edge.origid();
else
return _iter._iter->_cache->vertex(_iter._iter->operator*().second);
return edge.destid();
}
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
{
_seen.set(_iter._iter->operator*().second);
_seen.set(edge.destid());
}
while (_iter._iter->_current &&
_seen.test(_iter._iter->operator*().first) &&
_seen.test(_iter._iter->operator*().second))
while (_seen.test(edge.origid()) && _seen.test(edge.destid()))
{
++_iter;
if (_cursor->seek_next())
break;
edge= _cursor;
}
return *this;
}
self operator++(int) { self t= *this; ++(*this); return t; }
bool operator==(const self& x) { return _iter == x._iter; }
bool operator!=(const self& x) { return _iter != x._iter; }
edge_iterator _iter;
self operator++(int) { cursor* t(new cursor(*_cursor)); ++(*this); return vertex_iterator(t); }
bool operator==(const self& x) { return *_cursor == *x._cursor; }
bool operator!=(const self& x) { return *_cursor != *x._cursor; }
cursor_ptr _cursor;
open_query::judy_bitset _seen;
};
......@@ -116,74 +127,70 @@ namespace oqgraph3
struct out_edge_iterator
{
typedef out_edge_iterator self;
typedef vertex_info::edge_list_type::const_iterator iter_type;
typedef edge_descriptor value_type;
typedef edge_descriptor& reference;
typedef edge_descriptor pointer;
typedef edge_info value_type;
typedef edge_info& reference;
typedef edge_info pointer;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
out_edge_iterator() { }
out_edge_iterator(iter_type iter, const vertex_descriptor& v)
: _iter(iter), _v(v) { }
edge_descriptor operator*()
{ return _v->_cache->edge(edge_key(*_iter)); }
self& operator++() { ++_iter; return *this; }
self operator++(int) { self t= *this; ++(*this); return t; }
bool operator==(const self& x) { return _iter == x._iter; }
bool operator!=(const self& x) { return _iter != x._iter; }
iter_type _iter;
vertex_descriptor _v;
out_edge_iterator(const cursor_ptr& cursor) : _cursor(cursor) { }
value_type operator*() { return value_type(_cursor); }
self& operator++() { _cursor->seek_next(); return *this; }
self operator++(int)
{ cursor_ptr t(new cursor(*_cursor)); ++(*this); return out_edge_iterator(t); }
bool operator==(const self& x) { return _cursor == x._cursor; }
bool operator!=(const self& x) { return _cursor != x._cursor; }
cursor_ptr _cursor;
};
struct in_edge_iterator
{
typedef in_edge_iterator self;
typedef vertex_info::edge_list_type::const_iterator iter_type;
typedef edge_descriptor value_type;
typedef edge_descriptor& reference;
typedef edge_descriptor pointer;
typedef edge_info value_type;
typedef edge_info& reference;
typedef edge_info pointer;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
in_edge_iterator() { }
in_edge_iterator(iter_type iter, const vertex_descriptor& v)
: _iter(iter), _v(v) { }
edge_descriptor operator*()
{ return _v->_cache->edge(edge_key(*_iter)); }
self& operator++() { ++_iter; return *this; }
self operator++(int) { self t= *this; ++(*this); return t; }
bool operator==(const self& x) { return _iter == x._iter; }
bool operator!=(const self& x) { return _iter != x._iter; }
iter_type _iter;
vertex_descriptor _v;
in_edge_iterator(const cursor_ptr& cursor) : _cursor(cursor) { }
value_type operator*() { return value_type(_cursor); }
self& operator++() { _cursor->seek_next(); return *this; }
self operator++(int)
{ cursor_ptr t(new cursor(*_cursor)); ++(*this); return in_edge_iterator(t); }
bool operator==(const self& x) { return _cursor == x._cursor; }
bool operator!=(const self& x) { return _cursor != x._cursor; }
cursor_ptr _cursor;
};
struct vertex_index_property_map
{
typedef vertex_id value_type;
typedef value_type reference;
typedef vertex_descriptor key_type;
typedef vertex_id key_type;
typedef boost::readable_property_map_tag category;
vertex_index_property_map(const graph& g) : _g(g) { }
const graph& _g;
friend inline reference
get(const vertex_index_property_map&, key_type key)
{ return key; }
};
struct edge_weight_property_map
{
typedef weight_t value_type;
typedef value_type reference;
typedef edge_descriptor key_type;
typedef edge_info key_type;
typedef boost::readable_property_map_tag category;
edge_weight_property_map(const graph& g) : _g(g) { }
const graph& _g;
};
struct edge_index_property_map
{
typedef edge_key::ref_type value_type;
typedef const edge_key::ref_type& reference;
typedef edge_descriptor key_type;
typedef cursor_ptr value_type;
typedef cursor_ptr reference;
typedef edge_info key_type;
typedef boost::readable_property_map_tag category;
edge_index_property_map(const graph& g) : _g(g) { }
const graph& _g;
......@@ -196,17 +203,17 @@ namespace boost
template<>
struct graph_traits<oqgraph3::graph>
{
typedef oqgraph3::vertex_descriptor vertex_descriptor;
typedef oqgraph3::edge_descriptor edge_descriptor;
typedef oqgraph3::vertex_id vertex_descriptor;
typedef oqgraph3::edge_info edge_descriptor;
typedef boost::adjacency_iterator_generator<
oqgraph3::graph,
oqgraph3::vertex_descriptor,
oqgraph3::vertex_id,
oqgraph3::out_edge_iterator>::type adjacency_iterator;
typedef oqgraph3::out_edge_iterator out_edge_iterator;
typedef oqgraph3::in_edge_iterator in_edge_iterator;
typedef oqgraph3::vertex_iterator vertex_iterator;
typedef oqgraph3::edge_iterator edge_iterator;
typedef boost::directed_tag directed_category;
typedef boost::allow_parallel_edge_tag edge_parallel_category;
typedef oqgraph3::traversal_category traversal_category;
......@@ -214,16 +221,16 @@ namespace boost
typedef oqgraph3::vertices_size_type vertices_size_type;
typedef oqgraph3::edges_size_type edges_size_type;
typedef oqgraph3::degree_size_type degree_size_type;
static inline vertex_descriptor null_vertex()
{ return oqgraph3::vertex_descriptor(); }
static inline oqgraph3::vertex_id null_vertex()
{ return oqgraph3::vertex_id(-1); }
};
template<>
struct graph_traits<const oqgraph3::graph>
: public graph_traits<oqgraph3::graph>
{ };
template <>
struct graph_property_type<oqgraph3::graph>
{
......@@ -235,7 +242,7 @@ namespace boost
{
typedef no_property type;
};
template <>
struct edge_property_type<oqgraph3::graph>
{
......@@ -253,53 +260,110 @@ namespace boost
{
typedef no_vertex_bundle type;
};
template <>
struct edge_bundle_type<oqgraph3::graph>
{
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<
graph_traits<oqgraph3::graph>::out_edge_iterator,
graph_traits<oqgraph3::graph>::out_edge_iterator>
out_edges(
graph_traits<oqgraph3::graph>::vertex_descriptor v,
const oqgraph3::graph&)
const oqgraph3::graph& g)
{
const oqgraph3::vertex_info::edge_list_type&
iter= v->out_edges();
oqgraph3::cursor*
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(
graph_traits<oqgraph3::graph>::out_edge_iterator(iter.begin(), v),
graph_traits<oqgraph3::graph>::out_edge_iterator(iter.end(), v));
graph_traits<oqgraph3::graph>::out_edge_iterator(start),
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<
graph_traits<oqgraph3::graph>::in_edge_iterator,
graph_traits<oqgraph3::graph>::in_edge_iterator>
in_edges(
graph_traits<oqgraph3::graph>::vertex_descriptor v,
const oqgraph3::graph&)
const oqgraph3::graph& g)
{
const oqgraph3::vertex_info::edge_list_type&
iter= v->out_edges();
oqgraph3::cursor*
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(
graph_traits<oqgraph3::graph>::in_edge_iterator(iter.begin(), v),
graph_traits<oqgraph3::graph>::in_edge_iterator(iter.end(), v));
graph_traits<oqgraph3::graph>::in_edge_iterator(start),
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
inline std::pair<
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(
graph_traits<oqgraph3::graph>::edge_iterator(
oqgraph3::row_cursor(&g).first()),
const_cast<oqgraph3::graph*>(&g), start),
graph_traits<oqgraph3::graph>::edge_iterator(
oqgraph3::row_cursor(&g).end()));
const_cast<oqgraph3::graph*>(&g), end));
}
inline std::pair<
......@@ -307,12 +371,13 @@ namespace boost
graph_traits<oqgraph3::graph>::vertex_iterator>
vertices(const oqgraph3::graph& g)
{
std::pair<
graph_traits<oqgraph3::graph>::edge_iterator,
graph_traits<oqgraph3::graph>::edge_iterator> epair= edges(g);
oqgraph3::cursor*
start= new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g));
start->seek_to(boost::none, boost::none);
return std::make_pair(
graph_traits<oqgraph3::graph>::vertex_iterator(epair.first),
graph_traits<oqgraph3::graph>::vertex_iterator(epair.second));
graph_traits<oqgraph3::graph>::vertex_iterator(start),
graph_traits<oqgraph3::graph>::vertex_iterator(
new oqgraph3::cursor(const_cast<oqgraph3::graph*>(&g))));
}
inline graph_traits<oqgraph3::graph>::vertices_size_type
......@@ -335,7 +400,7 @@ namespace boost
typedef void type;
typedef oqgraph3::edge_weight_property_map const_type;
};
template<>
struct property_map<oqgraph3::graph, vertex_index_t>
{
......@@ -349,17 +414,17 @@ namespace boost
typedef void type;
typedef oqgraph3::edge_index_property_map const_type;
};
inline property_map<
oqgraph3::graph,
edge_weight_t>::const_type::reference
get(
edge_weight_t,
const oqgraph3::graph& g,
const oqgraph3::graph& g,
const property_map<
oqgraph3::graph,
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<
oqgraph3::graph,
......@@ -371,365 +436,48 @@ namespace boost
inline property_map<
oqgraph3::graph,
edge_weight_t>::const_type::reference
get(property_map<oqgraph3::graph,
edge_weight_t>::const_type p,
get(const property_map<oqgraph3::graph,
edge_weight_t>::const_type& p,
const property_map<
oqgraph3::graph,
edge_weight_t>::const_type::key_type& key)
{ return oqgraph3::row_cursor(
key, const_cast<oqgraph3::graph*>(&p._g))->_weight; }
{ return key.weight(); }
inline property_map<
oqgraph3::graph,
edge_index_t>::const_type::reference
get(edge_index_t,
const oqgraph3::graph&,
const oqgraph3::graph&,
const property_map<
oqgraph3::graph,
oqgraph3::graph,
edge_index_t>::const_type::key_type& key)
{ return key->_ref; }
{ return key._cursor; }
inline property_map<oqgraph3::graph, edge_index_t>::const_type
get(edge_index_t, const oqgraph3::graph& g)
{ return property_map<oqgraph3::graph, edge_index_t>::const_type(g); }
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,
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
get(vertex_index_t, const oqgraph3::graph&,
get(vertex_index_t, const oqgraph3::graph&,
const property_map<oqgraph3::graph,
vertex_index_t>::const_type::key_type& key)
{ return key->id; }
{ return key; }
inline property_map<oqgraph3::graph, vertex_index_t>::const_type
get(vertex_index_t, const oqgraph3::graph& 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>
find_vertex(oqgraph3::vertex_id id, const oqgraph3::graph& g)
{
graph_traits<oqgraph3::graph>::vertex_descriptor tmp(
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;
return id;
}
// 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 @@
#define MYSQL_SERVER
#include "mysql_priv.h"
oqgraph3::vertex_info::~vertex_info()
{ }
void oqgraph3::vertex_info::release()
{
if (!--(_ref_count))
{
oqgraph3::graph& cache= *_cache;
oqgraph3::graph::vertex_cache_type::const_iterator it;
static int debugid = 0;
if (!_on_gc)
{
cache._gc_vertices.push(this);
_on_gc= true;
}
oqgraph3::vertex_id oqgraph3::edge_info::origid() const
{ return _cursor->get_origid(); }
while (!cache._gc_running && cache._gc_vertices.size() > 64)
{
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::vertex_id oqgraph3::edge_info::destid() const
{ return _cursor->get_destid(); }
oqgraph3::edge_key::~edge_key()
{ }
oqgraph3::weight_t oqgraph3::edge_info::weight() const
{ return _cursor->get_weight(); }
void oqgraph3::edge_key::release() const
bool oqgraph3::cursor_ptr::operator==(const cursor_ptr& x) const
{
if (!--(_ref_count))
{
oqgraph3::graph& cache= *_cache;
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;
}
}
if (get() == x.get())
return true;
return (*this)->record_position() == x->_position;
}
oqgraph3::graph::graph(
::TABLE* table,
::Field* source,
::Field* target,
::Field* weight)
: _gc_running(false)
, _ref_count(0)
, _table(table)
, _source(source)
, _target(target)
, _weight(weight)
bool oqgraph3::cursor_ptr::operator!=(const cursor_ptr& x) const
{
bitmap_set_bit(table->read_set, source->field_index);
bitmap_set_bit(table->read_set, target->field_index);
if (weight)
bitmap_set_bit(table->read_set, weight->field_index);
table->file->column_bitmaps_signal();
if (get() == x.get())
return false;
return (*this)->record_position() != x->_position;
}
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++()
{
printf("%s:%d\n", __func__, __LINE__);
if (!_current)
return *this;
oqgraph3::cursor::cursor(const cursor& src)
: _ref_count(0)
, _graph(src._graph)
, _index(src._index)
, _parts(src._parts)
, _key(src._key)
, _position(src.record_position())
, _debugid(++debugid)
{ }
graph::edge_cache_type::iterator
current= _cache->_cache_edges.find(*_current);
oqgraph3::cursor::~cursor()
{
if (this == _graph->_cursor)
{
if (_graph->_cursor->_index >= 0)
_graph->_table->file->ha_index_end();
else
_graph->_table->file->ha_rnd_end();
_graph->_cursor= 0;
_graph->_stale= false;
}
}
if (current->second._next)
const std::string& oqgraph3::cursor::record_position() const
{
if (_graph->_stale && _graph->_cursor)
{
graph::edge_cache_type::iterator next=
_cache->_cache_edges.find(edge_key(*current->second._next));
if (_cache->_cache_edges.end() != next)
TABLE& table= *_graph->_table;
table.file->position(table.record[0]);
_graph->_cursor->_position.assign(
(const char*) table.file->ref, table.file->ref_length);
if (_graph->_cursor->_index >= 0)
{
_current.reset(&next->first);
return *this;
key_copy((uchar*) _graph->_cursor->_key.data(), table.record[0],
table.s->key_info + _index, table.s->key_info[_index].key_length, true);
}
}
TABLE& table= *_cache->_table;
_graph->_stale= false;
}
return _position;
}
table.file->ha_index_init(0, 1);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
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_AFTER_KEY))
void oqgraph3::cursor::clear_position()
{
_position.clear();
if (this == _graph->_cursor)
{
table.file->ha_index_end();
_current.reset(0);
return *this;
_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)
void oqgraph3::cursor::save_position()
{
record_position();
if (this == _graph->_cursor)
{
// 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;
TABLE& table= *_graph->_table;
if (_graph->_cursor->_index >= 0)
table.file->ha_index_end();
else
table.file->ha_rnd_end();
_graph->_cursor= 0;
_graph->_stale= false;
}
_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()
int oqgraph3::cursor::restore_position()
{
printf("%s:%d\n", __func__, __LINE__);
TABLE& table= *_cache->_table;
table.file->ha_index_init(0, 1);
TABLE& table= *_graph->_table;
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);
if (!_position.size())
return ENOENT;
if (this == _graph->_cursor)
return 0;
if (_graph->_cursor)
_graph->_cursor->save_position();
edge_key tmp(table.key_info->key_length, _cache);
if (_origid || _destid)
{
if (int rc= table.file->ha_index_init(_index, 1))
return rc;
key_copy(
reinterpret_cast<uchar*>(const_cast<char*>(tmp._ref.data())),
table.record[0],
table.key_info,
tmp._ref.size(), true);
restore_record(&table, s->default_values);
graph::edge_cache_type::iterator
found= _cache->_cache_edges.find(tmp);
if (found != _cache->_cache_edges.end())
if (_origid)
{
// we already had a row
_current.reset(&found->first);
bitmap_set_bit(table.write_set, _graph->_source->field_index);
_graph->_source->store(*_origid, 1);
bitmap_clear_bit(table.write_set, _graph->_source->field_index);
}
else
if (_destid)
{
_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,
0
)
)).first->first);
bitmap_set_bit(table.write_set, _graph->_target->field_index);
_graph->_target->store(*_destid, 1);
bitmap_clear_bit(table.write_set, _graph->_target->field_index);
}
}
table.file->ha_index_end();
if (int rc= table.file->ha_index_init(_index, 1))
return rc;
return *this;
}
oqgraph3::row_cursor& oqgraph3::row_cursor::last()
{
printf("%s:%d\n", __func__, __LINE__);
TABLE& table= *_cache->_table;
table.file->ha_index_init(0, 1);
if (int rc= table.file->ha_index_read_map(
table.record[0], (const uchar*) _key.data(),
(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();
return rc;
}
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);
table.file->position(table.record[0]);
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())
while (memcmp(table.file->ref, _position.data(), table.file->ref_length))
{
// we already had a row
_current.reset(&found->first);
if (int rc= table.file->ha_index_next(table.record[0]))
{
table.file->ha_index_end();
return rc;
}
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();
return ENOENT;
}
table.file->position(table.record[0]);
}
else
update_virtual_fields(table.in_use, &table);
}
else
{
if (int rc= table.file->ha_rnd_init(1))
return rc;
if (int rc= table.file->ha_rnd_pos(
table.record[0], (uchar*) _position.data()))
{
_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,
0
)
)).first->first);
table.file->ha_rnd_end();
return rc;
}
update_virtual_fields(table.in_use, &table);
}
table.file->ha_index_end();
_graph->_cursor= this;
_graph->_stale= false;
return *this;
return 0;
}
oqgraph3::row_cursor& oqgraph3::row_cursor::operator--()
oqgraph3::vertex_id oqgraph3::cursor::get_origid()
{
printf("%s:%d\n", __func__, __LINE__);
if (!_current)
return last();
graph::edge_cache_type::iterator
current= _cache->_cache_edges.find(*_current);
if (_origid)
return *_origid;
if (current->second._prev)
if (this != _graph->_cursor)
{
graph::edge_cache_type::iterator prev=
_cache->_cache_edges.find(edge_key(*current->second._prev));
if (_cache->_cache_edges.end() != prev)
{
_current.reset(&prev->first);
return *this;
}
if (restore_position())
return -1;
}
return static_cast<vertex_id>(_graph->_source->val_int());
}
oqgraph3::vertex_id oqgraph3::cursor::get_destid()
{
if (_destid)
return *_destid;
TABLE& table= *_cache->_table;
table.file->ha_index_init(0, 1);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
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))
if (this != _graph->_cursor)
{
table.file->ha_index_end();
_current.reset();
return *this;
if (restore_position())
return -1;
}
return static_cast<vertex_id>(_graph->_target->val_int());
}
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)
oqgraph3::weight_t oqgraph3::cursor::get_weight()
{
if (!_graph->_weight)
return 1.0;
if (this != _graph->_cursor)
{
// 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;
if (restore_position())
return -1;
}
_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;
return static_cast<vertex_id>(_graph->_weight->val_int());
}
oqgraph3::row_cursor& oqgraph3::row_cursor::operator+=(difference_type delta)
int oqgraph3::cursor::seek_next()
{
printf("%s:%d\n", __func__, __LINE__);
if (!delta || !_current)
return *this;
if (delta < 0)
return *this -= (-delta);
if (this != _graph->_cursor)
{
if (int rc= restore_position())
return rc;
}
graph::edge_cache_type::iterator
current= _cache->_cache_edges.find(*_current);
TABLE& table= *_graph->_table;
bool index_started= false;
TABLE& table= *_cache->_table;
while (delta-- > 0)
if (_index < 0)
{
if (_cache->_cache_edges.end() != current)
if (int rc= table.file->ha_rnd_next(table.record[0]))
{
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;
}
if (!index_started)
{
table.file->ha_index_init(0, 1);
index_started= true;
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
if (table.file->ha_index_read_map(
table.record[0],
reinterpret_cast<const uchar*>(current->second._next->data()),
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_KEY_OR_NEXT))
{
table.file->ha_index_end();
_current.reset();
return *this;
}
}
else
{
if (!index_started)
{
table.file->ha_index_init(0, 1);
index_started= true;
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
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_AFTER_KEY))
{
table.file->ha_index_end();
_current.reset();
return *this;
}
}
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;
table.file->ha_rnd_end();
return clear_position(rc);
}
else
{
if (!index_started)
return *this;
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_next");
if (table.file->ha_index_next(table.record[0]))
{
table.file->ha_index_end();
_current.reset();
return *this;
}
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);
return 0;
}
current= _cache->_cache_edges.find(tmp);
}
if (int rc= table.file->ha_index_next(table.record[0]))
{
table.file->ha_index_end();
return clear_position(rc);
}
if (index_started)
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();
return clear_position(ENOENT);
}
return *this;
return 0;
}
oqgraph3::row_cursor& oqgraph3::row_cursor::operator-=(difference_type delta)
int oqgraph3::cursor::seek_prev()
{
printf("%s:%d\n", __func__, __LINE__);
if (!delta || !_current)
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 (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;
}
if (!index_started)
{
table.file->ha_index_init(0, 1);
index_started= true;
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
if (table.file->ha_index_read_map(
table.record[0],
reinterpret_cast<const uchar*>(current->second._next->data()),
(key_part_map)((1 << table.key_info->key_parts) - 1),
HA_READ_KEY_OR_PREV))
{
table.file->ha_index_end();
return first();
}
}
else
{
if (!index_started)
{
table.file->ha_index_init(0, 1);
index_started= true;
}
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
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();
return first();
}
}
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 (_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= found;
}
else
{
if (!index_started)
return first();
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_prev");
if (table.file->ha_index_prev(table.record[0]))
{
table.file->ha_index_end();
return first();
}
if (int rc= restore_position())
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);
if (_index < 0)
{
return -1; // not supported
}
current= _cache->_cache_edges.find(tmp);
}
if (int rc= table.file->ha_index_prev(table.record[0]))
{
table.file->ha_index_end();
return clear_position(rc);
}
if (index_started)
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();
return clear_position(ENOENT);
}
return *this;
return 0;
}
oqgraph3::vertex_descriptor oqgraph3::graph::vertex(vertex_id id)
{
printf("%s:%d\n", __func__, __LINE__);
vertex_cache_type::const_iterator
found= _cache_vertices.find(vertex_info(id));
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)
int oqgraph3::cursor::seek_to(
boost::optional<vertex_id> origid,
boost::optional<vertex_id> destid)
{
printf("%s:%d\n", __func__, __LINE__);
edge_cache_type::const_iterator
found= _cache_edges.find(key);
if (_graph->_cursor && this != _graph->_cursor)
_graph->_cursor->save_position();
if (_cache_edges.end() != found)
return edge_descriptor(&found->first);
TABLE& table= *_graph->_table;
_index= -1;
_origid= origid;
_destid= destid;
TABLE& table= *_table;
if (origid || destid)
{
Field *source= _graph->_source;
Field *target= _graph->_target;
table.file->ha_index_init(0, 0);
uint source_fieldpos= _graph->_source->offset(table.record[0]);
uint target_fieldpos= _graph->_target->offset(table.record[0]);
printf("%s:%d - %s\n", __func__, __LINE__, "ha_index_read_map");
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();
return edge_descriptor();
}
if (!destid)
{
int i= 0;
for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
{
if (key_info->key_part[0].offset != source_fieldpos)
continue;
update_virtual_fields(table.in_use, &table);
if (table.file->ha_index_init(i, 1))
continue;
table.file->ha_index_end();
return edge_descriptor(&_cache_edges.insert(
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);
}
restore_record(&table, s->default_values);
oqgraph3::edge_descriptor oqgraph3::graph::edge(
const vertex_descriptor& source,
const vertex_descriptor& target)
{
printf("%s:%d\n", __func__, __LINE__);
vertex_cache_type::const_iterator xsource= _cache_vertices.find(*source);
if (_cache_vertices.end() != xsource && xsource->_out_edges)
{
const vertex_info::edge_list_type& edges= *xsource->_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));
bitmap_set_bit(table.write_set, source->field_index);
source->store(*_origid, 1);
bitmap_clear_bit(table.write_set, source->field_index);
if (_cache_edges.end() != found &&
target->id == found->second.second)
{
return edge_descriptor(&found->first);
uchar* buff= (uchar*) my_alloca(source->pack_length());
source->get_key_image(buff, source->pack_length(), Field::itRAW);
_key.clear();
_key.append((char*) buff, source->pack_length());
_key.resize(key_info->key_length, '\0');
my_afree(buff);
_parts= 1;
_index= i;
break;
}
}
return edge_descriptor();
}
else if (!origid)
{
int i= 0;
for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
{
if (key_info->key_part[0].offset != target_fieldpos)
continue;
vertex_cache_type::const_iterator xtarget= _cache_vertices.find(*target);
if (table.file->ha_index_init(i, 1))
continue;
if (_cache_vertices.end() != xtarget && xtarget->_in_edges)
{
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));
restore_record(&table, s->default_values);
if (_cache_edges.end() != found &&
source->id == found->second.first)
{
return edge_descriptor(&found->first);
bitmap_set_bit(table.write_set, target->field_index);
target->store(*_destid, 1);
bitmap_clear_bit(table.write_set, target->field_index);
uchar* buff= (uchar*) my_alloca(target->pack_length());
target->get_key_image(buff, target->pack_length(), Field::itRAW);
_key.clear();
_key.append((char*) buff, target->pack_length());
_key.resize(key_info->key_length, '\0');
my_afree(buff);
_parts= 1;
_index= i;
break;
}
}
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;
for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
{
if (key_info->key_parts < 2)
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))
else
{
// 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);
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)
int i= 0;
for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
{
// We have found the edge,
update_virtual_fields(table.in_use, &table);
if (key_info->key_parts < 2)
continue;
if (!((key_info->key_part[0].offset == target_fieldpos &&
key_info->key_part[1].offset == source_fieldpos) ||
(key_info->key_part[1].offset == target_fieldpos &&
key_info->key_part[0].offset == source_fieldpos)))
continue;
table.file->ha_index_end();
my_afree(key_prefix);
edge_key tmp(table.key_info->key_length, this);
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_edges.find(tmp);
if (_cache_edges.end() != found)
{
// 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);
if (table.file->ha_index_init(i, 1))
continue;
restore_record(&table, s->default_values);
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;
}
}
}
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)
if (_index < 0)
{
return edge_descriptor(&found->first);
// no suitable index found
return clear_position(ENXIO);
}
}
return edge_descriptor();
}
if (int rc= table.file->ha_index_read_map(
table.record[0], (uchar*) _key.data(),
(key_part_map) ((1U << _parts) - 1),
table.s->key_info[_index].key_parts == _parts ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{
table.file->ha_index_end();
return clear_position(rc);
}
oqgraph3::edges_size_type oqgraph3::graph::num_edges() const
{
return _table->file->stats.records;
}
update_virtual_fields(table.in_use, &table);
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;
for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
if ((_origid && vertex_id(_graph->_source->val_int()) != *_origid) ||
(_destid && vertex_id(_graph->_target->val_int()) != *_destid))
{
if (key_info->key_part[0].offset == source_fieldpos)
{
// 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);
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;
}
_out_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->_source->val_int() == id);
table.file->ha_index_end();
my_afree(key);
break;
}
table.file->ha_index_end();
}
table.file->ha_index_end();
return clear_position(ENOENT);
}
}
return *_out_edges;
}
const oqgraph3::vertex_info::edge_list_type&
oqgraph3::vertex_info::in_edges()
{
printf("%s:%d\n", __func__, __LINE__);
if (!_in_edges)
else
{
_in_edges = edge_list_type();
TABLE& table= *_cache->_table;
uint target_fieldpos= _cache->_target->offset(table.record[0]);
int i= 0;
for( ::KEY *key_info= table.s->key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
if (int rc= table.file->ha_rnd_init(true))
return clear_position(rc);
if (int rc= table.file->ha_rnd_next(table.record[0]))
{
if (key_info->key_part[0].offset == target_fieldpos)
{
// we can use this key
restore_record(&table, s->default_values);
bitmap_set_bit(table.write_set, _cache->_target->field_index);
_cache->_target->store(id, 1);
bitmap_clear_bit(table.write_set, _cache->_target->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);
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);
table.file->ha_index_end();
my_afree(key);
break;
}
table.file->ha_index_end();
}
table.file->ha_rnd_end();
return clear_position(rc);
}
}
return *_in_edges;
}
std::size_t oqgraph3::vertex_info::degree()
{
printf("%s:%d\n", __func__, __LINE__);
return out_edges().size() + in_edges().size();
_graph->_cursor= this;
_graph->_stale= true;
return 0;
}
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 (*this)->in_edges().size();
return record_position() == x._position;
}
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 (*this)->out_edges().size();
return record_position() != x._position;
}
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__);
return (*this)->_cache->vertex(
oqgraph3::row_cursor(*this, (*this)->_cache)->first);
bitmap_set_bit(table->read_set, source->field_index);
bitmap_set_bit(table->read_set, target->field_index);
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 (*this)->_cache->vertex(
oqgraph3::row_cursor(*this, (*this)->_cache)->second);
return _table->file->stats.records;
}
......@@ -44,292 +44,114 @@ namespace oqgraph3
{
typedef open_query::VertexID vertex_id;
typedef open_query::EdgeWeight weight_t;
typedef size_t vertices_size_type;
typedef size_t edges_size_type;
typedef size_t degree_size_type;
struct graph;
struct vertex_info;
struct cursor;
typedef boost::intrusive_ptr<graph> graph_ptr;
struct edge_key
struct cursor_ptr : public boost::intrusive_ptr<cursor>
{
typedef std::string ref_type;
ref_type _ref;
mutable int _ref_count;
cursor_ptr() : boost::intrusive_ptr<cursor>() { }
cursor_ptr(cursor* pos) : boost::intrusive_ptr<cursor>(pos) { }
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
{
typedef vertex_id vertex_id_type;
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();
const edge_list_type& in_edges();
std::size_t degree();
void release();
friend void intrusive_ptr_add_ref(vertex_info* ptr)
{ ++ptr->_ref_count; }
friend void intrusive_ptr_release(vertex_info* ptr)
{ ptr->release(); }
};
struct vertex_descriptor
: public boost::intrusive_ptr<vertex_info>
{
vertex_descriptor()
: boost::intrusive_ptr<vertex_info>()
{ }
vertex_descriptor(vertex_info* v)
: boost::intrusive_ptr<vertex_info>(v)
{ }
vertex_descriptor(const vertex_descriptor& v)
: boost::intrusive_ptr<vertex_info>(v)
{ }
degree_size_type in_degree() const;
degree_size_type out_degree() const;
friend degree_size_type in_degree(const vertex_descriptor& v, const graph&)
{ return v.in_degree(); }
friend degree_size_type out_degree(const vertex_descriptor& v, const graph&)
{ return v.out_degree(); }
operator const std::string&() const;
bool operator==(const cursor_ptr&) const;
bool operator!=(const cursor_ptr&) const;
};
struct edge_descriptor
: public boost::intrusive_ptr<const edge_key>
struct edge_info
{
edge_descriptor()
: boost::intrusive_ptr<const edge_key>()
{ }
edge_descriptor(const edge_key* e)
: boost::intrusive_ptr<const edge_key>(e)
{ }
edge_descriptor(const edge_descriptor& e)
: boost::intrusive_ptr<const edge_key>(e)
{ }
vertex_descriptor source() const;
vertex_descriptor target() const;
friend vertex_descriptor source(const edge_descriptor& e, const graph&)
{ return e.source(); }
friend vertex_descriptor target(const edge_descriptor& e, const graph&)
{ return e.target(); }
cursor_ptr _cursor;
edge_info() : _cursor(0) { }
explicit edge_info(const cursor_ptr& pos) : _cursor(pos) { }
edge_info& operator=(const cursor_ptr& pos) { _cursor= pos; return *this; }
vertex_id origid() const;
vertex_id destid() const;
weight_t weight() const;
bool operator==(const edge_info&) const;
bool operator!=(const edge_info&) const;
};
struct row_info
: public std::pair<vertex_id, vertex_id>
struct cursor
{
weight_t _weight;
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);}
mutable int _ref_count;
graph_ptr _graph;
int _index;
unsigned _parts;
std::string _key;
std::string _position;
int _debugid;
boost::optional<vertex_id> _origid;
boost::optional<vertex_id> _destid;
cursor(const graph_ptr& graph);
cursor(const cursor& src);
~cursor();
operator bool() const
{ return !_position.empty(); }
operator edge_info() const
{ return edge_info(const_cast<cursor*>(this)); }
vertex_id get_origid();
vertex_id get_destid();
weight_t get_weight();
int seek_to(
boost::optional<vertex_id> origid,
boost::optional<vertex_id> destid);
int seek_next();
int seek_prev();
void save_position();
int restore_position();
const std::string& record_position() const;
void clear_position();
int clear_position(int rc) { clear_position(); return rc; }
bool operator==(const cursor& x) const;
bool operator!=(const cursor& x) const;
friend void intrusive_ptr_add_ref(cursor* ptr)
{ ++ptr->_ref_count; }
friend void intrusive_ptr_release(cursor* ptr)
{ if (!--(ptr->_ref_count)) delete ptr; }
};
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
: public std::binary_function<Value, Value, bool>
{
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>
: public std::unary_function<edge_key, std::size_t>
{
boost::hash<edge_key::ref_type> ref_hasher;
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
{
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;
cursor* _cursor;
bool _stale;
edge_cache_type _cache_edges;
boost::queue<edge_key*> _gc_edges;
cursor_ptr _rnd_cursor;
size_t _rnd_pos;
vertex_cache_type _cache_vertices;
boost::queue<vertex_info*> _gc_vertices;
::TABLE* _table;
::Field* _source;
::Field* _target;
::Field* _weight;
graph(
::TABLE* table,
::Field* source,
::Field* target,
::Field* weight= 0);
~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;
......@@ -343,73 +165,5 @@ namespace oqgraph3
{ 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