1
0
Fork 0

Merge branch 'devel' of github.com:arangodb/arangodb into devel

This commit is contained in:
hkernbach 2016-06-16 09:56:59 +02:00
commit b6f3d506d9
8 changed files with 80 additions and 165 deletions

View File

@ -25,14 +25,6 @@
using namespace arangodb::traverser;
void SingleServerTraversalPath::getDocumentByIdentifier(arangodb::Transaction* trx,
std::string const& identifier,
VPackBuilder& result) {
std::shared_ptr<VPackBuffer<uint8_t>> vertex =
_traverser->fetchVertexData(_path.vertices.back());
result.add(VPackSlice(vertex->data()));
}
void SingleServerTraversalPath::pathToVelocyPack(arangodb::Transaction* trx,
VPackBuilder& result) {
result.openObject();

View File

@ -32,7 +32,7 @@ namespace traverser {
class SingleServerTraversalPath : public TraversalPath {
public:
explicit SingleServerTraversalPath(
SingleServerTraversalPath(
arangodb::basics::EnumeratedPath<std::string, std::string> const& path,
SingleServerTraverser* traverser)
: _traverser(traverser), _path(path) {}
@ -50,15 +50,9 @@ class SingleServerTraversalPath : public TraversalPath {
private:
void getDocumentByIdentifier(Transaction*, std::string const&,
arangodb::velocypack::Builder&);
SingleServerTraverser* _traverser;
arangodb::basics::EnumeratedPath<std::string, std::string> _path;
arangodb::velocypack::Builder _searchBuilder;
};
} // namespace traverser

View File

@ -23,9 +23,11 @@
#include "SingleServerTraverser.h"
#include "Utils/OperationCursor.h"
#include "Utils/Transaction.h"
#include "VocBase/MasterPointer.h"
#include "VocBase/SingleServerTraversalPath.h"
using namespace arangodb;
using namespace arangodb::traverser;
////////////////////////////////////////////////////////////////////////////////
@ -37,7 +39,6 @@ using namespace arangodb::traverser;
static int FetchDocumentById(arangodb::Transaction* trx,
std::string const& id,
VPackBuilder& builder,
VPackBuilder& result) {
size_t pos = id.find('/');
if (pos == std::string::npos) {
@ -49,12 +50,10 @@ static int FetchDocumentById(arangodb::Transaction* trx,
return TRI_ERROR_INTERNAL;
}
std::string col = id.substr(0, pos);
trx->addCollectionAtRuntime(col);
builder.clear();
builder.add(VPackValue(id.substr(pos + 1)));
TransactionBuilderLeaser builder(trx);
builder->add(VPackValue(id.substr(pos + 1)));
int res = trx->documentFastPath(col, builder.slice(), result);
int res = trx->documentFastPath(id.substr(0, pos), builder->slice(), result);
if (res != TRI_ERROR_NO_ERROR && res != TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
THROW_ARANGO_EXCEPTION(res);
@ -125,7 +124,7 @@ std::shared_ptr<VPackBuffer<uint8_t>> SingleServerTraverser::fetchVertexData(
auto it = _vertices.find(id);
if (it == _vertices.end()) {
VPackBuilder tmp;
int res = FetchDocumentById(_trx, id, _builder, tmp);
int res = FetchDocumentById(_trx, id, tmp);
++_readDocuments;
if (res != TRI_ERROR_NO_ERROR) {
TRI_ASSERT(res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND);
@ -143,7 +142,7 @@ bool SingleServerTraverser::VertexGetter::getVertex(std::string const& edge,
std::string const& vertex,
size_t depth,
std::string& result) {
auto const& it = _traverser->_edges.find(edge);
auto it = _traverser->_edges.find(edge);
TRI_ASSERT(it != _traverser->_edges.end());
VPackSlice v(it->second->data());
// NOTE: We assume that we only have valid edges.
@ -165,7 +164,7 @@ void SingleServerTraverser::VertexGetter::reset(std::string const&) {
bool SingleServerTraverser::UniqueVertexGetter::getVertex(
std::string const& edge, std::string const& vertex, size_t depth,
std::string& result) {
auto const& it = _traverser->_edges.find(edge);
auto it = _traverser->_edges.find(edge);
TRI_ASSERT(it != _traverser->_edges.end());
VPackSlice v(it->second->data());
// NOTE: We assume that we only have valid edges.
@ -209,7 +208,7 @@ void SingleServerTraverser::setStartVertex(std::string const& v) {
if (fetchVertex) {
fetchVertex = false;
VPackBuilder tmp;
int result = FetchDocumentById(_trx, v, _builder, tmp);
int result = FetchDocumentById(_trx, v, tmp);
++_readDocuments;
if (result != TRI_ERROR_NO_ERROR) {
// Vertex does not exist
@ -290,11 +289,11 @@ TraversalPath* SingleServerTraverser::next() {
}
}
auto p = std::make_unique<SingleServerTraversalPath>(path, this);
if (countEdges < _opts.minDepth) {
return next();
}
return p.release();
return new SingleServerTraversalPath(path, this);
}
bool SingleServerTraverser::EdgeGetter::nextCursor(std::string const& startVertex,

View File

@ -80,8 +80,8 @@ class SingleServerTraverser : public Traverser {
arangodb::velocypack::ValueLength> {
public:
EdgeGetter(SingleServerTraverser* traverser,
TraverserOptions const& opts,
Transaction* trx)
TraverserOptions const& opts,
Transaction* trx)
: _traverser(traverser), _opts(opts), _trx(trx) {}
//////////////////////////////////////////////////////////////////////////////

View File

@ -33,30 +33,6 @@
using TraverserExpression = arangodb::traverser::TraverserExpression;
////////////////////////////////////////////////////////////////////////////////
/// @brief Helper to transform a vertex _id string to VertexId struct.
/// NOTE: Make sure the given string is not freed as long as the resulting
/// VertexId is in use
////////////////////////////////////////////////////////////////////////////////
arangodb::traverser::VertexId arangodb::traverser::IdStringToVertexId(
CollectionNameResolver const* resolver, std::string const& vertex) {
size_t split;
char const* str = vertex.c_str();
if (!TRI_ValidateDocumentIdKeyGenerator(str, vertex.size(), &split)) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
}
std::string const collectionName = vertex.substr(0, split);
auto cid = resolver->getCollectionIdCluster(collectionName);
if (cid == 0) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
return VertexId(cid, const_cast<char*>(str + split + 1));
}
/// @brief Class Shortest Path
@ -83,11 +59,12 @@ void arangodb::traverser::ShortestPath::vertexToVelocyPack(Transaction* trx, siz
std::string collection = v.copyString();
size_t p = collection.find("/");
TRI_ASSERT(p != std::string::npos);
_searchBuilder.clear();
_searchBuilder.add(VPackValue(collection.substr(p + 1)));
TransactionBuilderLeaser searchBuilder(trx);
searchBuilder->add(VPackValue(collection.substr(p + 1)));
collection = collection.substr(0, p);
int res = trx->documentFastPath(collection, _searchBuilder.slice(), builder);
int res = trx->documentFastPath(collection, searchBuilder->slice(), builder);
if (res != TRI_ERROR_NO_ERROR) {
builder.clear(); // Just in case...
builder.add(basics::VelocyPackHelper::NullValue());

View File

@ -41,43 +41,6 @@ class Slice;
}
namespace traverser {
////////////////////////////////////////////////////////////////////////////////
/// @brief Template for a vertex id. Is simply a pair of cid and key
/// NOTE: This struct will never free the value asigned to char const* key
/// The environment has to make sure that the string it points to is
/// not freed as long as this struct is in use!
////////////////////////////////////////////////////////////////////////////////
struct VertexId {
TRI_voc_cid_t cid;
char const* key;
VertexId() : cid(0), key("") {}
VertexId(TRI_voc_cid_t cid, char const* key) : cid(cid), key(key) {}
bool operator==(VertexId const& other) const {
if (cid == other.cid) {
return strcmp(key, other.key) == 0;
}
return false;
}
std::string toString(arangodb::CollectionNameResolver const* resolver) const {
return resolver->getCollectionNameCluster(cid) + "/" + std::string(key);
}
};
// EdgeId and VertexId are similar here. both have a key and a cid
typedef VertexId EdgeId;
////////////////////////////////////////////////////////////////////////////////
/// @brief Helper function to convert an _id string into a VertexId
////////////////////////////////////////////////////////////////////////////////
VertexId IdStringToVertexId(arangodb::CollectionNameResolver const* resolver,
std::string const& vertex);
class TraverserExpression {
public:
bool isEdgeAccess;
@ -171,9 +134,6 @@ class ShortestPath {
size_t length() { return _vertices.size(); };
private:
/// @brief Local builder to create a search value
arangodb::velocypack::Builder _searchBuilder;
/// @brief Count how many documents have been read
size_t _readDocuments;
@ -417,37 +377,4 @@ class Traverser {
} // traverser
} // arangodb
namespace std {
template <>
struct hash<arangodb::traverser::VertexId> {
public:
size_t operator()(arangodb::traverser::VertexId const& s) const {
size_t h1 = std::hash<TRI_voc_cid_t>()(s.cid);
size_t h2 = static_cast<size_t>(TRI_FnvHashString(s.key));
return h1 ^ (h2 << 1);
}
};
template <>
struct equal_to<arangodb::traverser::VertexId> {
public:
bool operator()(arangodb::traverser::VertexId const& s,
arangodb::traverser::VertexId const& t) const {
return s.cid == t.cid && strcmp(s.key, t.key) == 0;
}
};
template <>
struct less<arangodb::traverser::VertexId> {
public:
bool operator()(arangodb::traverser::VertexId const& lhs,
arangodb::traverser::VertexId const& rhs) {
if (lhs.cid != rhs.cid) {
return lhs.cid < rhs.cid;
}
return strcmp(lhs.key, rhs.key) < 0;
}
};
}
#endif

View File

@ -128,6 +128,12 @@ var registerCompatibilityFunctions = function() {
}, false);
};
var fixWeight = function (options) {
if (!options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("weight")) {
options.weightAttribute = options.weight;
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief transform a string into an array.
////////////////////////////////////////////////////////////////////////////////
@ -1490,14 +1496,15 @@ Graph.prototype._shortestPath = function(startVertexExample, endVertexExample, o
query += "ANY ";
}
query += `SHORTEST_PATH start TO target GRAPH @graphName `;
if (options.hasOwnProperty("weight") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weight: @attribute, defaultWeight: @default}
fixWeight(options);
if (options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weightAttribute: @attribute, defaultWeight: @default}
RETURN {
v: v,
e: e,
d: IS_NULL(e) ? 0 : (IS_NUMBER(e[@attribute]) ? e[@attribute] : @default)
}) `;
bindVars.attribute = options.weight;
bindVars.attribute = options.weightAttribute;
bindVars.default = options.defaultWeight;
} else {
query += "RETURN {v: v, e: e, d: IS_NULL(e) ? 0 : 1}) ";
@ -1534,10 +1541,11 @@ Graph.prototype._distanceTo = function(startVertexExample, endVertexExample, opt
query += "ANY ";
}
query += `SHORTEST_PATH start TO target GRAPH @graphName `;
if (options.hasOwnProperty("weight") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weight: @attribute, defaultWeight: @default}
fixWeight(options);
if (options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weightAttribute: @attribute, defaultWeight: @default}
FILTER e != null RETURN IS_NUMBER(e[@attribute]) ? e[@attribute] : @default) `;
bindVars.attribute = options.weight;
bindVars.attribute = options.weightAttribute;
bindVars.default = options.defaultWeight;
} else {
query += "FILTER e != null RETURN 1) ";
@ -1575,10 +1583,11 @@ Graph.prototype._absoluteEccentricity = function(vertexExample, options) {
query += "ANY ";
}
query += "SHORTEST_PATH start TO target GRAPH @graphName ";
if (options.hasOwnProperty("weight") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weight: @attribute, defaultWeight: @default}
fixWeight(options);
if (options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weightAttribute: @attribute, defaultWeight: @default}
FILTER e != null RETURN IS_NUMBER(e[@attribute]) ? e[@attribute] : @default) `;
bindVars.attribute = options.weight;
bindVars.attribute = options.weightAttribute;
bindVars.default = options.defaultWeight;
} else {
query += "FILTER e != null RETURN 1) ";
@ -1617,10 +1626,11 @@ Graph.prototype._farness = Graph.prototype._absoluteCloseness = function(vertexE
query += "ANY ";
}
query += "SHORTEST_PATH start TO target GRAPH @graphName ";
if (options.hasOwnProperty("weight") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weight: @attribute, defaultWeight: @default}
fixWeight(options);
if (options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weightAttribute: @attribute, defaultWeight: @default}
FILTER e != null RETURN IS_NUMBER(e[@attribute]) ? e[@attribute] : @default) `;
bindVars.attribute = options.weight;
bindVars.attribute = options.weightAttribute;
bindVars.default = options.defaultWeight;
} else {
query += "FILTER e != null RETURN 1) ";
@ -1704,9 +1714,10 @@ Graph.prototype._absoluteBetweenness = function(example, options) {
query += "ANY ";
}
query += "SHORTEST_PATH start TO target GRAPH @graphName ";
if (options.hasOwnProperty("weight") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weight: @attribute, defaultWeight: @default} `;
bindVars.attribute = options.weight;
fixWeight(options);
if (options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weightAttribute: @attribute, defaultWeight: @default} `;
bindVars.attribute = options.weightAttribute;
bindVars.default = options.defaultWeight;
}
query += `
@ -1784,10 +1795,11 @@ Graph.prototype._radius = function(options) {
query += "ANY ";
}
query += "SHORTEST_PATH s TO t GRAPH @graphName ";
if (options.hasOwnProperty("weight") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weight: @attribute, defaultWeight: @default}
fixWeight(options);
if (options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weightAttribute: @attribute, defaultWeight: @default}
FILTER e != null RETURN IS_NUMBER(e[@attribute]) ? e[@attribute] : @default) `;
bindVars.attribute = options.weight;
bindVars.attribute = options.weightAttribute;
bindVars.default = options.defaultWeight;
} else {
query += "FILTER e != null RETURN 1) ";
@ -1828,10 +1840,11 @@ Graph.prototype._diameter = function(options) {
"graphName": this.__name
};
query += "SHORTEST_PATH s TO t GRAPH @graphName ";
if (options.hasOwnProperty("weight") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weight: @attribute, defaultWeight: @default}
fixWeight(options);
if (options.hasOwnProperty("weightAttribute") && options.hasOwnProperty("defaultWeight")) {
query += `OPTIONS {weightAttribute: @attribute, defaultWeight: @default}
FILTER e != null RETURN IS_NUMBER(e[@attribute]) ? e[@attribute] : @default)) `;
bindVars.attribute = options.weight;
bindVars.attribute = options.weightAttribute;
bindVars.default = options.defaultWeight;
} else {
query += "RETURN 1)) - 1 ";

View File

@ -243,7 +243,7 @@ class BreadthFirstEnumerator : public PathEnumerator<edgeIdentifier, vertexIdent
PathStep() {}
public:
PathStep(vertexIdentifier const& vertex) : sourceIdx(0), vertex(vertex) {}
explicit PathStep(vertexIdentifier const& vertex) : sourceIdx(0), vertex(vertex) {}
PathStep(size_t sourceIdx, edgeIdentifier const& edge,
vertexIdentifier const& vertex)
@ -453,6 +453,15 @@ class BreadthFirstEnumerator : public PathEnumerator<edgeIdentifier, vertexIdent
private:
inline size_t getDepth(size_t index) const {
size_t depth = 0;
while (index != 0) {
++depth;
index = _schreier[index]->sourceIdx;
}
return depth;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Build the enumerated path for the given index in the schreier
/// vector.
@ -460,23 +469,27 @@ class BreadthFirstEnumerator : public PathEnumerator<edgeIdentifier, vertexIdent
void computeEnumeratedPath(size_t index) {
TRI_ASSERT(index < _schreier.size());
std::vector<edgeIdentifier> edges;
std::vector<vertexIdentifier> vertices;
PathStep* current = nullptr;
while (index != 0) {
current = _schreier[index];
vertices.push_back(current->vertex);
edges.push_back(current->edge);
index = current->sourceIdx;
}
current = _schreier[0];
vertices.push_back(current->vertex);
// Computed path. Insert it into the path enumerator.
size_t depth = getDepth(index);
this->_enumeratedPath.edges.clear();
this->_enumeratedPath.vertices.clear();
std::copy(vertices.rbegin(), vertices.rend(), std::back_inserter(this->_enumeratedPath.vertices));
std::copy(edges.rbegin(), edges.rend(), std::back_inserter(this->_enumeratedPath.edges));
this->_enumeratedPath.edges.resize(depth);
this->_enumeratedPath.vertices.resize(depth + 1);
// Computed path. Insert it into the path enumerator.
PathStep* current = nullptr;
while (index != 0) {
TRI_ASSERT(depth > 0);
current = _schreier[index];
this->_enumeratedPath.vertices[depth] = current->vertex;
this->_enumeratedPath.edges[depth - 1] = current->edge;
index = current->sourceIdx;
--depth;
}
current = _schreier[0];
this->_enumeratedPath.vertices[0] = current->vertex;
}
};