Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
b965d031
Commit
b965d031
authored
Sep 30, 2012
by
Antony T Curtis
Browse files
Options
Browse Files
Download
Plain Diff
Merge OQGraph3 into MariaDB 5.5.27
parents
a0efc4bd
0fee6ce7
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
2127 additions
and
552 deletions
+2127
-552
storage/oqgraph/graphcore-graph.cc
storage/oqgraph/graphcore-graph.cc
+28
-0
storage/oqgraph/graphcore-graph.h
storage/oqgraph/graphcore-graph.h
+137
-17
storage/oqgraph/graphcore-types.h
storage/oqgraph/graphcore-types.h
+6
-0
storage/oqgraph/graphcore.cc
storage/oqgraph/graphcore.cc
+165
-172
storage/oqgraph/graphcore.h
storage/oqgraph/graphcore.h
+1
-1
storage/oqgraph/ha_oqgraph.cc
storage/oqgraph/ha_oqgraph.cc
+240
-355
storage/oqgraph/ha_oqgraph.h
storage/oqgraph/ha_oqgraph.h
+15
-7
storage/oqgraph/oqgraph_judy.cc
storage/oqgraph/oqgraph_judy.cc
+126
-0
storage/oqgraph/oqgraph_judy.h
storage/oqgraph/oqgraph_judy.h
+123
-0
storage/oqgraph/oqgraph_shim.cc
storage/oqgraph/oqgraph_shim.cc
+76
-0
storage/oqgraph/oqgraph_shim.h
storage/oqgraph/oqgraph_shim.h
+488
-0
storage/oqgraph/oqgraph_thunk.cc
storage/oqgraph/oqgraph_thunk.cc
+553
-0
storage/oqgraph/oqgraph_thunk.h
storage/oqgraph/oqgraph_thunk.h
+169
-0
No files found.
storage/oqgraph/graphcore-graph.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 Arjen G Lentz & Antony T Curtis for Open Query
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* ======================================================================
Open Query Graph Computation Engine, based on a concept by Arjen Lentz
Mk.III implementation by Antony Curtis & Arjen Lentz
For more information, documentation, support, enhancement engineering,
and non-GPL licensing, see http://openquery.com/graph
or contact graph@openquery.com
For packaged binaries, see http://ourdelta.org
======================================================================
*/
#include "graphcore-graph.h"
storage/oqgraph/graphcore-graph.h
View file @
b965d031
...
...
@@ -27,22 +27,142 @@
#ifndef oq_graphcore_graph_h_
#define oq_graphcore_graph_h_
typedef
adjacency_list
<
vecS
,
vecS
,
bidirectionalS
,
VertexInfo
,
EdgeInfo
>
Graph
;
#define GRAPH_WEIGHTMAP(G) get(&EdgeInfo::weight, G)
typedef
property_map
<
Graph
,
EdgeWeight
EdgeInfo
::*>::
type
weightmap_type
;
#define GRAPH_INDEXMAP(G) get(vertex_index, G)
typedef
property_map
<
Graph
,
vertex_index_t
>::
type
indexmap_type
;
#define GRAPH_IDMAP(G) get(&VertexInfo::id, G)
typedef
property_map
<
Graph
,
VertexID
VertexInfo
::*>::
type
idmap_type
;
#include "oqgraph_shim.h"
#include <boost/graph/two_bit_color_map.hpp>
namespace
boost
{
typedef
oqgraph3
::
graph
Graph
;
template
<
typename
IndexMap
=
identity_property_map
>
struct
two_bit_judy_map
{
typedef
typename
property_traits
<
IndexMap
>::
key_type
key_type
;
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
)
{
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
,
two_bit_color_type
value
)
{
typename
property_traits
<
IndexMap
>::
value_type
i
=
get
(
pm
.
index
,
key
);
pm
.
msb
.
set
(
i
,
value
&
2
);
pm
.
lsb
.
set
(
i
,
value
&
1
);
}
};
template
<
typename
IndexMap
>
inline
two_bit_judy_map
<
IndexMap
>
make_two_bit_judy_map
(
const
IndexMap
&
index
)
{
return
two_bit_judy_map
<
IndexMap
>
(
index
);
}
template
<
typename
Type
>
struct
default_lazy_initializer
{
template
<
typename
Key
>
Type
operator
()(
const
Key
&
)
const
{
return
Type
();
}
};
template
<
typename
Type
>
struct
copy_initializer
{
copy_initializer
(
const
Type
&
value
)
:
_
(
value
)
{
}
template
<
typename
Key
>
const
Type
&
operator
()(
const
Key
&
)
const
{
return
_
;
}
const
Type
&
_
;
};
template
<
typename
Type
>
copy_initializer
<
Type
>
make_copy_initializer
(
const
Type
&
value
)
{
return
copy_initializer
<
Type
>
(
value
);
}
template
<
typename
Type
>
struct
value_initializer
{
value_initializer
(
const
Type
&
value
)
:
_
(
value
)
{
}
template
<
typename
Key
>
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
{
const
Key
&
operator
()(
const
Key
&
_
)
const
{
return
_
;
}
};
template
<
class
Container
,
class
Generator
>
struct
lazy_property_map
{
typedef
lazy_property_map
<
Container
,
Generator
>
self
;
typedef
typename
Container
::
key_type
key_type
;
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
);
if
(
_m
.
end
()
==
found
)
{
found
=
_m
.
insert
(
std
::
make_pair
(
k
,
_g
(
k
))).
first
;
}
return
found
->
second
;
}
void
set
(
const
key_type
&
k
,
const
value_type
&
v
)
{
_m
[
k
]
=
v
;
}
friend
reference
get
(
const
self
&
s
,
const
key_type
&
k
)
{
return
s
[
k
];
}
friend
void
put
(
self
&
s
,
const
key_type
&
k
,
const
value_type
&
v
)
{
s
.
set
(
k
,
v
);
}
Container
&
_m
;
Generator
_g
;
};
template
<
class
Container
,
class
Generator
>
lazy_property_map
<
Container
,
Generator
>
make_lazy_property_map
(
Container
&
c
,
Generator
g
)
{
return
lazy_property_map
<
Container
,
Generator
>
(
c
,
g
);
}
}
#endif
storage/oqgraph/graphcore-types.h
View file @
b965d031
...
...
@@ -26,6 +26,7 @@
#ifndef oq_graphcore_types_h_
#define oq_graphcore_types_h_
namespace
open_query
{
...
...
@@ -33,4 +34,9 @@ namespace open_query
typedef
double
EdgeWeight
;
}
class
Field
;
typedef
struct
st_table
TABLE
;
#endif
storage/oqgraph/graphcore.cc
View file @
b965d031
...
...
@@ -30,14 +30,13 @@
#include <boost/config.hpp>
#include "graphcore-graph.h"
#include <set>
#include <stack>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/graph_archetypes.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/iteration_macros.hpp>
...
...
@@ -46,6 +45,8 @@
#include "graphcore.h"
#include <boost/unordered_map.hpp>
using
namespace
open_query
;
using
namespace
boost
;
...
...
@@ -53,46 +54,6 @@ static const row empty_row = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
namespace
open_query
{
enum
vertex_id_t
{
vertex_id
};
struct
VertexInfo
{
inline
VertexInfo
()
{
}
inline
VertexInfo
(
VertexID
_id
)
:
id
(
_id
)
{
}
VertexID
id
;
};
struct
EdgeInfo
{
EdgeWeight
weight
;
};
}
namespace
boost
{
BOOST_INSTALL_PROPERTY
(
vertex
,
id
);
namespace
graph
{
template
<
>
struct
internal_vertex_name
<
VertexInfo
>
{
typedef
multi_index
::
member
<
VertexInfo
,
VertexID
,
&
VertexInfo
::
id
>
type
;
};
template
<
>
struct
internal_vertex_constructor
<
VertexInfo
>
{
typedef
vertex_from_name
<
VertexInfo
>
type
;
};
}
}
namespace
open_query
{
#include "graphcore-graph.h"
typedef
graph_traits
<
Graph
>::
vertex_descriptor
Vertex
;
typedef
graph_traits
<
Graph
>::
edge_descriptor
Edge
;
...
...
@@ -261,18 +222,15 @@ namespace open_query {
public:
Graph
g
;
weightmap_type
weightmap
;
idmap_type
idmap
;
indexmap_type
indexmap
;
optional
<
Vertex
>
find_vertex
(
VertexID
id
)
const
;
optional
<
Edge
>
find_edge
(
Vertex
,
Vertex
)
const
;
inline
oqgraph_share
()
throw
()
:
g
(),
weightmap
(
GRAPH_WEIGHTMAP
(
g
)),
idmap
(
GRAPH_IDMAP
(
g
)),
indexmap
(
GRAPH_INDEXMAP
(
g
))
inline
oqgraph_share
(
TABLE
*
table
,
Field
*
origid
,
Field
*
destid
,
Field
*
weight
)
throw
()
:
g
(
table
,
origid
,
destid
,
weight
)
{
}
inline
~
oqgraph_share
()
{
}
...
...
@@ -360,13 +318,13 @@ namespace open_query {
}
};
template
<
typename
P
,
typename
D
>
struct
GRAPHCORE_INTERNAL
oqgraph_visit_dist
:
public
base_visitor
<
oqgraph_visit_dist
>
:
public
base_visitor
<
oqgraph_visit_dist
<
P
,
D
>
>
{
typedef
on_finish_vertex
event_filter
;
oqgraph_visit_dist
(
std
::
vector
<
Vertex
>::
iterator
p
,
std
::
vector
<
EdgeWeight
>::
iterator
d
,
oqgraph_visit_dist
(
const
P
&
p
,
const
D
&
d
,
stack_cursor
*
cursor
)
:
seq
(
0
),
m_cursor
(
*
cursor
),
m_p
(
p
),
m_d
(
d
)
{
assert
(
cursor
);
}
...
...
@@ -374,22 +332,28 @@ namespace open_query {
template
<
class
T
,
class
Graph
>
void
operator
()(
T
u
,
Graph
&
g
)
{
m_cursor
.
results
.
push
(
reference
(
++
seq
,
u
,
m_d
[
GRAPH_INDEXMAP
(
g
)[
u
]
]));
m_cursor
.
results
.
push
(
reference
(
++
seq
,
u
,
m_d
[
u
]));
}
private:
int
seq
;
stack_cursor
&
m_cursor
;
std
::
vector
<
Vertex
>::
iterator
m_p
;
std
::
vector
<
EdgeWeight
>::
iterator
m_d
;
P
m_p
;
D
m_d
;
};
template
<
bool
record_weight
,
typename
goal_filter
>
template
<
typename
P
,
typename
D
>
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
:
public
base_visitor
<
oqgraph_goal
<
record_weight
,
goal_filter
>
>
:
public
base_visitor
<
oqgraph_goal
<
record_weight
,
goal_filter
,
P
>
>
{
typedef
goal_filter
event_filter
;
oqgraph_goal
(
Vertex
goal
,
std
::
vector
<
Vertex
>::
iterator
p
,
oqgraph_goal
(
const
Vertex
&
goal
,
const
P
&
p
,
stack_cursor
*
cursor
)
:
m_goal
(
goal
),
m_cursor
(
*
cursor
),
m_p
(
p
)
{
assert
(
cursor
);
}
...
...
@@ -400,17 +364,16 @@ namespace open_query {
if
(
u
==
m_goal
)
{
int
seq
=
0
;
indexmap_type
indexmap
=
GRAPH_INDEXMAP
(
g
);
for
(
Vertex
q
,
v
=
u
;;
v
=
q
,
seq
++
)
if
((
q
=
m_p
[
indexmap
[
v
]
])
==
v
)
if
((
q
=
m_p
[
v
])
==
v
)
break
;
for
(
Vertex
v
=
u
;;
u
=
v
)
{
optional
<
Edge
>
edge
;
optional
<
EdgeWeight
>
weight
;
v
=
m_p
[
indexmap
[
u
]
];
v
=
m_p
[
u
];
if
(
record_weight
&&
u
!=
v
)
{
typename
graph_traits
<
Graph
>::
out_edge_iterator
ei
,
ei_end
;
...
...
@@ -419,7 +382,7 @@ namespace open_query {
if
(
target
(
*
ei
,
g
)
==
u
)
{
edge
=
*
ei
;
weight
=
GRAPH_WEIGHTMAP
(
g
)[
*
ei
]
;
weight
=
get
(
boost
::
edge_weight
,
g
,
*
ei
)
;
break
;
}
}
...
...
@@ -437,8 +400,14 @@ namespace open_query {
private:
Vertex
m_goal
;
stack_cursor
&
m_cursor
;
std
::
vector
<
Vertex
>::
iterator
m_p
;
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
)
{
return
oqgraph_goal
<
record_weight
,
goal_filter
,
P
>
(
goal
,
p
,
cursor
);
}
}
namespace
open_query
...
...
@@ -468,9 +437,14 @@ namespace open_query
return
new
(
std
::
nothrow
)
oqgraph
(
share
);
}
oqgraph_share
*
oqgraph
::
create
()
throw
()
oqgraph_share
*
oqgraph
::
create
(
TABLE
*
table
,
Field
*
origid
,
Field
*
destid
,
Field
*
weight
)
throw
()
{
return
new
(
std
::
nothrow
)
oqgraph_share
();
return
new
(
std
::
nothrow
)
oqgraph_share
(
table
,
origid
,
destid
,
weight
);
}
optional
<
Edge
>
...
...
@@ -479,14 +453,14 @@ namespace open_query
if
(
in_degree
(
dest
,
g
)
>=
out_degree
(
orig
,
g
))
{
graph_traits
<
Graph
>::
out_edge_iterator
ei
,
ei_end
;
boost
::
tuples
::
tie
(
ei
,
ei_end
)
=
out_edges
(
orig
,
g
);
tie
(
ei
,
ei_end
)
=
out_edges
(
orig
,
g
);
if
((
ei
=
find_if
(
ei
,
ei_end
,
target_equals
(
dest
,
g
)))
!=
ei_end
)
return
*
ei
;
}
else
{
graph_traits
<
Graph
>::
in_edge_iterator
ei
,
ei_end
;
boost
::
tuples
::
tie
(
ei
,
ei_end
)
=
in_edges
(
dest
,
g
);
tie
(
ei
,
ei_end
)
=
in_edges
(
dest
,
g
);
if
((
ei
=
find_if
(
ei
,
ei_end
,
source_equals
(
orig
,
g
)))
!=
ei_end
)
return
*
ei
;
}
...
...
@@ -496,9 +470,10 @@ namespace open_query
optional
<
Vertex
>
oqgraph_share
::
find_vertex
(
VertexID
id
)
const
{
return
boost
::
graph
::
find_vertex
(
id
,
g
);
return
::
boost
::
find_vertex
(
id
,
g
);
}
#if 0
int oqgraph::delete_all() throw()
{
share->g.clear();
...
...
@@ -598,8 +573,9 @@ namespace open_query
optional<Vertex> orig= source(*edge, share->g),
dest= target(*edge, share->g);
bool
orig_neq
=
orig_id
?
share
->
idmap
[
*
orig
]
!=
*
orig_id
:
0
;
bool
dest_neq
=
dest_id
?
share
->
idmap
[
*
dest
]
!=
*
dest_id
:
0
;
bool orig_neq= orig_id ? get(boost::vertex_index, share->g, *orig) != *orig_id : 0;
bool dest_neq= dest_id ? get(boost::vertex_index, share->g, *dest) != *dest_id : 0;
if (orig_neq || dest_neq)
{
optional<Edge> new_edge;
...
...
@@ -675,7 +651,6 @@ namespace open_query
return OK;
}
int oqgraph::delete_edge(VertexID orig_id, VertexID dest_id) throw()
{
optional<Vertex> orig, dest;
...
...
@@ -694,6 +669,7 @@ namespace open_query
remove_vertex(*dest, share->g);
return OK;
}
#endif
int
oqgraph
::
search
(
int
*
latch
,
VertexID
*
orig_id
,
VertexID
*
dest_id
)
throw
()
...
...
@@ -731,7 +707,8 @@ namespace open_query
{
Vertex
v
=
target
(
*
ei
,
share
->
g
);
static_cast
<
stack_cursor
*>
(
cursor
)
->
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
share
->
weightmap
[
*
ei
]));
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
get
(
boost
::
edge_weight
,
share
->
g
,
*
ei
)));
}
}
/* fall through */
...
...
@@ -745,7 +722,8 @@ namespace open_query
{
Vertex
v
=
source
(
*
ei
,
share
->
g
);
static_cast
<
stack_cursor
*>
(
cursor
)
->
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
share
->
weightmap
[
*
ei
]));
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
get
(
boost
::
edge_weight
,
share
->
g
,
*
ei
)));
}
}
break
;
...
...
@@ -757,27 +735,29 @@ namespace open_query
case
DIJKSTRAS
|
HAVE_ORIG
|
HAVE_DEST
:
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
orig
&&
dest
)
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
));
std
::
vector
<
EdgeWeight
>
d
(
num_vertices
(
share
->
g
));
oqgraph_goal
<
true
,
on_finish_vertex
>
vis
(
*
dest
,
p
.
begin
(),
static_cast
<
stack_cursor
*>
(
cursor
));
p
[
share
->
indexmap
[
*
orig
]]
=
*
orig
;
boost
::
unordered_map
<
Vertex
,
Vertex
>
p
;
boost
::
unordered_map
<
Vertex
,
EdgeWeight
>
d
;
p
[
*
orig
]
=
*
orig
;
d
[
*
orig
]
=
EdgeWeight
();
try
{
dijkstra_shortest_paths
(
share
->
g
,
*
orig
,
weight_map
(
share
->
weightmap
).
distance_map
(
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
)
).
predecessor_map
(
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
)
).
visitor
(
make_dijkstra_visitor
(
vis
)
dijkstra_shortest_paths_no_init
(
share
->
g
,
*
orig
,
make_lazy_property_map
(
p
,
identity_initializer
<
Vertex
>
()),
make_lazy_property_map
(
d
,
value_initializer
<
EdgeWeight
>
(
(
std
::
numeric_limits
<
EdgeWeight
>::
max
)())),
get
(
edge_weight
,
share
->
g
),
get
(
vertex_index
,
share
->
g
),
std
::
less
<
EdgeWeight
>
(),
closed_plus
<
EdgeWeight
>
(),
EdgeWeight
(),
make_dijkstra_visitor
(
make_oqgraph_goal
<
true
,
on_finish_vertex
>
(
*
dest
,
boost
::
make_assoc_property_map
(
p
),
static_cast
<
stack_cursor
*>
(
cursor
)
)
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
}
catch
(...)
{
/* printf("found\n"); */
}
...
...
@@ -787,23 +767,25 @@ namespace open_query
case
BREADTH_FIRST
|
HAVE_ORIG
|
HAVE_DEST
:
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
orig
&&
dest
)
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
));
oqgraph_goal
<
false
,
on_discover_vertex
>
vis
(
*
dest
,
p
.
begin
(),
static_cast
<
stack_cursor
*>
(
cursor
));
p
[
share
->
indexmap
[
*
orig
]]
=
*
orig
;
boost
::
unordered_map
<
Vertex
,
Vertex
>
p
;
boost
::
queue
<
Vertex
>
Q
;
p
[
*
orig
]
=
*
orig
;
try
{
breadth_first_
search
(
share
->
g
,
*
orig
,
visitor
(
make_bfs_visitor
(
breadth_first_
visit
(
share
->
g
,
*
orig
,
Q
,
make_bfs_visitor
(
std
::
make_pair
(
record_predecessors
(
make_iterator_property_map
(
p
.
begin
(),
share
->
indexma
p
),
boost
::
make_assoc_property_map
(
p
),
on_tree_edge
()
),
vis
)
make_oqgraph_goal
<
false
,
on_discover_vertex
>
(
*
dest
,
boost
::
make_assoc_property_map
(
p
),
static_cast
<
stack_cursor
*>
(
cursor
)
)
)
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
}
catch
(...)
{
/* printf("found\n"); */
}
...
...
@@ -814,109 +796,121 @@ namespace open_query
case
BREADTH_FIRST
|
HAVE_ORIG
:
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
(
orig
||
dest
))
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
))
;
std
::
vector
<
EdgeWeight
>
d
(
num_vertices
(
share
->
g
))
;
oqgraph_visit_dist
vis
(
p
.
begin
(),
d
.
begin
(),
static_cast
<
stack_cursor
*>
(
cursor
))
;
p
[
share
->
indexmap
[
*
orig
]]
=
*
orig
;
boost
::
unordered_map
<
Vertex
,
Vertex
>
p
;
boost
::
unordered_map
<
Vertex
,
EdgeWeight
>
d
;
boost
::
queue
<
Vertex
>
Q
;
p
[
*
orig
]
=
*
orig
;
d
[
*
orig
]
=
EdgeWeight
()
;
switch
(
ALGORITHM
&
op
)
{
case
DIJKSTRAS
:
dijkstra_shortest_paths
(
share
->
g
,
*
orig
,
weight_map
(
share
->
weightmap
).
distance_map
(
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
)
).
predecessor_map
(
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
)
).
visitor
(
make_dijkstra_visitor
(
vis
)
dijkstra_shortest_paths_no_init
(
share
->
g
,
*
orig
,
make_lazy_property_map
(
p
,
identity_initializer
<
Vertex
>
()),
make_lazy_property_map
(
d
,
value_initializer
<
EdgeWeight
>
(
(
std
::
numeric_limits
<
EdgeWeight
>::
max
)())),
get
(
edge_weight
,
share
->
g
),
get
(
vertex_index
,
share
->
g
),
std
::
less
<
EdgeWeight
>
(),
closed_plus
<
EdgeWeight
>
(),
EdgeWeight
(),
make_dijkstra_visitor
(
make_oqgraph_visit_dist
(
boost
::
make_assoc_property_map
(
p
),
d
,
static_cast
<
stack_cursor
*>
(
cursor
)
)
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
break
;
case
BREADTH_FIRST
:
breadth_first_
search
(
share
->
g
,
*
orig
,
visitor
(
make_bfs_visitor
(
breadth_first_
visit
(
share
->
g
,
*
orig
,
Q
,
make_bfs_visitor
(
std
::
make_pair
(
record_predecessors
(
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
),
boost
::
make_assoc_property_map
(
p
),
on_tree_edge
()
),
std
::
make_pair
(
record_distances
(
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
),
boost
::
make_assoc_property_map
(
d
),
on_tree_edge
()
),
vis
))
make_oqgraph_visit_dist
(
boost
::
make_assoc_property_map
(
p
),
boost
::
make_assoc_property_map
(
d
),
static_cast
<
stack_cursor
*>
(
cursor
)
)
))
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
break
;
default:
abort
();
}
}
break
;
#if 0
case BREADTH_FIRST | HAVE_DEST:
case DIJKSTRAS | HAVE_DEST:
if ((cursor= new (std::nothrow) stack_cursor(share)) && (orig || dest))
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
));
std
::
vector
<
EdgeWeight
>
d
(
num_vertices
(
share
->
g
));
oqgraph_visit_dist
vis
(
p
.
begin
(),
d
.
begin
(),
static_cast
<
stack_cursor
*>
(
cursor
));
boost::unordered_map<Vertex, Vertex> p;
boost::unordered_map<Vertex, EdgeWeight> d;
boost::queue<Vertex> Q;
reverse_graph<Graph> r(share->g);
p
[
share
->
indexmap
[
*
dest
]]
=
*
dest
;
p[ *dest ]= *dest;
d[ *dest ] = EdgeWeight();
switch (ALGORITHM & op)
{
case DIJKSTRAS:
dijkstra_shortest_paths
(
r
.
m_g
,
*
dest
,
weight_map
(
share
->
weightmap
).
distance_map
(
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
)
).
predecessor_map
(
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
)
).
visitor
(
make_dijkstra_visitor
(
vis
)
dijkstra_shortest_paths_no_init(share->g, *dest,
make_lazy_property_map(p, identity_initializer<Vertex>()),
make_lazy_property_map(d, value_initializer<EdgeWeight>(
(std::numeric_limits<EdgeWeight>::max)())),
get(edge_weight, share->g),
get(vertex_index, share->g),
std::less<EdgeWeight>(),
closed_plus<EdgeWeight>(),
EdgeWeight(),
make_dijkstra_visitor(
make_dijkstra_visitor(
make_oqgraph_visit_dist(
boost::make_assoc_property_map(p),
boost::make_assoc_property_map(d),
static_cast<stack_cursor*>(cursor)
)
)
);
),
make_two_bit_judy_map(get(vertex_index, share->g)));
break;
case BREADTH_FIRST:
breadth_first_
search
(
r
,
*
dest
,
visitor
(
make_bfs_visitor
(
breadth_first_
visit(share->g, *dest, Q
,
make_bfs_visitor(
std::make_pair(
record_predecessors(
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
),
boost::make_assoc_property_map(p),
on_tree_edge()
),
std::make_pair(
record_distances(
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
),
boost::make_assoc_property_map(d),
on_tree_edge()
),
vis
))
make_oqgraph_visit_dist(
boost::make_assoc_property_map(p),
boost::make_assoc_property_map(d),
static_cast<stack_cursor*>(cursor)
)
))
);
),
make_two_bit_judy_map(get(vertex_index, share->g)));
break;
default:
abort();
}
}
break;
#endif
default:
break
;
}
...
...
@@ -1006,7 +1000,7 @@ int stack_cursor::fetch_row(const row &row_info, row &result,
if
((
result
.
seq_indicator
=
seq
=
last
.
sequence
()))
result
.
seq
=
*
seq
;
if
((
result
.
link_indicator
=
v
=
last
.
vertex
()))
result
.
link
=
share
->
idmap
[
*
v
]
;
result
.
link
=
get
(
boost
::
vertex_index
,
share
->
g
,
*
v
)
;
if
((
result
.
weight_indicator
=
w
=
last
.
weight
()))
result
.
weight
=
*
w
;
return
oqgraph
::
OK
;
...
...
@@ -1040,7 +1034,7 @@ int vertices_cursor::fetch_row(const row &row_info, row &result,
if
(
v
)
{
result
.
link_indicator
=
1
;
result
.
link
=
share
->
idmap
[
*
v
]
;
result
.
link
=
get
(
boost
::
vertex_index
,
share
->
g
,
*
v
)
;
#ifdef DISPLAY_VERTEX_INFO
result
.
seq_indicator
=
1
;
if
((
result
.
seq
=
degree
(
*
v
,
share
->
g
)))
...
...
@@ -1048,10 +1042,10 @@ int vertices_cursor::fetch_row(const row &row_info, row &result,
EdgeWeight
weight
=
0
;
graph_traits
<
Graph
>::
in_edge_iterator
iei
,
iei_end
;
for
(
tie
(
iei
,
iei_end
)
=
in_edges
(
*
v
,
share
->
g
);
iei
!=
iei_end
;
++
iei
)
weight
+=
share
->
weightmap
[
*
iei
]
;
weight
+=
get
(
boost
::
edge_weight
,
share
->
g
,
*
iei
)
;
graph_traits
<
Graph
>::
out_edge_iterator
oei
,
oei_end
;
for
(
tie
(
oei
,
oei_end
)
=
out_edges
(
*
v
,
share
->
g
);
oei
!=
oei_end
;
++
oei
)
weight
+=
share
->
weightmap
[
*
oei
]
;
weight
+=
get
(
boost
::
edge_weight
,
share
->
g
,
*
oei
)
;
result
.
weight_indicator
=
1
;
result
.
weight
=
weight
/
result
.
seq
;
}
...
...
@@ -1066,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
(
boost
::
tuples
::
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
))
...
...
@@ -1085,9 +1078,9 @@ int edges_cursor::fetch_row(const row &row_info, row &result,
{
result
=
row_info
;
result
.
orig_indicator
=
result
.
dest_indicator
=
result
.
weight_indicator
=
1
;
result
.
orig
=
share
->
idmap
[
source
(
*
edge
,
share
->
g
)
]
;
result
.
dest
=
share
->
idmap
[
target
(
*
edge
,
share
->
g
)
]
;
result
.
weight
=
share
->
weightmap
[
*
edge
]
;
result
.
orig
=
get
(
boost
::
vertex_index
,
share
->
g
,
source
(
*
edge
,
share
->
g
)
)
;
result
.
dest
=
get
(
boost
::
vertex_index
,
share
->
g
,
target
(
*
edge
,
share
->
g
)
)
;
result
.
weight
=
get
(
boost
::
edge_weight
,
share
->
g
,
*
edge
)
;
return
oqgraph
::
OK
;
}
return
oqgraph
::
NO_MORE_DATA
;
...
...
storage/oqgraph/graphcore.h
View file @
b965d031
...
...
@@ -104,7 +104,7 @@ namespace open_query
void
row_ref
(
void
*
)
throw
();
static
oqgraph
*
create
(
oqgraph_share
*
)
throw
();
static
oqgraph_share
*
create
()
throw
();
static
oqgraph_share
*
create
(
TABLE
*
,
Field
*
,
Field
*
,
Field
*
)
throw
();
static
void
free
(
oqgraph
*
)
throw
();
static
void
free
(
oqgraph_share
*
)
throw
();
...
...
storage/oqgraph/ha_oqgraph.cc
View file @
b965d031
...
...
@@ -29,6 +29,8 @@
#endif
#ifdef HAVE_OQGRAPH
#include <stdarg.h>
#include <stdio.h>
#include <mysql_version.h>
#include "ha_oqgraph.h"
...
...
@@ -46,19 +48,27 @@
using
namespace
open_query
;
struct
oqgraph_
info_s
t
struct
oqgraph_
table_option_struc
t
{
THR_LOCK
lock
;
oqgraph_share
*
graph
;
uint
use_count
;
uint
key_stat_version
;
uint
records
;
bool
dropped
;
char
name
[
FN_REFLEN
+
1
];
char
*
table_name
;
char
*
origid
;
// name of the origin id column
char
*
destid
;
// name of the target id column
char
*
weight
;
// name of the weight column (optional)
};
#define ha_table_option_struct oqgraph_table_option_struct
ha_create_table_option
oqgraph_table_option_list
[]
=
{
HA_TOPTION_STRING
(
"data_table"
,
table_name
),
HA_TOPTION_STRING
(
"origid"
,
origid
),
HA_TOPTION_STRING
(
"destid"
,
destid
),
HA_TOPTION_STRING
(
"weight"
,
weight
),
HA_TOPTION_END
};
static
const
char
oqgraph_description
[]
=
"Open Query Graph Computation Engine
, stored in memory
"
"Open Query Graph Computation Engine "
"(http://openquery.com/graph)"
;
#if MYSQL_VERSION_ID < 50100
...
...
@@ -96,27 +106,10 @@ statistic_increment(table->in_use->status_var.X, &LOCK_status)
#define STATISTIC_INCREMENT(X)
/* nothing */
#define MOVE(X) move_field_offset(X)
#define RECORDS stats.records
#endif
static
HASH
oqgraph_open_tables
;
static
pthread_mutex_t
LOCK_oqgraph
;
static
bool
oqgraph_init_done
=
0
;
#if MYSQL_VERSION_ID >= 50130
#define HASH_KEY_LENGTH size_t
#else
#define HASH_KEY_LENGTH uint
#endif
static
uchar
*
get_key
(
const
uchar
*
ptr
,
HASH_KEY_LENGTH
*
length
,
my_bool
)
{
const
OQGRAPH_INFO
*
share
=
(
const
OQGRAPH_INFO
*
)
ptr
;
*
length
=
strlen
(
share
->
name
);
return
(
uchar
*
)
share
->
name
;
}
#if MYSQL_VERSION_ID >= 50100
static
handler
*
oqgraph_create_handler
(
handlerton
*
hton
,
TABLE_SHARE
*
table
,
MEM_ROOT
*
mem_root
)
{
...
...
@@ -130,7 +123,6 @@ static bool oqgraph_init()
{
if
(
have_oqgraph
==
SHOW_OPTION_DISABLED
)
return
1
;
#endif
if
(
pthread_mutex_init
(
&
LOCK_oqgraph
,
MY_MUTEX_INIT_FAST
))
goto
error
;
if
(
my_hash_init
(
&
oqgraph_open_tables
,
&
my_charset_bin
,
32
,
0
,
0
,
...
...
@@ -144,17 +136,11 @@ static bool oqgraph_init()
hton
->
db_type
=
DB_TYPE_AUTOASSIGN
;
hton
->
create
=
oqgraph_create_handler
;
hton
->
flags
=
HTON_NO_FLAGS
;
#endif
hton
->
table_options
=
oqgraph_table_option_list
;
oqgraph_init_done
=
TRUE
;
return
0
;
error:
#if MYSQL_VERSION_ID < 50100
have_oqgraph
=
SHOW_OPTION_DISABLED
;
#endif
return
1
;
}
#if MYSQL_VERSION_ID >= 50100
static
int
oqgraph_fini
(
void
*
)
{
my_hash_free
(
&
oqgraph_open_tables
);
...
...
@@ -264,6 +250,9 @@ static int error_code(int res)
KEY (latch, origid, destid) USING HASH,
KEY (latch, destid, origid) USING HASH
) ENGINE=OQGRAPH
READ_TABLE=bar
ORIGID=src_id
DESTID=tgt_id
*/
static
int
oqgraph_check_table_structure
(
TABLE
*
table_arg
)
...
...
@@ -331,16 +320,15 @@ static int oqgraph_check_table_structure (TABLE *table_arg)
** OQGRAPH tables
*****************************************************************************/
#if MYSQL_VERSION_ID >= 50100
ha_oqgraph
::
ha_oqgraph
(
handlerton
*
hton
,
TABLE_SHARE
*
table_arg
)
:
handler
(
hton
,
table_arg
),
#else
ha_oqgraph
::
ha_oqgraph
(
TABLE
*
table_arg
)
:
handler
(
&
oqgraph_hton
,
table_arg
),
#endif
share
(
0
),
graph
(
0
),
records_changed
(
0
),
key_stat_version
(
0
)
:
handler
(
hton
,
table_arg
)
,
graph_share
(
0
)
,
graph
(
0
)
,
error_message
(
""
,
0
,
&
my_charset_latin1
)
{
}
ha_oqgraph
::~
ha_oqgraph
()
{
}
static
const
char
*
ha_oqgraph_exts
[]
=
{
...
...
@@ -352,11 +340,7 @@ const char **ha_oqgraph::bas_ext() const
return
ha_oqgraph_exts
;
}
#if MYSQL_VERSION_ID >= 50100
ulonglong
ha_oqgraph
::
table_flags
()
const
#else
ulong
ha_oqgraph
::
table_flags
()
const
#endif
{
return
(
HA_NO_BLOBS
|
HA_NULL_IN_KEY
|
HA_REC_NOT_IN_SEQ
|
HA_CAN_INSERT_DELAYED
|
...
...
@@ -368,278 +352,251 @@ ulong ha_oqgraph::index_flags(uint inx, uint part, bool all_parts) const
return
HA_ONLY_WHOLE_INDEX
|
HA_KEY_SCAN_NOT_ROR
;
}
int
ha_oqgraph
::
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
)
bool
ha_oqgraph
::
get_error_message
(
int
error
,
String
*
buf
)
{
pthread_mutex_lock
(
&
LOCK_oqgraph
);
if
((
share
=
get_share
(
name
,
table
)))
if
(
error
<
0
)
{
ref_length
=
oqgraph
::
sizeof_ref
;
buf
->
append
(
error_message
);
buf
->
c_ptr_safe
();
error_message
.
length
(
0
);
}
if
(
share
)
{
/* Initialize variables for the opened table */
thr_lock_data_init
(
&
share
->
lock
,
&
lock
,
NULL
);
graph
=
oqgraph
::
create
(
share
->
graph
);
/*
We cannot run update_key_stats() here because we do not have a
lock on the table. The 'records' count might just be changed
temporarily at this moment and we might get wrong statistics (Bug
#10178). Instead we request for update. This will be done in
ha_oqgraph::info(), which is always called before key statistics are
used.
*/
key_stat_version
=
share
->
key_stat_version
-
1
;
}
pthread_mutex_unlock
(
&
LOCK_oqgraph
);
return
(
share
?
0
:
1
);
return
false
;
}
int
ha_oqgraph
::
close
(
void
)
void
ha_oqgraph
::
print_error
(
const
char
*
fmt
,
...
)
{
pthread_mutex_lock
(
&
LOCK_oqgraph
);
oqgraph
::
free
(
graph
);
graph
=
0
;
int
res
=
free_share
(
share
);
pthread_mutex_unlock
(
&
LOCK_oqgraph
);
return
error_code
(
res
);
va_list
ap
;
va_start
(
ap
,
fmt
);
error_message
.
reserve
(
256
);
size_t
len
=
error_message
.
length
();
len
+=
vsnprintf
(
&
error_message
[
len
],
255
,
fmt
,
ap
);
error_message
.
length
(
len
);
va_end
(
ap
);
}
void
ha_oqgraph
::
update_key_stats
()
int
ha_oqgraph
::
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
)
{
for
(
uint
i
=
0
;
i
<
table
->
s
->
keys
;
i
++
)
{
KEY
*
key
=
table
->
key_info
+
i
;
if
(
!
key
->
rec_per_key
)
continue
;
if
(
key
->
algorithm
!=
HA_KEY_ALG_BTREE
)
{
if
(
key
->
flags
&
HA_NOSAME
)
key
->
rec_per_key
[
key
->
key_parts
-
1
]
=
1
;
else
{
unsigned
vertices
=
graph
->
vertices_count
();
unsigned
edges
=
graph
->
edges_count
();
uint
no_records
=
vertices
?
2
*
(
edges
+
vertices
)
/
vertices
:
2
;
if
(
no_records
<
2
)
no_records
=
2
;
key
->
rec_per_key
[
key
->
key_parts
-
1
]
=
no_records
;
}
}
}
records_changed
=
0
;
/* At the end of update_key_stats() we can proudly claim they are OK. */
key_stat_version
=
share
->
key_stat_version
;
}
THD
*
thd
=
current_thd
;
oqgraph_table_option_struct
*
options
=
reinterpret_cast
<
oqgraph_table_option_struct
*>
(
table
->
s
->
option_struct
);
error_message
.
length
(
0
);
int
ha_oqgraph
::
write_row
(
byte
*
buf
)
{
int
res
=
oqgraph
::
MISC_FAIL
;
Field
**
const
field
=
table
->
field
;
STATISTIC_INCREMENT
(
ha_write_count
);
const
char
*
p
=
strend
(
name
)
-
1
;
while
(
p
>
name
&&
*
p
!=
'\\'
&&
*
p
!=
'/'
)
--
p
;
#if MYSQL_VERSION_ID >= 50100
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
#endif
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
init_tmp_table_share
(
thd
,
share
,
table
->
s
->
db
.
str
,
table
->
s
->
db
.
length
,
options
->
table_name
,
""
);
if
(
ptrdiff
)
size_t
tlen
=
strlen
(
options
->
table_name
);
size_t
plen
=
(
int
)(
p
-
name
)
+
tlen
;
share
->
path
.
str
=
(
char
*
)
alloc_root
(
&
share
->
mem_root
,
plen
+
1
);
strmov
(
strnmov
(
share
->
path
.
str
,
name
,
(
int
)(
p
-
name
)
+
1
),
options
->
table_name
);
share
->
normalized_path
.
str
=
share
->
path
.
str
;
share
->
path
.
length
=
share
->
normalized_path
.
length
=
plen
;
origid
=
destid
=
weight
=
0
;
while
(
open_table_def
(
thd
,
share
,
0
))
{
field
[
1
]
->
MOVE
(
ptrdiff
);
field
[
2
]
->
MOVE
(
ptrdiff
);
field
[
3
]
->
MOVE
(
ptrdiff
);
if
(
thd
->
is_error
()
&&
thd
->
main_da
.
sql_errno
()
!=
ER_NO_SUCH_TABLE
)
{
free_table_share
(
share
);
return
thd
->
main_da
.
sql_errno
();
}
if
(
!
field
[
1
]
->
is_null
()
&&
!
field
[
2
]
->
is_null
(
))
if
(
ha_create_table_from_engine
(
thd
,
table
->
s
->
db
.
str
,
options
->
table_name
))
{
VertexID
orig_id
=
(
VertexID
)
field
[
1
]
->
val_int
();
VertexID
dest_id
=
(
VertexID
)
field
[
2
]
->
val_int
();
EdgeWeight
weight
=
1
;
if
(
!
field
[
3
]
->
is_null
())
weight
=
(
EdgeWeight
)
field
[
3
]
->
val_real
();
free_table_share
(
share
);
return
thd
->
main_da
.
sql_errno
();
}
mysql_reset_errors
(
thd
,
1
);
thd
->
clear_error
();
continue
;
}
if
(
!
(
res
=
graph
->
insert_edge
(
orig_id
,
dest_id
,
weight
,
replace_dups
))
)
if
(
int
err
=
share
->
error
)
{
++
records_changed
;
share
->
records
++
;
}
if
(
res
==
oqgraph
::
DUPLICATE_EDGE
&&
ignore_dups
&&
!
insert_dups
)
res
=
oqgraph
::
OK
;
open_table_error
(
share
,
share
->
error
,
share
->
open_errno
,
share
->
errarg
);
free_table_share
(
share
);
return
err
;
}
if
(
ptrdiff
)
if
(
share
->
is_view
)
{
field
[
1
]
->
MOVE
(
-
ptrdiff
);
field
[
2
]
->
MOVE
(
-
ptrdiff
);
field
[
3
]
->
MOVE
(
-
ptrdiff
);
open_table_error
(
share
,
1
,
EMFILE
,
0
);
free_table_share
(
share
);
print_error
(
"VIEWs are not supported for a backing store"
);
return
-
1
;
}
#if MYSQL_VERSION_ID >= 50100
dbug_tmp_restore_column_map
(
table
->
read_set
,
old_map
);
#endif
if
(
!
res
&&
records_changed
*
OQGRAPH_STATS_UPDATE_THRESHOLD
>
share
->
records
)
if
(
int
err
=
open_table_from_share
(
thd
,
share
,
""
,
(
uint
)
(
HA_OPEN_KEYFILE
|
HA_OPEN_RNDFILE
|
HA_GET_INDEX
|
HA_TRY_READ_ONLY
),
READ_KEYINFO
|
COMPUTE_TYPES
|
EXTRA_RECORD
,
thd
->
open_options
,
edges
,
FALSE
))
{
/*
We can perform this safely since only one writer at the time is
allowed on the table.
*/
share
->
key_stat_version
++
;
open_table_error
(
share
,
err
,
EMFILE
,
0
);
free_table_share
(
share
);
return
-
1
;
}
return
error_code
(
res
);
}
edges
->
reginfo
.
lock_type
=
TL_READ
;
int
ha_oqgraph
::
update_row
(
const
byte
*
old
,
byte
*
buf
)
{
int
res
=
oqgraph
::
MISC_FAIL
;
VertexID
orig_id
,
dest_id
;
EdgeWeight
weight
=
1
;
Field
**
field
=
table
->
field
;
STATISTIC_INCREMENT
(
ha_update_count
);
edges
->
tablenr
=
thd
->
current_tablenr
++
;
edges
->
status
=
STATUS_NO_RECORD
;
edges
->
file
->
ha_start_of_new_statement
();
edges
->
file
->
ft_handler
=
0
;
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
);
#if MYSQL_VERSION_ID >= 50100
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
#endif
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
// We expect fields origid, destid and optionally weight
origid
=
destid
=
weight
=
0
;
if
(
ptrdiff
)
if
(
!
edges
->
file
)
{
field
[
0
]
->
MOVE
(
ptrdiff
);
field
[
1
]
->
MOVE
(
ptrdiff
);
field
[
2
]
->
MOVE
(
ptrdiff
);
field
[
3
]
->
MOVE
(
ptrdiff
);
print_error
(
"Some error occurred opening table '%s'"
,
options
->
table_name
);
free_table_share
(
share
);
return
-
1
;
}
if
(
inited
==
INDEX
||
inited
==
RND
)
for
(
Field
**
field
=
edges
->
field
;
*
field
;
++
field
)
{
VertexID
*
origp
=
0
,
*
destp
=
0
;
EdgeWeight
*
weightp
=
0
;
if
(
!
field
[
1
]
->
is_null
())
*
(
origp
=
&
orig_id
)
=
(
VertexID
)
field
[
1
]
->
val_int
();
if
(
!
field
[
2
]
->
is_null
())
*
(
destp
=
&
dest_id
)
=
(
VertexID
)
field
[
2
]
->
val_int
();
if
(
!
field
[
3
]
->
is_null
())
*
(
weightp
=
&
weight
)
=
(
EdgeWeight
)
field
[
3
]
->
val_real
();
my_ptrdiff_t
ptrdiff2
=
old
-
buf
;
field
[
0
]
->
MOVE
(
ptrdiff2
);
field
[
1
]
->
MOVE
(
ptrdiff2
);
field
[
2
]
->
MOVE
(
ptrdiff2
);
field
[
3
]
->
MOVE
(
ptrdiff2
);
if
(
field
[
0
]
->
is_null
())
if
(
strcmp
(
options
->
origid
,
(
*
field
)
->
field_name
))
continue
;
if
((
*
field
)
->
cmp_type
()
!=
INT_RESULT
||
!
((
*
field
)
->
flags
&
NOT_NULL_FLAG
))
{
if
(
!
origp
==
field
[
1
]
->
is_null
()
&&
*
origp
==
(
VertexID
)
field
[
1
]
->
val_int
())
origp
=
0
;
if
(
!
destp
==
field
[
2
]
->
is_null
()
&&
*
destp
==
(
VertexID
)
field
[
2
]
->
val_int
())
origp
=
0
;
if
(
!
weightp
==
field
[
3
]
->
is_null
()
&&
*
weightp
==
(
VertexID
)
field
[
3
]
->
val_real
())
weightp
=
0
;
if
(
!
(
res
=
graph
->
modify_edge
(
oqgraph
::
current_row
(),
origp
,
destp
,
weightp
,
replace_dups
)))
++
records_changed
;
else
if
(
ignore_dups
&&
res
==
oqgraph
::
DUPLICATE_EDGE
)
res
=
oqgraph
::
OK
;
print_error
(
"Column '%s.%s' is not a not-null integer type"
,
options
->
table_name
,
options
->
origid
);
closefrm
(
edges
,
0
);
free_table_share
(
share
);
return
-
1
;
}
field
[
0
]
->
MOVE
(
-
ptrdiff2
);
field
[
1
]
->
MOVE
(
-
ptrdiff2
);
field
[
2
]
->
MOVE
(
-
ptrdiff2
);
field
[
3
]
->
MOVE
(
-
ptrdiff2
);
origid
=
*
field
;
break
;
}
if
(
ptrdiff
)
for
(
Field
**
field
=
edges
->
field
;
*
field
;
++
field
)
{
field
[
0
]
->
MOVE
(
-
ptrdiff
);
field
[
1
]
->
MOVE
(
-
ptrdiff
);
field
[
2
]
->
MOVE
(
-
ptrdiff
);
field
[
3
]
->
MOVE
(
-
ptrdiff
);
}
#if MYSQL_VERSION_ID >= 50100
dbug_tmp_restore_column_map
(
table
->
read_set
,
old_map
);
#endif
if
(
!
res
&&
records_changed
*
OQGRAPH_STATS_UPDATE_THRESHOLD
>
share
->
records
)
if
(
strcmp
(
options
->
destid
,
(
*
field
)
->
field_name
))
continue
;
if
((
*
field
)
->
type
()
!=
origid
->
type
()
||
!
((
*
field
)
->
flags
&
NOT_NULL_FLAG
))
{
/*
We can perform this safely since only one writer at the time is
allowed on the table.
*/
share
->
key_stat_version
++
;
print_error
(
"Column '%s.%s' is not a not-null integer type"
,
options
->
table_name
,
options
->
destid
);
closefrm
(
edges
,
0
);
free_table_share
(
share
);
return
-
1
;
}
destid
=
*
field
;
break
;
}
return
error_code
(
res
);
}
int
ha_oqgraph
::
delete_row
(
const
byte
*
buf
)
{
int
res
=
oqgraph
::
EDGE_NOT_FOUND
;
Field
**
field
=
table
->
field
;
STATISTIC_INCREMENT
(
ha_delete_count
);
if
(
inited
==
INDEX
||
inited
==
RND
)
for
(
Field
**
field
=
edges
->
field
;
options
->
weight
&&
*
field
;
++
field
)
{
if
((
res
=
graph
->
delete_edge
(
oqgraph
::
current_row
()))
==
oqgraph
::
OK
)
if
(
strcmp
(
options
->
weight
,
(
*
field
)
->
field_name
))
continue
;
if
((
*
field
)
->
result_type
()
!=
REAL_RESULT
||
!
((
*
field
)
->
flags
&
NOT_NULL_FLAG
))
{
++
records_changed
;
share
->
records
--
;
print_error
(
"Column '%s.%s' is not a not-null real type"
,
options
->
table_name
,
options
->
weight
);
closefrm
(
edges
,
0
);
free_table_share
(
share
);
return
-
1
;
}
weight
=
*
field
;
break
;
}
if
(
res
!=
oqgraph
::
OK
)
{
#if MYSQL_VERSION_ID >= 50100
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
#endif
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
if
(
ptrdiff
)
if
(
!
origid
||
!
destid
||
(
!
weight
&&
options
->
weight
)
)
{
field
[
0
]
->
MOVE
(
ptrdiff
);
field
[
1
]
->
MOVE
(
ptrdiff
);
field
[
2
]
->
MOVE
(
ptrdiff
);
print_error
(
"Data columns missing on table '%s'"
,
options
->
table_name
);
closefrm
(
edges
,
0
);
free_table_share
(
share
);
return
-
1
;
}
if
(
field
[
0
]
->
is_null
()
&&
!
field
[
1
]
->
is_null
()
&&
!
field
[
2
]
->
is_null
(
))
if
(
!
(
graph_share
=
oqgraph
::
create
(
edges
,
origid
,
destid
,
weight
)
))
{
VertexID
orig_id
=
(
VertexID
)
field
[
1
]
->
val_int
();
VertexID
dest_id
=
(
VertexID
)
field
[
2
]
->
val_int
();
print_error
(
"Unable to create graph instance."
);
closefrm
(
edges
,
0
);
free_table_share
(
share
);
return
-
1
;
}
ref_length
=
oqgraph
::
sizeof_ref
;
graph
=
oqgraph
::
create
(
graph_share
);
return
0
;
}
if
((
res
=
graph
->
delete_edge
(
orig_id
,
dest_id
))
==
oqgraph
::
OK
)
int
ha_oqgraph
::
close
(
void
)
{
oqgraph
::
free
(
graph
);
graph
=
0
;
oqgraph
::
free
(
graph_share
);
graph_share
=
0
;
if
(
share
)
{
++
records_changed
;
share
->
records
--
;
}
if
(
edges
->
file
)
closefrm
(
edges
,
0
)
;
free_table_share
(
share
);
}
return
0
;
}
if
(
ptrdiff
)
void
ha_oqgraph
::
update_key_stats
()
{
for
(
uint
i
=
0
;
i
<
table
->
s
->
keys
;
i
++
)
{
field
[
0
]
->
MOVE
(
-
ptrdiff
);
field
[
1
]
->
MOVE
(
-
ptrdiff
);
field
[
2
]
->
MOVE
(
-
ptrdiff
);
KEY
*
key
=
table
->
key_info
+
i
;
if
(
!
key
->
rec_per_key
)
continue
;
if
(
key
->
algorithm
!=
HA_KEY_ALG_BTREE
)
{
if
(
key
->
flags
&
HA_NOSAME
)
key
->
rec_per_key
[
key
->
key_parts
-
1
]
=
1
;
else
{
//unsigned vertices= graph->vertices_count();
//unsigned edges= graph->edges_count();
//uint no_records= vertices ? 2 * (edges + vertices) / vertices : 2;
//if (no_records < 2)
uint
no_records
=
2
;
key
->
rec_per_key
[
key
->
key_parts
-
1
]
=
no_records
;
}
#if MYSQL_VERSION_ID >= 50100
dbug_tmp_restore_column_map
(
table
->
read_set
,
old_map
);
#endif
}
if
(
!
res
&&
table
->
s
->
tmp_table
==
NO_TMP_TABLE
&&
records_changed
*
OQGRAPH_STATS_UPDATE_THRESHOLD
>
share
->
records
)
{
/*
We can perform this safely since only one writer at the time is
allowed on the table.
*/
share
->
key_stat_version
++
;
}
return
error_code
(
res
);
/* At the end of update_key_stats() we can proudly claim they are OK. */
//skey_stat_version= share->key_stat_version;
}
int
ha_oqgraph
::
write_row
(
byte
*
buf
)
{
return
ER_OPEN_AS_READONLY
;
}
int
ha_oqgraph
::
update_row
(
const
byte
*
old
,
byte
*
buf
)
{
return
ER_OPEN_AS_READONLY
;
}
int
ha_oqgraph
::
delete_row
(
const
byte
*
buf
)
{
return
ER_OPEN_AS_READONLY
;
}
int
ha_oqgraph
::
index_read
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
,
...
...
@@ -677,9 +634,7 @@ int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
bmove_align
(
buf
,
table
->
s
->
default_values
,
table
->
s
->
reclength
);
key_restore
(
buf
,
(
byte
*
)
key
,
key_info
,
key_len
);
#if MYSQL_VERSION_ID >= 50100
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
#endif
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
if
(
ptrdiff
)
...
...
@@ -713,9 +668,7 @@ int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
field
[
1
]
->
MOVE
(
-
ptrdiff
);
field
[
2
]
->
MOVE
(
-
ptrdiff
);
}
#if MYSQL_VERSION_ID >= 50100
dbug_tmp_restore_column_map
(
table
->
read_set
,
old_map
);
#endif
res
=
graph
->
search
(
latchp
,
orig_idp
,
dest_idp
);
...
...
@@ -731,9 +684,7 @@ int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
bmove_align
(
record
,
table
->
s
->
default_values
,
table
->
s
->
reclength
);
#if MYSQL_VERSION_ID >= 50100
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
write_set
);
#endif
my_ptrdiff_t
ptrdiff
=
record
-
table
->
record
[
0
];
if
(
ptrdiff
)
...
...
@@ -792,15 +743,14 @@ int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
field
[
4
]
->
MOVE
(
-
ptrdiff
);
field
[
5
]
->
MOVE
(
-
ptrdiff
);
}
#if MYSQL_VERSION_ID >= 50100
dbug_tmp_restore_column_map
(
table
->
write_set
,
old_map
);
#endif
return
0
;
}
int
ha_oqgraph
::
rnd_init
(
bool
scan
)
{
edges
->
prepare_for_position
();
return
error_code
(
graph
->
random
(
scan
));
}
...
...
@@ -838,75 +788,31 @@ int ha_oqgraph::cmp_ref(const byte *ref1, const byte *ref2)
int
ha_oqgraph
::
info
(
uint
flag
)
{
RECORDS
=
graph
->
vertices_count
()
+
graph
->
edges_count
();
#if 0
records= hp_info.records;
deleted= hp_info.deleted;
errkey= hp_info.errkey;
mean_rec_length= hp_info.reclength;
data_file_length= hp_info.data_length;
index_file_length= hp_info.index_length;
max_data_file_length= hp_info.max_records* hp_info.reclength;
delete_length= hp_info.deleted * hp_info.reclength;
#endif
RECORDS
=
graph
->
edges_count
();
/*
If info() is called for the first time after open(), we will still
have to update the key statistics. Hoping that a table lock is now
in place.
*/
if
(
key_stat_version
!=
share
->
key_stat_version
)
update_key_stats
();
//
if (key_stat_version != share->key_stat_version)
//
update_key_stats();
return
0
;
}
int
ha_oqgraph
::
extra
(
enum
ha_extra_function
operation
)
{
switch
(
operation
)
{
case
HA_EXTRA_IGNORE_DUP_KEY
:
ignore_dups
=
true
;
break
;
case
HA_EXTRA_NO_IGNORE_DUP_KEY
:
ignore_dups
=
false
;
insert_dups
=
false
;
break
;
case
HA_EXTRA_WRITE_CAN_REPLACE
:
replace_dups
=
true
;
break
;
case
HA_EXTRA_WRITE_CANNOT_REPLACE
:
replace_dups
=
false
;
break
;
case
HA_EXTRA_INSERT_WITH_UPDATE
:
insert_dups
=
true
;
break
;
default:
break
;
}
return
0
;
return
edges
->
file
->
extra
(
operation
);
}
int
ha_oqgraph
::
delete_all_rows
()
{
int
res
;
if
(
!
(
res
=
graph
->
delete_all
()))
{
share
->
records
=
0
;
}
if
(
!
res
&&
table
->
s
->
tmp_table
==
NO_TMP_TABLE
)
{
/*
We can perform this safely since only one writer at the time is
allowed on the table.
*/
share
->
key_stat_version
++
;
}
return
error_code
(
res
);
return
ER_OPEN_AS_READONLY
;
}
int
ha_oqgraph
::
external_lock
(
THD
*
thd
,
int
lock_type
)
{
return
0
;
// No external locking
return
edges
->
file
->
ha_external_lock
(
thd
,
lock_type
);
}
...
...
@@ -914,10 +820,7 @@ THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
THR_LOCK_DATA
**
to
,
enum
thr_lock_type
lock_type
)
{
if
(
lock_type
!=
TL_IGNORE
&&
lock
.
type
==
TL_UNLOCK
)
lock
.
type
=
lock_type
;
*
to
++=
&
lock
;
return
to
;
return
edges
->
file
->
store_lock
(
thd
,
to
,
lock_type
);
}
/*
...
...
@@ -925,20 +828,12 @@ THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
not when doing a CREATE on the table.
*/
int
ha_oqgraph
::
delete_table
(
const
char
*
name
)
int
ha_oqgraph
::
delete_table
(
const
char
*
)
{
int
res
=
0
;
OQGRAPH_INFO
*
share
;
pthread_mutex_lock
(
&
LOCK_oqgraph
);
if
((
share
=
get_share
(
name
)))
{
res
=
free_share
(
share
,
true
);
}
pthread_mutex_unlock
(
&
LOCK_oqgraph
);
return
error_code
(
res
);
return
0
;
}
int
ha_oqgraph
::
rename_table
(
const
char
*
from
,
const
char
*
to
)
int
ha_oqgraph
::
rename_table
(
const
char
*
,
const
char
*
)
{
pthread_mutex_lock
(
&
LOCK_oqgraph
);
if
(
OQGRAPH_INFO
*
share
=
get_share
(
from
))
...
...
@@ -980,8 +875,9 @@ ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
return
RECORDS
;
/* Assert that info() did run. We need current statistics here. */
DBUG_ASSERT
(
key_stat_version
==
share
->
key_stat_version
);
ha_rows
result
=
key
->
rec_per_key
[
key
->
key_parts
-
1
];
//DBUG_ASSERT(key_stat_version == share->key_stat_version);
//ha_rows result= key->rec_per_key[key->key_parts-1];
ha_rows
result
=
10
;
return
result
;
}
...
...
@@ -990,24 +886,14 @@ ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
int
ha_oqgraph
::
create
(
const
char
*
name
,
TABLE
*
table_arg
,
HA_CREATE_INFO
*
create_info
)
{
int
res
=
-
1
;
OQGRAPH_INFO
*
share
;
oqgraph_table_option_struct
*
options
=
reinterpret_cast
<
oqgraph_table_option_struct
*>
(
table
->
s
->
option_struct
)
;
pthread_mutex_lock
(
&
LOCK_oqgraph
);
if
((
share
=
get_share
(
name
)))
{
free_share
(
share
);
}
else
{
if
(
!
oqgraph_check_table_structure
(
table_arg
))
res
=
0
;;
}
pthread_mutex_unlock
(
&
LOCK_oqgraph
);
if
(
this
->
share
)
info
(
HA_STATUS_NO_LOCK
|
HA_STATUS_CONST
|
HA_STATUS_VARIABLE
);
if
(
int
res
=
oqgraph_check_table_structure
(
table_arg
))
return
error_code
(
res
);
(
void
)(
options
);
return
0
;
}
...
...
@@ -1018,7 +904,6 @@ void ha_oqgraph::update_create_info(HA_CREATE_INFO *create_info)
// create_info->auto_increment_value= auto_increment_value;
}
#if MYSQL_VERSION_ID >= 50100
struct
st_mysql_storage_engine
oqgraph_storage_engine
=
{
MYSQL_HANDLERTON_INTERFACE_VERSION
};
...
...
@@ -1032,7 +917,7 @@ maria_declare_plugin(oqgraph)
PLUGIN_LICENSE_GPL
,
(
int
(
*
)(
void
*
))
oqgraph_init
,
/* Plugin Init */
oqgraph_fini
,
/* Plugin Deinit */
0x0
200
,
/* Version: 2
.0 */
0x0
300
,
/* Version: 3s
.0 */
NULL
,
/* status variables */
NULL
,
/* system variables */
"2.0"
,
...
...
storage/oqgraph/ha_oqgraph.h
View file @
b965d031
...
...
@@ -37,19 +37,21 @@ namespace open_query
{
struct
row
;
class
oqgraph
;
class
oqgraph_share
;
}
/* class for the the Open Query Graph handler */
class
ha_oqgraph
:
public
handler
{
OQGRAPH_INFO
*
share
;
TABLE_SHARE
share
[
1
];
TABLE
edges
[
1
];
Field
*
origid
;
Field
*
destid
;
Field
*
weight
;
open_query
::
oqgraph_share
*
graph_share
;
open_query
::
oqgraph
*
graph
;
THR_LOCK_DATA
lock
;
/* number of records changed since last statistics update */
uint
records_changed
;
uint
key_stat_version
;
bool
replace_dups
,
ignore_dups
,
insert_dups
;
int
fill_record
(
byte
*
,
const
open_query
::
row
&
);
...
...
@@ -61,7 +63,7 @@ class ha_oqgraph: public handler
ha_oqgraph
(
TABLE
*
table
);
Table_flags
table_flags
()
const
;
#endif
~
ha_oqgraph
()
{}
~
ha_oqgraph
()
;
const
char
*
table_type
()
const
{
return
"OQGRAPH"
;
...
...
@@ -107,6 +109,12 @@ 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
;
};
storage/oqgraph/oqgraph_judy.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 Arjen G Lentz & Antony T Curtis for Open Query
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* ======================================================================
Open Query Graph Computation Engine, based on a concept by Arjen Lentz
Mk.III implementation by Antony Curtis & Arjen Lentz
For more information, documentation, support, enhancement engineering,
and non-GPL licensing, see http://openquery.com/graph
or contact graph@openquery.com
For packaged binaries, see http://ourdelta.org
======================================================================
*/
#include "oqgraph_judy.h"
#include <Judy.h>
void
open_query
::
judy_bitset
::
clear
()
{
int
rc
;
J1FA
(
rc
,
array
);
}
bool
open_query
::
judy_bitset
::
test
(
size_type
n
)
const
{
int
rc
;
J1T
(
rc
,
array
,
n
);
return
rc
==
1
;
}
open_query
::
judy_bitset
&
open_query
::
judy_bitset
::
setbit
(
size_type
n
)
{
int
rc
;
J1S
(
rc
,
array
,
n
);
return
*
this
;
}
open_query
::
judy_bitset
&
open_query
::
judy_bitset
::
reset
(
size_type
n
)
{
int
rc
;
J1U
(
rc
,
array
,
n
);
return
*
this
;
}
open_query
::
judy_bitset
&
open_query
::
judy_bitset
::
flip
(
size_type
n
)
{
int
rc
;
J1U
(
rc
,
array
,
n
);
if
(
!
rc
)
{
J1S
(
rc
,
array
,
n
);
}
return
*
this
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
num_blocks
()
const
{
Word_t
rc
;
J1MU
(
rc
,
array
);
return
rc
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
size
()
const
{
int
rc
;
Word_t
index
=
(
Word_t
)
-
1
;
J1L
(
rc
,
array
,
index
);
if
(
!
rc
)
return
index
;
else
return
npos
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
count
()
const
{
Word_t
rc
;
J1C
(
rc
,
array
,
0
,
-
1
);
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
;
Word_t
index
=
0
;
J1F
(
rc
,
array
,
index
);
if
(
!
rc
)
return
index
;
else
return
npos
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
find_next
(
size_type
n
)
const
{
int
rc
;
Word_t
index
=
(
Word_t
)
n
;
J1N
(
rc
,
array
,
index
);
if
(
!
rc
)
return
index
;
else
return
npos
;
}
storage/oqgraph/oqgraph_judy.h
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 Arjen G Lentz & Antony T Curtis for Open Query
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* ======================================================================
Open Query Graph Computation Engine, based on a concept by Arjen Lentz
Mk.III implementation by Antony Curtis & Arjen Lentz
For more information, documentation, support, enhancement engineering,
and non-GPL licensing, see http://openquery.com/graph
or contact graph@openquery.com
For packaged binaries, see http://ourdelta.org
======================================================================
*/
#pragma once
#include <cstddef>
namespace
open_query
{
class
judy_bitset
{
public:
typedef
std
::
size_t
size_type
;
enum
{
npos
=
(
size_type
)
-
1
};
judy_bitset
()
:
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
();
}
inline
judy_bitset
&
set
(
size_type
n
,
bool
val
=
true
)
{
if
(
!
val
)
return
reset
(
n
);
else
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
;
size_type
count
()
const
;
size_type
size
()
const
;
size_type
num_blocks
()
const
;
class
reference
{
friend
class
judy_bitset
;
reference
(
judy_bitset
&
array
,
size_type
pos
)
:
j
(
array
)
,
n
(
pos
)
{
}
void
operator
&
();
// not defined
public:
reference
&
operator
=
(
bool
value
)
{
j
.
set
(
n
,
value
);
return
*
this
;
}
reference
&
operator
=
(
const
reference
&
ref
)
{
j
.
set
(
n
,
ref
);
return
*
this
;
}
reference
&
operator
|=
(
bool
value
)
{
if
(
value
)
j
.
set
(
n
);
return
*
this
;
}
reference
&
operator
&=
(
bool
value
)
{
if
(
!
value
)
j
.
reset
(
n
);
return
*
this
;
}
reference
&
operator
^=
(
bool
value
)
{
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
;
}
private:
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:
mutable
void
*
array
;
judy_bitset
&
setbit
(
size_type
n
);
};
}
storage/oqgraph/oqgraph_shim.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 Arjen G Lentz & Antony T Curtis for Open Query
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* ======================================================================
Open Query Graph Computation Engine, based on a concept by Arjen Lentz
Mk.III implementation by Antony Curtis & Arjen Lentz
For more information, documentation, support, enhancement engineering,
and non-GPL licensing, see http://openquery.com/graph
or contact graph@openquery.com
For packaged binaries, see http://ourdelta.org
======================================================================
*/
#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
;
}
storage/oqgraph/oqgraph_shim.h
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 Arjen G Lentz & Antony T Curtis for Open Query
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* ======================================================================
Open Query Graph Computation Engine, based on a concept by Arjen Lentz
Mk.III implementation by Antony Curtis & Arjen Lentz
For more information, documentation, support, enhancement engineering,
and non-GPL licensing, see http://openquery.com/graph
or contact graph@openquery.com
For packaged binaries, see http://ourdelta.org
======================================================================
*/
#pragma once
#include "oqgraph_thunk.h"
#include "oqgraph_judy.h"
#define BOOST_NO_HASH 1
#define BOOST_NO_SLIST 1
#include <boost/graph/directed_graph.hpp>
#include <boost/graph/adjacency_iterator.hpp>
namespace
open_query
{
struct
OQGraphTraversalCategory
:
public
boost
::
bidirectional_graph_tag
,
public
boost
::
adjacency_graph_tag
,
public
boost
::
edge_list_graph_tag
{
};
}
namespace
oqgraph3
{
struct
traversal_category
:
public
boost
::
adjacency_graph_tag
,
public
boost
::
bidirectional_graph_tag
,
public
boost
::
edge_list_graph_tag
{
};
struct
edge_iterator
{
typedef
edge_iterator
self
;
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
(
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_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
(
const
cursor_ptr
&
pos
)
:
_cursor
(
pos
.
operator
->
())
{
}
vertex_id
operator
*
()
const
{
edge_info
edge
(
*
_cursor
);
if
(
!
_seen
.
test
(
edge
.
origid
()))
return
edge
.
origid
();
else
return
edge
.
destid
();
}
self
&
operator
++
()
{
edge_info
edge
(
*
_cursor
);
if
(
!
_seen
.
test
(
edge
.
origid
()))
{
_seen
.
set
(
edge
.
origid
());
}
else
{
_seen
.
set
(
edge
.
destid
());
}
while
(
_seen
.
test
(
edge
.
origid
())
&&
_seen
.
test
(
edge
.
destid
()))
{
if
(
_cursor
->
seek_next
())
break
;
edge
=
_cursor
;
}
return
*
this
;
}
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
;
};
struct
out_edge_iterator
{
typedef
out_edge_iterator
self
;
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
(
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
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
(
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_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_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
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
;
};
}
namespace
boost
{
template
<
>
struct
graph_traits
<
oqgraph3
::
graph
>
{
typedef
oqgraph3
::
vertex_id
vertex_descriptor
;
typedef
oqgraph3
::
edge_info
edge_descriptor
;
typedef
boost
::
adjacency_iterator_generator
<
oqgraph3
::
graph
,
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
;
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
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
>
{
typedef
no_property
type
;
};
template
<
>
struct
vertex_property_type
<
oqgraph3
::
graph
>
{
typedef
no_property
type
;
};
template
<
>
struct
edge_property_type
<
oqgraph3
::
graph
>
{
typedef
no_property
type
;
};
#if BOOST_VERSION >= 104601
template
<
>
struct
graph_bundle_type
<
oqgraph3
::
graph
>
{
typedef
no_graph_bundle
type
;
};
template
<
>
struct
vertex_bundle_type
<
oqgraph3
::
graph
>
{
typedef
no_vertex_bundle
type
;
};
template
<
>
struct
edge_bundle_type
<
oqgraph3
::
graph
>
{
typedef
no_edge_bundle
type
;
};
#endif
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
&
g
)
{
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
(
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
&
g
)
{
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
(
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
)
{
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
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
),
start
),
graph_traits
<
oqgraph3
::
graph
>::
edge_iterator
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
),
end
));
}
inline
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
>
vertices
(
const
oqgraph3
::
graph
&
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
(
start
),
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
(
new
oqgraph3
::
cursor
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
))));
}
inline
graph_traits
<
oqgraph3
::
graph
>::
vertices_size_type
num_vertices
(
const
oqgraph3
::
graph
&
g
)
{
std
::
size_t
count
=
0
;
for
(
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
>
i
=
vertices
(
g
);
i
.
first
!=
i
.
second
;
++
i
.
first
)
{
++
count
;
}
return
count
;
}
template
<
>
struct
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>
{
typedef
void
type
;
typedef
oqgraph3
::
edge_weight_property_map
const_type
;
};
template
<
>
struct
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>
{
typedef
void
type
;
typedef
oqgraph3
::
vertex_index_property_map
const_type
;
};
template
<
>
struct
property_map
<
oqgraph3
::
graph
,
edge_index_t
>
{
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
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
::
key_type
&
key
)
{
return
key
.
weight
();
}
inline
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
get
(
edge_weight_t
,
const
oqgraph3
::
graph
&
g
)
{
return
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
(
g
);
}
inline
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
::
reference
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
key
.
weight
();
}
inline
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
::
reference
get
(
edge_index_t
,
const
oqgraph3
::
graph
&
,
const
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
::
key_type
&
key
)
{
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
(
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
.
_cursor
;
}
inline
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>::
const_type
::
reference
get
(
vertex_index_t
,
const
oqgraph3
::
graph
&
,
const
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>::
const_type
::
key_type
&
key
)
{
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
optional
<
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
>
find_vertex
(
oqgraph3
::
vertex_id
id
,
const
oqgraph3
::
graph
&
g
)
{
return
id
;
}
}
storage/oqgraph/oqgraph_thunk.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 Arjen G Lentz & Antony T Curtis for Open Query
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* ======================================================================
Open Query Graph Computation Engine, based on a concept by Arjen Lentz
Mk.III implementation by Antony Curtis & Arjen Lentz
For more information, documentation, support, enhancement engineering,
and non-GPL licensing, see http://openquery.com/graph
or contact graph@openquery.com
For packaged binaries, see http://ourdelta.org
======================================================================
*/
#include "oqgraph_thunk.h"
#include <boost/tuple/tuple.hpp>
#define MYSQL_SERVER
#include "mysql_priv.h"
static
int
debugid
=
0
;
oqgraph3
::
vertex_id
oqgraph3
::
edge_info
::
origid
()
const
{
return
_cursor
->
get_origid
();
}
oqgraph3
::
vertex_id
oqgraph3
::
edge_info
::
destid
()
const
{
return
_cursor
->
get_destid
();
}
oqgraph3
::
weight_t
oqgraph3
::
edge_info
::
weight
()
const
{
return
_cursor
->
get_weight
();
}
bool
oqgraph3
::
cursor_ptr
::
operator
==
(
const
cursor_ptr
&
x
)
const
{
if
(
get
()
==
x
.
get
())
return
true
;
return
(
*
this
)
->
record_position
()
==
x
->
_position
;
}
bool
oqgraph3
::
cursor_ptr
::
operator
!=
(
const
cursor_ptr
&
x
)
const
{
if
(
get
()
==
x
.
get
())
return
false
;
return
(
*
this
)
->
record_position
()
!=
x
->
_position
;
}
oqgraph3
::
cursor
::
cursor
(
const
graph_ptr
&
graph
)
:
_ref_count
(
0
)
,
_graph
(
graph
)
,
_index
(
-
1
)
,
_parts
(
0
)
,
_key
()
,
_position
()
,
_debugid
(
++
debugid
)
{
}
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
)
{
}
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
;
}
}
const
std
::
string
&
oqgraph3
::
cursor
::
record_position
()
const
{
if
(
_graph
->
_stale
&&
_graph
->
_cursor
)
{
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
)
{
key_copy
((
uchar
*
)
_graph
->
_cursor
->
_key
.
data
(),
table
.
record
[
0
],
table
.
s
->
key_info
+
_index
,
table
.
s
->
key_info
[
_index
].
key_length
,
true
);
}
_graph
->
_stale
=
false
;
}
return
_position
;
}
void
oqgraph3
::
cursor
::
clear_position
()
{
_position
.
clear
();
if
(
this
==
_graph
->
_cursor
)
{
_graph
->
_cursor
=
0
;
_graph
->
_stale
=
false
;
}
}
void
oqgraph3
::
cursor
::
save_position
()
{
record_position
();
if
(
this
==
_graph
->
_cursor
)
{
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
;
}
}
int
oqgraph3
::
cursor
::
restore_position
()
{
TABLE
&
table
=
*
_graph
->
_table
;
if
(
!
_position
.
size
())
return
ENOENT
;
if
(
this
==
_graph
->
_cursor
)
return
0
;
if
(
_graph
->
_cursor
)
_graph
->
_cursor
->
save_position
();
if
(
_origid
||
_destid
)
{
if
(
int
rc
=
table
.
file
->
ha_index_init
(
_index
,
1
))
return
rc
;
restore_record
(
&
table
,
s
->
default_values
);
if
(
_origid
)
{
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
);
}
if
(
_destid
)
{
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
);
}
if
(
int
rc
=
table
.
file
->
ha_index_init
(
_index
,
1
))
return
rc
;
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
;
}
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
(
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
]);
}
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
()))
{
table
.
file
->
ha_rnd_end
();
return
rc
;
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
}
_graph
->
_cursor
=
this
;
_graph
->
_stale
=
false
;
return
0
;
}
oqgraph3
::
vertex_id
oqgraph3
::
cursor
::
get_origid
()
{
if
(
_origid
)
return
*
_origid
;
if
(
this
!=
_graph
->
_cursor
)
{
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
;
if
(
this
!=
_graph
->
_cursor
)
{
if
(
restore_position
())
return
-
1
;
}
return
static_cast
<
vertex_id
>
(
_graph
->
_target
->
val_int
());
}
oqgraph3
::
weight_t
oqgraph3
::
cursor
::
get_weight
()
{
if
(
!
_graph
->
_weight
)
return
1.0
;
if
(
this
!=
_graph
->
_cursor
)
{
if
(
restore_position
())
return
-
1
;
}
return
static_cast
<
vertex_id
>
(
_graph
->
_weight
->
val_int
());
}
int
oqgraph3
::
cursor
::
seek_next
()
{
if
(
this
!=
_graph
->
_cursor
)
{
if
(
int
rc
=
restore_position
())
return
rc
;
}
TABLE
&
table
=
*
_graph
->
_table
;
if
(
_index
<
0
)
{
if
(
int
rc
=
table
.
file
->
ha_rnd_next
(
table
.
record
[
0
]))
{
table
.
file
->
ha_rnd_end
();
return
clear_position
(
rc
);
}
return
0
;
}
if
(
int
rc
=
table
.
file
->
ha_index_next
(
table
.
record
[
0
]))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
rc
);
}
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
0
;
}
int
oqgraph3
::
cursor
::
seek_prev
()
{
if
(
this
!=
_graph
->
_cursor
)
{
if
(
int
rc
=
restore_position
())
return
rc
;
}
TABLE
&
table
=
*
_graph
->
_table
;
if
(
_index
<
0
)
{
return
-
1
;
// not supported
}
if
(
int
rc
=
table
.
file
->
ha_index_prev
(
table
.
record
[
0
]))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
rc
);
}
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
0
;
}
int
oqgraph3
::
cursor
::
seek_to
(
boost
::
optional
<
vertex_id
>
origid
,
boost
::
optional
<
vertex_id
>
destid
)
{
if
(
_graph
->
_cursor
&&
this
!=
_graph
->
_cursor
)
_graph
->
_cursor
->
save_position
();
TABLE
&
table
=
*
_graph
->
_table
;
_index
=
-
1
;
_origid
=
origid
;
_destid
=
destid
;
if
(
origid
||
destid
)
{
Field
*
source
=
_graph
->
_source
;
Field
*
target
=
_graph
->
_target
;
uint
source_fieldpos
=
_graph
->
_source
->
offset
(
table
.
record
[
0
]);
uint
target_fieldpos
=
_graph
->
_target
->
offset
(
table
.
record
[
0
]);
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
;
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
);
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
;
}
}
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
;
if
(
table
.
file
->
ha_index_init
(
i
,
1
))
continue
;
restore_record
(
&
table
,
s
->
default_values
);
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
;
}
}
else
{
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
==
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
;
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
;
}
}
if
(
_index
<
0
)
{
// no suitable index found
return
clear_position
(
ENXIO
);
}
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
);
}
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
clear_position
(
ENOENT
);
}
}
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
);
}
}
_graph
->
_cursor
=
this
;
_graph
->
_stale
=
true
;
return
0
;
}
bool
oqgraph3
::
cursor
::
operator
==
(
const
cursor
&
x
)
const
{
return
record_position
()
==
x
.
_position
;
}
bool
oqgraph3
::
cursor
::
operator
!=
(
const
cursor
&
x
)
const
{
return
record_position
()
!=
x
.
_position
;
}
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
)
{
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
::
graph
::~
graph
()
{
}
oqgraph3
::
edges_size_type
oqgraph3
::
graph
::
num_edges
()
const
{
return
_table
->
file
->
stats
.
records
;
}
storage/oqgraph/oqgraph_thunk.h
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 Arjen G Lentz & Antony T Curtis for Open Query
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* ======================================================================
Open Query Graph Computation Engine, based on a concept by Arjen Lentz
Mk.III implementation by Antony Curtis & Arjen Lentz
For more information, documentation, support, enhancement engineering,
and non-GPL licensing, see http://openquery.com/graph
or contact graph@openquery.com
For packaged binaries, see http://ourdelta.org
======================================================================
*/
#pragma once
#include <list>
#include <queue>
#include <string>
#include <utility>
#include <boost/intrusive_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/pending/queue.hpp>
#include <boost/ptr_container/ptr_deque.hpp>
#include "graphcore-types.h"
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
cursor
;
typedef
boost
::
intrusive_ptr
<
graph
>
graph_ptr
;
struct
cursor_ptr
:
public
boost
::
intrusive_ptr
<
cursor
>
{
cursor_ptr
()
:
boost
::
intrusive_ptr
<
cursor
>
()
{
}
cursor_ptr
(
cursor
*
pos
)
:
boost
::
intrusive_ptr
<
cursor
>
(
pos
)
{
}
operator
const
std
::
string
&
()
const
;
bool
operator
==
(
const
cursor_ptr
&
)
const
;
bool
operator
!=
(
const
cursor_ptr
&
)
const
;
};
struct
edge_info
{
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
cursor
{
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
;
}
};
struct
graph
{
mutable
int
_ref_count
;
cursor
*
_cursor
;
bool
_stale
;
cursor_ptr
_rnd_cursor
;
size_t
_rnd_pos
;
::
TABLE
*
_table
;
::
Field
*
_source
;
::
Field
*
_target
;
::
Field
*
_weight
;
graph
(
::
TABLE
*
table
,
::
Field
*
source
,
::
Field
*
target
,
::
Field
*
weight
=
0
);
~
graph
();
edges_size_type
num_edges
()
const
;
friend
edges_size_type
num_edges
(
const
graph
&
g
)
{
return
g
.
num_edges
();
}
friend
void
intrusive_ptr_add_ref
(
graph
*
ptr
)
{
ptr
->
_ref_count
++
;
}
friend
void
intrusive_ptr_release
(
graph
*
ptr
)
{
ptr
->
_ref_count
--
;
}
};
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment