1
0
Fork 0

Merge branch 'spdvpk' of ssh://github.com/ArangoDB/ArangoDB into spdvpk

This commit is contained in:
Max Neunhoeffer 2016-03-10 11:25:20 +01:00
commit 3ed256a478
13 changed files with 633 additions and 572 deletions

View File

@ -479,37 +479,7 @@ static void RequestEdges(VPackSlice const& vertexSlice,
}
VPackBuilder searchValueBuilder;
searchValueBuilder.openArray();
switch (direction) {
case TRI_EDGE_OUT:
searchValueBuilder.openArray();
searchValueBuilder.openObject();
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
searchValueBuilder.close();
searchValueBuilder.close();
searchValueBuilder.add(VPackValue(VPackValueType::None));
break;
case TRI_EDGE_IN:
searchValueBuilder.add(VPackValue(VPackValueType::None));
searchValueBuilder.openArray();
searchValueBuilder.openObject();
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
searchValueBuilder.close();
searchValueBuilder.close();
break;
case TRI_EDGE_ANY:
searchValueBuilder.openArray();
searchValueBuilder.openObject();
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
searchValueBuilder.close();
searchValueBuilder.close();
searchValueBuilder.openArray();
searchValueBuilder.openObject();
searchValueBuilder.add(TRI_SLICE_KEY_EQUAL, VPackValue(vertexId));
searchValueBuilder.close();
searchValueBuilder.close();
}
searchValueBuilder.close();
EdgeIndex::buildSearchValue(direction, vertexId, searchValueBuilder);
VPackSlice search = searchValueBuilder.slice();
OperationCursor cursor = trx->indexScan(
collectionName, arangodb::Transaction::CursorType::INDEX, indexId,
@ -2281,11 +2251,9 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
"'%s'", collectionName.c_str());
}
VertexId v(coli->_cid, const_cast<char*>(str + split + 1));
opts.start = v;
opts.start = vertexId;
} else {
VertexId v(resolver->getCollectionIdLocal(vColName), vertexId.c_str());
opts.start = v;
opts.start = vertexId;
}
VPackSlice direction = ExtractFunctionParameter(trx, parameters, 3);
@ -2337,10 +2305,10 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
trx->addCollectionAtRuntime(eCid);
// Function to return constant distance
auto wc = [](TRI_doc_mptr_t&) -> double { return 1; };
auto wc = [](VPackSlice) -> double { return 1; };
auto eci = std::make_unique<EdgeCollectionInfo>(
trx, eCid, trx->documentCollection(eCid), wc);
trx, eColName, wc);
TRI_IF_FAILURE("EdgeCollectionInfoOOM1") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
@ -2348,7 +2316,7 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
if (n > 4) {
auto edgeExamples = ExtractFunctionParameter(trx, parameters, 4);
if (!(edgeExamples.isArray() && edgeExamples.length() == 0)) {
opts.addEdgeFilter(edgeExamples, eCid);
opts.addEdgeFilter(edgeExamples, eColName);
}
}
@ -2366,7 +2334,7 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
}
std::unordered_set<std::string> neighbors;
#warning TRI_RunNeighborsSearch(edgeCollectionInfos, opts, neighbors);
TRI_RunNeighborsSearch(edgeCollectionInfos, opts, neighbors);
return VertexIdsToAqlValueVPack(query, trx, neighbors, includeData);
}

View File

@ -27,6 +27,15 @@
using ClusterTraversalPath = arangodb::traverser::ClusterTraversalPath;
using ClusterTraverser = arangodb::traverser::ClusterTraverser;
void ClusterTraversalPath::pathToVelocyPack(Transaction*, VPackBuilder&) {
}
void ClusterTraversalPath::lastVertexToVelocyPack(Transaction*, VPackBuilder&) {
}
void ClusterTraversalPath::lastEdgeToVelocyPack(Transaction*, VPackBuilder&) {
}
arangodb::basics::Json* ClusterTraversalPath::pathToJson(
arangodb::Transaction*, arangodb::CollectionNameResolver*) {
auto result =
@ -79,18 +88,18 @@ arangodb::basics::Json* ClusterTraversalPath::lastVertexToJson(
// return _traverser->vertexToJson(_path.vertices.back());
}
bool ClusterTraverser::VertexGetter::operator()(VPackSlice const& edgeId,
VPackSlice const& vertexId,
bool ClusterTraverser::VertexGetter::operator()(std::string const& edgeId,
std::string const& vertexId,
size_t depth,
VPackSlice& result) {
std::string& result) {
auto it = _traverser->_edges.find(edgeId);
if (it != _traverser->_edges.end()) {
VPackSlice from = it->second.get(TRI_VOC_ATTRIBUTE_FROM);
std::string from = it->second.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
if (from != vertexId) {
result.set(from.start());
result = from;
} else {
VPackSlice to = it->second.get(TRI_VOC_ATTRIBUTE_TO);
result.set(to.start());
std::string to = it->second.get(TRI_VOC_ATTRIBUTE_TO).copyString();
result = to;
}
auto exp = _traverser->_expressions->find(depth);
if (exp != _traverser->_expressions->end()) {
@ -108,16 +117,15 @@ bool ClusterTraverser::VertexGetter::operator()(VPackSlice const& edgeId,
return true;
}
// This should never be reached
// Set it to velocypack NONE
VPackSlice def("\x00");
result.set(def.start());
result = "";
return false;
}
void ClusterTraverser::EdgeGetter::operator()(VPackSlice const& startVertex,
std::vector<VPackSlice>& result,
void ClusterTraverser::EdgeGetter::operator()(std::string const& startVertex,
std::vector<std::string>& result,
size_t*& last, size_t& eColIdx,
bool& unused) {
#warning IMPLEMENT
std::string collName;
TRI_edge_direction_e dir;
if (!_traverser->_opts.getCollection(eColIdx, collName, dir)) {
@ -229,7 +237,7 @@ void ClusterTraverser::EdgeGetter::operator()(VPackSlice const& startVertex,
last = nullptr;
return;
}
std::stack<VPackSlice>& tmp = _traverser->_iteratorCache.top();
std::stack<std::string>& tmp = _traverser->_iteratorCache.top();
if (tmp.empty()) {
_traverser->_iteratorCache.pop();
last = nullptr;
@ -237,7 +245,7 @@ void ClusterTraverser::EdgeGetter::operator()(VPackSlice const& startVertex,
operator()(startVertex, result, last, eColIdx, unused);
return;
} else {
VPackSlice const next = tmp.top();
std::string const next = tmp.top();
tmp.pop();
auto search = std::find(result.begin(), result.end(), next);
if (search != result.end()) {
@ -251,11 +259,12 @@ void ClusterTraverser::EdgeGetter::operator()(VPackSlice const& startVertex,
}
void ClusterTraverser::setStartVertex(VPackSlice const& v) {
std::string start = v.get(TRI_VOC_ATTRIBUTE_ID).copyString();
_enumerator.reset(
new arangodb::basics::PathEnumerator<VPackSlice, VPackSlice, size_t>(
_edgeGetter, _vertexGetter, v));
new arangodb::basics::PathEnumerator<std::string, std::string, size_t>(
_edgeGetter, _vertexGetter, start));
_done = false;
auto it = _vertices.find(v);
auto it = _vertices.find(start);
if (it == _vertices.end()) {
/* TODO DEPRECATED: Get Document
arangodb::rest::HttpResponse::HttpResponseCode responseCode;
@ -312,7 +321,7 @@ arangodb::traverser::TraversalPath* ClusterTraverser::next() {
_enumerator->prune();
}
TRI_ASSERT(!_pruneNext);
const arangodb::basics::EnumeratedPath<VPackSlice, VPackSlice>& path =
const arangodb::basics::EnumeratedPath<std::string, std::string>& path =
_enumerator->next();
size_t countEdges = path.edges.size();
if (countEdges == 0) {

View File

@ -68,8 +68,8 @@ class ClusterTraverser : public Traverser {
explicit VertexGetter(ClusterTraverser* traverser)
: _traverser(traverser) {}
bool operator()(arangodb::velocypack::Slice const&, arangodb::velocypack::Slice const&, size_t,
arangodb::velocypack::Slice&);
bool operator()(std::string const&, std::string const&, size_t,
std::string&);
private:
ClusterTraverser* _traverser;
@ -80,8 +80,8 @@ class ClusterTraverser : public Traverser {
explicit EdgeGetter(ClusterTraverser* traverser)
: _traverser(traverser), _continueConst(1) {}
void operator()(arangodb::velocypack::Slice const&,
std::vector<arangodb::velocypack::Slice>&, size_t*&,
void operator()(std::string const&,
std::vector<std::string>&, size_t*&,
size_t&, bool&);
private:
@ -90,11 +90,11 @@ class ClusterTraverser : public Traverser {
size_t _continueConst;
};
std::unordered_map<arangodb::velocypack::Slice, arangodb::velocypack::Slice> _edges;
std::unordered_map<std::string, arangodb::velocypack::Slice> _edges;
std::unordered_map<arangodb::velocypack::Slice, arangodb::velocypack::Slice> _vertices;
std::unordered_map<std::string, arangodb::velocypack::Slice> _vertices;
std::stack<std::stack<arangodb::velocypack::Slice>> _iteratorCache;
std::stack<std::stack<std::string>> _iteratorCache;
std::vector<std::string> _edgeCols;
@ -110,7 +110,7 @@ class ClusterTraverser : public Traverser {
/// @brief internal cursor to enumerate the paths of a graph
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<arangodb::basics::PathEnumerator<arangodb::velocypack::Slice, arangodb::velocypack::Slice,
std::unique_ptr<arangodb::basics::PathEnumerator<std::string, std::string,
size_t>> _enumerator;
};
@ -118,18 +118,26 @@ class ClusterTraversalPath : public TraversalPath {
public:
ClusterTraversalPath(
ClusterTraverser const* traverser,
const arangodb::basics::EnumeratedPath<arangodb::velocypack::Slice, arangodb::velocypack::Slice>& path)
const arangodb::basics::EnumeratedPath<std::string, std::string>& path)
: _path(path), _traverser(traverser) {}
arangodb::basics::Json* pathToJson(Transaction*, CollectionNameResolver*);
void pathToVelocyPack(Transaction*, arangodb::velocypack::Builder&) override;
arangodb::basics::Json* lastEdgeToJson(Transaction*, CollectionNameResolver*);
void lastEdgeToVelocyPack(Transaction*,
arangodb::velocypack::Builder&) override;
void lastVertexToVelocyPack(Transaction*,
arangodb::velocypack::Builder&) override;
arangodb::basics::Json* pathToJson(Transaction*, CollectionNameResolver*) override;
arangodb::basics::Json* lastEdgeToJson(Transaction*, CollectionNameResolver*) override;
arangodb::basics::Json* lastVertexToJson(Transaction*,
CollectionNameResolver*);
CollectionNameResolver*) override;
private:
arangodb::basics::EnumeratedPath<arangodb::velocypack::Slice, arangodb::velocypack::Slice> _path;
arangodb::basics::EnumeratedPath<std::string, std::string> _path;
ClusterTraverser const* _traverser;
};

View File

@ -307,6 +307,41 @@ EdgeIndex::~EdgeIndex() {
delete _edgesFrom;
}
void EdgeIndex::buildSearchValue(TRI_edge_direction_e dir,
std::string const& id, VPackBuilder& builder) {
builder.openArray();
switch (dir) {
case TRI_EDGE_OUT:
builder.openArray();
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, VPackValue(id));
builder.close();
builder.close();
builder.add(VPackValue(VPackValueType::None));
break;
case TRI_EDGE_IN:
builder.add(VPackValue(VPackValueType::None));
builder.openArray();
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, VPackValue(id));
builder.close();
builder.close();
break;
case TRI_EDGE_ANY:
builder.openArray();
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, VPackValue(id));
builder.close();
builder.close();
builder.openArray();
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, VPackValue(id));
builder.close();
builder.close();
}
builder.close();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a selectivity estimate for the index
////////////////////////////////////////////////////////////////////////////////

View File

@ -125,6 +125,9 @@ class EdgeIndex final : public Index {
~EdgeIndex();
static void buildSearchValue(TRI_edge_direction_e, std::string const&,
arangodb::velocypack::Builder&);
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief typedef for hash tables

View File

@ -537,13 +537,17 @@ IndexIterator* PrimaryIndex::createIterator(
}
// use _key value from _id
keys->openArray();
keys->openObject();
keys->add(TRI_SLICE_KEY_EQUAL, VPackValue(key));
keys->close();
keys->close();
} else {
keys->openArray();
keys->openObject();
keys->add(TRI_SLICE_KEY_EQUAL, VPackValue(valNode->getStringValue()));
keys->close();
keys->close();
}
}

View File

@ -67,30 +67,6 @@ class AqlTransaction : public Transaction {
~AqlTransaction() {}
//////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to the transaction for read, at runtime
//////////////////////////////////////////////////////////////////////////////
void addCollectionAtRuntime(TRI_voc_cid_t cid) {
auto collection = this->trxCollection(cid);
if (collection == nullptr) {
int res = TRI_AddCollectionTransaction(this->getInternals(), cid,
TRI_TRANSACTION_READ,
this->nestingLevel(), true, true);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
TRI_EnsureCollectionsTransaction(this->getInternals());
collection = this->trxCollection(cid);
if (collection == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"collection is a nullptr");
}
}
}
//////////////////////////////////////////////////////////////////////////////
/// @brief add a list of collections to the transaction
//////////////////////////////////////////////////////////////////////////////

View File

@ -25,6 +25,7 @@
#define ARANGOD_UTILS_TRANSACTION_H 1
#include "Basics/Common.h"
#include "Basics/Exceptions.h"
#include "Utils/OperationOptions.h"
#include "Utils/OperationResult.h"
#include "VocBase/transaction.h"
@ -255,6 +256,32 @@ class Transaction {
OperationResult any(std::string const&, uint64_t, uint64_t);
//////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to the transaction for read, at runtime
//////////////////////////////////////////////////////////////////////////////
void addCollectionAtRuntime(TRI_voc_cid_t cid) {
auto collection = this->trxCollection(cid);
if (collection == nullptr) {
int res = TRI_AddCollectionTransaction(this->getInternals(), cid,
TRI_TRANSACTION_READ,
this->nestingLevel(), true, true);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
TRI_EnsureCollectionsTransaction(this->getInternals());
collection = this->trxCollection(cid);
if (collection == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"collection is a nullptr");
}
}
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return the type of a collection
//////////////////////////////////////////////////////////////////////////////

View File

@ -24,34 +24,72 @@
#include "V8Traverser.h"
#include "Indexes/EdgeIndex.h"
#include "Utils/CollectionNameResolver.h"
#include "Utils/ShapedJsonTransformer.h"
#include "Utils/OperationCursor.h"
#include "Utils/SingleCollectionTransaction.h"
#include "VocBase/document-collection.h"
#include "VocBase/VocShaper.h"
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::traverser;
////////////////////////////////////////////////////////////////////////////////
/// @brief extract the _from Id out of mptr, we return an RValue reference
/// to explicitly allow move semantics.
////////////////////////////////////////////////////////////////////////////////
static VertexId ExtractFromId(TRI_doc_mptr_t const& ptr) {
return VertexId(TRI_EXTRACT_MARKER_FROM_CID(&ptr),
TRI_EXTRACT_MARKER_FROM_KEY(&ptr));
};
EdgeCollectionInfo::EdgeCollectionInfo(arangodb::Transaction* trx,
std::string const& collectionName,
WeightCalculatorFunction weighter)
: _trx(trx), _collectionName(collectionName), _weighter(weighter) {
TRI_voc_cid_t cid = trx->resolver()->getCollectionIdLocal(collectionName);
if (cid == 0) {
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, "'%s'",
collectionName.c_str());
}
trx->addCollectionAtRuntime(cid);
if (!trx->isEdgeCollection(collectionName)) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID);
}
TRI_document_collection_t* documentCollection = trx->documentCollection(cid);
arangodb::EdgeIndex* edgeIndex = documentCollection->edgeIndex();
TRI_ASSERT(edgeIndex !=
nullptr); // Checked because collection is edge Collection.
_indexId = arangodb::basics::StringUtils::itoa(edgeIndex->id());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extract the _to Id out of mptr, we return an RValue reference
/// to explicitly allow move semantics.
/// @brief Get edges for the given direction and start vertex.
////////////////////////////////////////////////////////////////////////////////
static VertexId ExtractToId(TRI_doc_mptr_t const& ptr) {
return VertexId(TRI_EXTRACT_MARKER_TO_CID(&ptr),
TRI_EXTRACT_MARKER_TO_KEY(&ptr));
};
OperationCursor EdgeCollectionInfo::getEdges(TRI_edge_direction_e direction,
std::string const& vertexId) {
_searchBuilder.clear();
EdgeIndex::buildSearchValue(direction, vertexId, _searchBuilder);
return _trx->indexScan(_collectionName,
arangodb::Transaction::CursorType::INDEX, _indexId,
_searchBuilder.slice(), 0, UINT64_MAX, 1000, false);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Compute the weight of an edge
////////////////////////////////////////////////////////////////////////////////
double EdgeCollectionInfo::weightEdge(VPackSlice const edge) {
return _weighter(edge);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Return name of the wrapped collection
////////////////////////////////////////////////////////////////////////////////
std::string const& EdgeCollectionInfo::getName() {
return _collectionName;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Expander for Multiple edge collections
@ -74,63 +112,73 @@ class MultiCollectionEdgeExpander {
/// @brief function to check if the edge passes the filter
//////////////////////////////////////////////////////////////////////////////
std::function<bool(EdgeId&, TRI_doc_mptr_t*)> _isAllowed;
std::function<bool(VPackSlice)> _isAllowed;
//////////////////////////////////////////////////////////////////////////////
/// @brief function to check if the vertex passes the filter
//////////////////////////////////////////////////////////////////////////////
std::function<bool(VertexId&)> _isAllowedVertex;
std::function<bool(std::string const&)> _isAllowedVertex;
public:
MultiCollectionEdgeExpander(
TRI_edge_direction_e const& direction,
std::vector<EdgeCollectionInfo*> const& edgeCollections,
std::function<bool(EdgeId&, TRI_doc_mptr_t*)> isAllowed,
std::function<bool(VertexId&)> isAllowedVertex)
std::function<bool(VPackSlice const)> isAllowed,
std::function<bool(std::string const&)> isAllowedVertex)
: _direction(direction),
_edgeCollections(edgeCollections),
_isAllowed(isAllowed),
_isAllowedVertex(isAllowedVertex) {}
void operator()(VertexId& source,
void operator()(std::string const& source,
std::vector<ArangoDBPathFinder::Step*>& result) {
std::equal_to<VertexId> eq;
for (auto const& edgeCollection : _edgeCollections) {
TRI_ASSERT(edgeCollection != nullptr);
auto edges = edgeCollection->getEdges(_direction, source);
auto edgeCursor = edgeCollection->getEdges(_direction, source);
std::unordered_map<std::string, size_t> candidates;
std::unordered_map<VertexId, size_t> candidates;
for (size_t j = 0; j < edges.size(); ++j) {
EdgeId edgeId = edgeCollection->extractEdgeId(edges[j]);
if (!_isAllowed(edgeId, &edges[j])) {
continue;
}
VertexId from = ExtractFromId(edges[j]);
VertexId to = ExtractToId(edges[j]);
double currentWeight = edgeCollection->weightEdge(edges[j]);
auto inserter = [&](VertexId& s, VertexId& t) {
if (_isAllowedVertex(t)) {
auto cand = candidates.find(t);
if (cand == candidates.end()) {
// Add weight
result.emplace_back(
new ArangoDBPathFinder::Step(t, s, currentWeight, edgeId));
candidates.emplace(t, result.size() - 1);
} else {
// Compare weight
auto oldWeight = result[cand->second]->weight();
if (currentWeight < oldWeight) {
result[cand->second]->setWeight(currentWeight);
}
auto inserter = [&](std::string const& s, std::string const& t,
double currentWeight, VPackSlice edge) {
if (_isAllowedVertex(t)) {
auto cand = candidates.find(t);
if (cand == candidates.end()) {
// Add weight
#warning The third parameter has to be replaced by _id content. We need to extract the internal attribute here. Waiting for JAN
result.emplace_back(new ArangoDBPathFinder::Step(
t, s, currentWeight,
edge.get(TRI_VOC_ATTRIBUTE_ID).copyString()));
candidates.emplace(t, result.size() - 1);
} else {
// Compare weight
auto oldWeight = result[cand->second]->weight();
if (currentWeight < oldWeight) {
result[cand->second]->setWeight(currentWeight);
}
}
};
if (!eq(from, source)) {
inserter(to, from);
} else if (!eq(to, source)) {
inserter(from, to);
}
};
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
VPackSlice edges = edgeCursor.slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (!_isAllowed(edge)) {
continue;
}
std::string const from = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
std::string const to = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
double currentWeight = edgeCollection->weightEdge(edge);
if (from == source) {
inserter(from, to, currentWeight, edge);
} else {
inserter(to, from, currentWeight, edge);
}
}
}
}
@ -155,36 +203,46 @@ class SimpleEdgeExpander {
EdgeCollectionInfo* edgeCollection)
: _direction(direction), _edgeCollection(edgeCollection) {}
void operator()(VertexId& source,
void operator()(std::string const& source,
std::vector<ArangoDBPathFinder::Step*>& result) {
TRI_ASSERT(_edgeCollection != nullptr);
auto edges = _edgeCollection->getEdges(_direction, source);
std::equal_to<VertexId> eq;
std::unordered_map<VertexId, size_t> candidates;
for (size_t j = 0; j < edges.size(); ++j) {
VertexId from = ExtractFromId(edges[j]);
VertexId to = ExtractToId(edges[j]);
double currentWeight = _edgeCollection->weightEdge(edges[j]);
auto inserter = [&](VertexId& s, VertexId& t) {
auto cand = candidates.find(t);
if (cand == candidates.end()) {
// Add weight
result.emplace_back(new ArangoDBPathFinder::Step(
t, s, currentWeight, _edgeCollection->extractEdgeId(edges[j])));
candidates.emplace(t, result.size() - 1);
} else {
// Compare weight
auto oldWeight = result[cand->second]->weight();
if (currentWeight < oldWeight) {
result[cand->second]->setWeight(currentWeight);
}
std::unordered_map<std::string, size_t> candidates;
auto inserter = [&](std::string const& s, std::string const& t,
double currentWeight, VPackSlice edge) {
auto cand = candidates.find(t);
if (cand == candidates.end()) {
// Add weight
result.emplace_back(new ArangoDBPathFinder::Step(
#warning The third parameter has to be replaced by _id content. We need to extract the internal attribute here. Waiting for JAN
t, s, currentWeight, edge.get(TRI_VOC_ATTRIBUTE_ID).copyString()));
candidates.emplace(t, result.size() - 1);
} else {
// Compare weight
auto oldWeight = result[cand->second]->weight();
if (currentWeight < oldWeight) {
result[cand->second]->setWeight(currentWeight);
}
}
};
auto edgeCursor = _edgeCollection->getEdges(_direction, source);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
VPackSlice edges = edgeCursor.slice();
for (auto const& edge : VPackArrayIterator(edges)) {
std::string const from = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
std::string const to = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
double currentWeight = _edgeCollection->weightEdge(edge);
if (from == source) {
inserter(from, to, currentWeight, edge);
} else {
inserter(to, from, currentWeight, edge);
}
};
if (!eq(from, source)) {
inserter(to, from);
} else if (!eq(to, source)) {
inserter(from, to);
}
}
}
@ -226,12 +284,15 @@ void BasicOptions::addVertexFilter(v8::Isolate* isolate,
/// @brief Checks if a vertex matches to given examples
////////////////////////////////////////////////////////////////////////////////
bool BasicOptions::matchesVertex(VertexId const& v) const {
bool BasicOptions::matchesVertex(std::string const& v) const {
if (!useVertexFilter) {
// Nothing to do
return true;
}
#warning We need to find a solution for this. cid => matcher, is not available any more
return true;
/*
auto it = _vertexFilter.find(v.cid);
if (it == _vertexFilter.end()) {
@ -253,6 +314,7 @@ bool BasicOptions::matchesVertex(VertexId const& v) const {
}
return it->second.matcher->matches(opRes.slice());
*/
}
////////////////////////////////////////////////////////////////////////////////
@ -261,10 +323,10 @@ bool BasicOptions::matchesVertex(VertexId const& v) const {
void BasicOptions::addEdgeFilter(v8::Isolate* isolate,
v8::Handle<v8::Value> const& example,
VocShaper* shaper, TRI_voc_cid_t const& cid,
std::string const& cName,
std::string& errorMessage) {
useEdgeFilter = true;
auto it = _edgeFilter.find(cid);
auto it = _edgeFilter.find(cName);
if (it != _edgeFilter.end()) {
return;
@ -272,12 +334,12 @@ void BasicOptions::addEdgeFilter(v8::Isolate* isolate,
if (example->IsArray()) {
_edgeFilter.emplace(
cid, new ExampleMatcher(isolate, v8::Handle<v8::Array>::Cast(example),
cName, new ExampleMatcher(isolate, v8::Handle<v8::Array>::Cast(example),
errorMessage));
} else {
// Has to be Object
_edgeFilter.emplace(
cid, new ExampleMatcher(isolate, v8::Handle<v8::Object>::Cast(example),
cName, new ExampleMatcher(isolate, v8::Handle<v8::Object>::Cast(example),
errorMessage));
}
}
@ -286,26 +348,12 @@ void BasicOptions::addEdgeFilter(v8::Isolate* isolate,
/// @brief Insert a new edge matcher object
////////////////////////////////////////////////////////////////////////////////
void BasicOptions::addEdgeFilter(Json const& example, VocShaper* shaper,
TRI_voc_cid_t const& cid,
CollectionNameResolver const* resolver) {
useEdgeFilter = true;
auto it = _edgeFilter.find(cid);
if (it == _edgeFilter.end()) {
_edgeFilter.emplace(cid, new ExampleMatcher(example.json(), resolver));
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Insert a new edge matcher object
////////////////////////////////////////////////////////////////////////////////
void BasicOptions::addEdgeFilter(VPackSlice const& example,
TRI_voc_cid_t const& cid) {
std::string const& cName) {
useEdgeFilter = true;
auto it = _edgeFilter.find(cid);
auto it = _edgeFilter.find(cName);
if (it == _edgeFilter.end()) {
_edgeFilter.emplace(cid, new ExampleMatcher(example, true));
_edgeFilter.emplace(cName, new ExampleMatcher(example, true));
}
}
@ -315,28 +363,32 @@ void BasicOptions::addEdgeFilter(VPackSlice const& example,
/// @brief Checks if an edge matches to given examples
////////////////////////////////////////////////////////////////////////////////
bool BasicOptions::matchesEdge(EdgeId& e, TRI_doc_mptr_t* edge) const {
bool BasicOptions::matchesEdge(VPackSlice edge) const {
if (!useEdgeFilter) {
// Nothing to do
return true;
}
#warning We need to find a solution for this. cid => matcher, is not available any more
return true;
/*
auto it = _edgeFilter.find(e.cid);
if (it == _edgeFilter.end()) {
// This collection does not have any object of this shape.
// This collection does not have any object that can match.
// Short circuit.
return false;
}
return it->second->matches(VPackSlice(edge->vpack()));
*/
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if a vertex matches to given examples
////////////////////////////////////////////////////////////////////////////////
bool ShortestPathOptions::matchesVertex(VertexId const& v) const {
bool ShortestPathOptions::matchesVertex(std::string const& v) const {
if (start == v || end == v) {
return true;
}
@ -348,13 +400,17 @@ bool ShortestPathOptions::matchesVertex(VertexId const& v) const {
/// @brief Checks if a vertex matches to given examples
////////////////////////////////////////////////////////////////////////////////
bool NeighborsOptions::matchesVertex(VertexId const& v) const {
bool NeighborsOptions::matchesVertex(std::string const& v) const {
// If there are explicitly marked collections check them.
if (!_explicitCollections.empty()) {
#warning find a solution for this.VertexId
return false;
// If the current collection is not stored the result is invalid
/*
if (_explicitCollections.find(v.cid) == _explicitCollections.end()) {
return false;
}
*/
}
return BasicOptions::matchesVertex(v);
}
@ -392,11 +448,11 @@ std::unique_ptr<ArangoDBPathFinder::Path> TRI_RunShortestPathSearch(
backward = TRI_EDGE_ANY;
}
auto edgeFilterClosure = [&opts](EdgeId& e, TRI_doc_mptr_t* edge)
-> bool { return opts.matchesEdge(e, edge); };
auto edgeFilterClosure = [&opts](VPackSlice edge)
-> bool { return opts.matchesEdge(edge); };
auto vertexFilterClosure =
[&opts](VertexId& v) -> bool { return opts.matchesVertex(v); };
[&opts](std::string const& v) -> bool { return opts.matchesVertex(v); };
MultiCollectionEdgeExpander forwardExpander(
forward, collectionInfos, edgeFilterClosure, vertexFilterClosure);
@ -437,47 +493,65 @@ TRI_RunSimpleShortestPathSearch(
}
auto fwExpander =
[&collectionInfos, forward](VertexId& v, std::vector<EdgeId>& res_edges,
std::vector<VertexId>& neighbors) {
std::equal_to<VertexId> eq;
[&collectionInfos, forward](std::string const& v, std::vector<std::string>& res_edges,
std::vector<std::string>& neighbors) {
for (auto const& edgeCollection : collectionInfos) {
TRI_ASSERT(edgeCollection != nullptr);
auto edges = edgeCollection->getEdges(forward, v);
for (size_t j = 0; j < edges.size(); ++j) {
EdgeId edgeId = edgeCollection->extractEdgeId(edges[j]);
VertexId from = ExtractFromId(edges[j]);
if (!eq(from, v)) {
res_edges.emplace_back(edgeId);
neighbors.emplace_back(from);
} else {
VertexId to = ExtractToId(edges[j]);
if (!eq(to, v)) {
OperationCursor edgeCursor = edgeCollection->getEdges(forward, v);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
VPackSlice edges = edgeCursor.slice();
for (auto const& edge : VPackArrayIterator(edges)) {
#warning fucking custom type
std::string edgeId = edge.get(TRI_VOC_ATTRIBUTE_ID).copyString();
std::string from = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
if (from == v) {
std::string to = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
if (to == v) {
res_edges.emplace_back(edgeId);
neighbors.emplace_back(to);
}
} else {
res_edges.emplace_back(edgeId);
neighbors.emplace_back(to);
neighbors.emplace_back(from);
}
}
}
}
};
auto bwExpander =
[&collectionInfos, backward](VertexId& v, std::vector<EdgeId>& res_edges,
std::vector<VertexId>& neighbors) {
std::equal_to<VertexId> eq;
[&collectionInfos, backward](std::string const& v, std::vector<std::string>& res_edges,
std::vector<std::string>& neighbors) {
for (auto const& edgeCollection : collectionInfos) {
TRI_ASSERT(edgeCollection != nullptr);
auto edges = edgeCollection->getEdges(backward, v);
for (size_t j = 0; j < edges.size(); ++j) {
EdgeId edgeId = edgeCollection->extractEdgeId(edges[j]);
VertexId from = ExtractFromId(edges[j]);
if (!eq(from, v)) {
res_edges.emplace_back(edgeId);
neighbors.emplace_back(from);
} else {
VertexId to = ExtractToId(edges[j]);
if (!eq(to, v)) {
OperationCursor edgeCursor = edgeCollection->getEdges(backward, v);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
VPackSlice edges = edgeCursor.slice();
for (auto const& edge : VPackArrayIterator(edges)) {
#warning fucking custom type
std::string edgeId = edge.get(TRI_VOC_ATTRIBUTE_ID).copyString();
std::string from = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
if (from == v) {
std::string to = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
if (to == v) {
res_edges.emplace_back(edgeId);
neighbors.emplace_back(to);
}
} else {
res_edges.emplace_back(edgeId);
neighbors.emplace_back(to);
neighbors.emplace_back(from);
}
}
}
}
@ -495,35 +569,40 @@ TRI_RunSimpleShortestPathSearch(
static void InboundNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
NeighborsOptions& opts,
std::unordered_set<VertexId>& startVertices,
std::unordered_set<VertexId>& visited,
std::unordered_set<VertexId>& distinct,
std::unordered_set<std::string>& startVertices,
std::unordered_set<std::string>& visited,
std::unordered_set<std::string>& distinct,
uint64_t depth = 1) {
TRI_edge_direction_e dir = TRI_EDGE_IN;
std::unordered_set<VertexId> nextDepth;
std::unordered_set<std::string> nextDepth;
for (auto const& col : collectionInfos) {
TRI_ASSERT(col != nullptr);
for (VertexId const& start : startVertices) {
auto edges = col->getEdges(dir, start);
for (size_t j = 0; j < edges.size(); ++j) {
EdgeId edgeId = col->extractEdgeId(edges[j]);
if (opts.matchesEdge(edgeId, &edges[j])) {
VertexId v = ExtractFromId(edges[j]);
if (visited.find(v) != visited.end()) {
// We have already visited this vertex
continue;
}
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
for (auto const& start : startVertices) {
auto edgeCursor = col->getEdges(dir, start);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
VPackSlice edges = edgeCursor.slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (opts.matchesEdge(edge)) {
std::string v = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
if (visited.find(v) != visited.end()) {
// We have already visited this vertex
continue;
}
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
}
}
@ -542,39 +621,46 @@ static void InboundNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
static void OutboundNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
NeighborsOptions& opts,
std::unordered_set<VertexId>& startVertices,
std::unordered_set<VertexId>& visited,
std::unordered_set<VertexId>& distinct,
std::unordered_set<std::string>& startVertices,
std::unordered_set<std::string>& visited,
std::unordered_set<std::string>& distinct,
uint64_t depth = 1) {
TRI_edge_direction_e dir = TRI_EDGE_OUT;
std::unordered_set<VertexId> nextDepth;
std::unordered_set<std::string> nextDepth;
for (auto const& col : collectionInfos) {
TRI_ASSERT(col != nullptr);
for (VertexId const& start : startVertices) {
auto edges = col->getEdges(dir, start);
for (size_t j = 0; j < edges.size(); ++j) {
EdgeId edgeId = col->extractEdgeId(edges[j]);
if (opts.matchesEdge(edgeId, &edges[j])) {
VertexId v = ExtractToId(edges[j]);
if (visited.find(v) != visited.end()) {
// We have already visited this vertex
continue;
}
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
for (auto const& start : startVertices) {
auto edgeCursor = col->getEdges(dir, start);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
VPackSlice edges = edgeCursor.slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (opts.matchesEdge(edge)) {
std::string v = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
if (visited.find(v) != visited.end()) {
// We have already visited this vertex
continue;
}
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
}
}
}
}
if (!nextDepth.empty()) {
OutboundNeighbors(collectionInfos, opts, nextDepth, visited, distinct,
depth + 1);
@ -587,61 +673,57 @@ static void OutboundNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
static void AnyNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
NeighborsOptions& opts,
std::unordered_set<VertexId>& startVertices,
std::unordered_set<VertexId>& visited,
std::unordered_set<VertexId>& distinct,
std::unordered_set<std::string>& startVertices,
std::unordered_set<std::string>& visited,
std::unordered_set<std::string>& distinct,
uint64_t depth = 1) {
TRI_edge_direction_e dir = TRI_EDGE_OUT;
std::unordered_set<VertexId> nextDepth;
TRI_edge_direction_e dir = TRI_EDGE_ANY;
std::unordered_set<std::string> nextDepth;
for (auto const& col : collectionInfos) {
TRI_ASSERT(col != nullptr);
for (VertexId const& start : startVertices) {
dir = TRI_EDGE_OUT;
auto edges = col->getEdges(dir, start);
for (size_t j = 0; j < edges.size(); ++j) {
EdgeId edgeId = col->extractEdgeId(edges[j]);
if (opts.matchesEdge(edgeId, &edges[j])) {
VertexId v = ExtractToId(edges[j]);
if (visited.find(v) != visited.end()) {
// We have already visited this vertex
continue;
}
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
for (auto const& start : startVertices) {
auto edgeCursor = col->getEdges(dir, start);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
}
dir = TRI_EDGE_IN;
edges = col->getEdges(dir, start);
for (size_t j = 0; j < edges.size(); ++j) {
EdgeId edgeId = col->extractEdgeId(edges[j]);
if (opts.matchesEdge(edgeId, &edges[j])) {
VertexId v = ExtractFromId(edges[j]);
if (visited.find(v) != visited.end()) {
// We have already visited this vertex
continue;
}
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
VPackSlice edges = edgeCursor.slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (opts.matchesEdge(edge)) {
std::string v = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
if (visited.find(v) == visited.end()) {
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
}
v = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
if (visited.find(v) == visited.end()) {
visited.emplace(v);
if (depth >= opts.minDepth) {
if (opts.matchesVertex(v)) {
distinct.emplace(v);
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
}
}
if (depth < opts.maxDepth) {
nextDepth.emplace(v);
}
}
}
}
}
if (!nextDepth.empty()) {
AnyNeighbors(collectionInfos, opts, nextDepth, visited, distinct,
depth + 1);
@ -654,9 +736,9 @@ static void AnyNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
void TRI_RunNeighborsSearch(std::vector<EdgeCollectionInfo*>& collectionInfos,
NeighborsOptions& opts,
std::unordered_set<VertexId>& result) {
std::unordered_set<VertexId> startVertices;
std::unordered_set<VertexId> visited;
std::unordered_set<std::string>& result) {
std::unordered_set<std::string> startVertices;
std::unordered_set<std::string> visited;
startVertices.emplace(opts.start);
visited.emplace(opts.start);
@ -673,103 +755,64 @@ void TRI_RunNeighborsSearch(std::vector<EdgeCollectionInfo*>& collectionInfos,
}
}
Json* SingleServerTraversalPath::pathToJson(Transaction* trx,
CollectionNameResolver* resolver) {
auto path = std::make_unique<Json>(Json::Object, 2);
Json vertices(Json::Array);
for (size_t i = 0; i < _path.vertices.size(); ++i) {
auto v = vertexToJson(trx, resolver, _path.vertices[i]);
try {
vertices(*v);
delete v;
} catch (...) {
delete v;
throw;
}
}
Json edges(Json::Array);
for (size_t i = 0; i < _path.edges.size(); ++i) {
auto e = edgeToJson(trx, resolver, _path.edges[i]);
try {
edges(*e);
delete e;
} catch (...) {
delete e;
throw;
}
}
(*path)("vertices", vertices)("edges", edges);
void SingleServerTraversalPath::getDocumentByIdentifier(Transaction* trx,
std::string const& identifier,
VPackBuilder& result) {
// TODO Check if we can get away with using ONLY VPackSlices referencing externals instead of std::string.
// I am afaid that they may run out of scope.
_searchBuilder.clear();
_searchBuilder.openObject();
_searchBuilder.add(VPackValue(TRI_VOC_ATTRIBUTE_KEY));
return path.release();
std::vector<std::string> parts =
arangodb::basics::StringUtils::split(identifier, "/");
TRI_ASSERT(parts.size() == 2);
_searchBuilder.add(VPackValue(parts[1]));
_searchBuilder.close();
TRI_voc_cid_t cid = trx->resolver()->getCollectionIdLocal(parts[0]);
if (cid == 0) {
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, "'%s'",
parts[0].c_str());
}
trx->addCollectionAtRuntime(cid);
OperationOptions options;
OperationResult opRes = trx->document(parts[0], _searchBuilder.slice(), options);
if (opRes.failed()) {
THROW_ARANGO_EXCEPTION(opRes.code);
}
result.add(opRes.slice());
}
Json* SingleServerTraversalPath::lastEdgeToJson(
Transaction* trx, CollectionNameResolver* resolver) {
return edgeToJson(trx, resolver, _path.edges.back());
void SingleServerTraversalPath::pathToVelocyPack(Transaction* trx,
VPackBuilder& result) {
result.openObject();
result.add(VPackValue("edges"));
result.openArray();
for (auto const& it : _path.edges) {
getDocumentByIdentifier(trx, it, result);
}
result.close();
result.add(VPackValue("vertices"));
result.openArray();
for (auto const& it : _path.vertices) {
getDocumentByIdentifier(trx, it, result);
}
result.close();
result.close();
}
Json* SingleServerTraversalPath::lastVertexToJson(
Transaction* trx, CollectionNameResolver* resolver) {
return vertexToJson(trx, resolver, _path.vertices.back());
void SingleServerTraversalPath::lastEdgeToVelocyPack(Transaction* trx, VPackBuilder& result) {
getDocumentByIdentifier(trx, _path.edges.back(), result);
}
Json* SingleServerTraversalPath::edgeToJson(Transaction* trx,
CollectionNameResolver* resolver,
EdgeInfo const& e) {
TRI_document_collection_t* documentCollection = trx->documentCollection(e.cid);
if (documentCollection == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
TRI_shaped_json_t shapedJson;
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, &e.mptr);
return new Json(
TRI_ExpandShapedJson(documentCollection->getShaper(),
resolver, e.cid, &e.mptr));
}
Json* SingleServerTraversalPath::vertexToJson(Transaction* trx,
CollectionNameResolver* resolver,
VPackSlice const& v) {
return nullptr;
// TODO FIXME
/* This has to be replaced by new Transaction API
auto collection = trx->trxCollection(v.cid);
if (collection == nullptr) {
int res = TRI_AddCollectionTransaction(trx->getInternals(), v.cid,
TRI_TRANSACTION_READ,
trx->nestingLevel(), true, true);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
TRI_EnsureCollectionsTransaction(trx->getInternals());
collection = trx->trxCollection(v.cid);
if (collection == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"collection is a nullptr");
}
auto trxCollection = trx->trxCollection(v.cid);
if (trxCollection != nullptr) {
trx->orderDitch(trxCollection);
}
}
TRI_doc_mptr_t mptr;
int res = trx->document(collection, &mptr, v.key);
++_readDocuments;
if (res != TRI_ERROR_NO_ERROR) {
if (res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
return new Json(Json::Null);
}
THROW_ARANGO_EXCEPTION(res);
}
return new Json(
TRI_ExpandShapedJson(collection->_collection->_collection->getShaper(),
resolver, v.cid, &mptr));
*/
void SingleServerTraversalPath::lastVertexToVelocyPack(Transaction* trx, VPackBuilder& result) {
getDocumentByIdentifier(trx, _path.vertices.back(), result);
}
DepthFirstTraverser::DepthFirstTraverser(
@ -881,8 +924,8 @@ bool DepthFirstTraverser::vertexMatchesConditions(VPackSlice const& v,
}
void DepthFirstTraverser::_defInternalFunctions() {
_getVertex = [](EdgeInfo const& edge, VPackSlice const& vertex, size_t depth,
VPackSlice& result) -> bool {
_getVertex = [](std::string const& edge, std::string const& vertex, size_t depth,
std::string& result) -> bool {
return false;
// TODO FIX THIS
/* Do we still use mptr here or do we switch to VPack?
@ -960,8 +1003,9 @@ void DepthFirstTraverser::setStartVertex(
}
}
}
_enumerator.reset(new PathEnumerator<EdgeInfo, VPackSlice, TRI_doc_mptr_t>(
_edgeGetter, _getVertex, v));
std::string tmp = v.get(TRI_VOC_ATTRIBUTE_ID).copyString();
_enumerator.reset(new PathEnumerator<std::string, std::string, TRI_doc_mptr_t>(
_edgeGetter, _getVertex, tmp));
_done = false;
}
@ -972,7 +1016,7 @@ TraversalPath* DepthFirstTraverser::next() {
_enumerator->prune();
}
TRI_ASSERT(!_pruneNext);
const EnumeratedPath<EdgeInfo, VPackSlice>& path = _enumerator->next();
const EnumeratedPath<std::string, std::string>& path = _enumerator->next();
size_t countEdges = path.edges.size();
if (countEdges == 0) {
_done = true;
@ -1008,9 +1052,13 @@ EdgeIndex* DepthFirstTraverser::EdgeGetter::getEdgeIndex(
}
void DepthFirstTraverser::EdgeGetter::operator()(
arangodb::velocypack::Slice const& startVertex,
std::vector<EdgeInfo>& edges, TRI_doc_mptr_t*& last, size_t& eColIdx,
std::string const& startVertex,
std::vector<std::string>& edges, TRI_doc_mptr_t*& last, size_t& eColIdx,
bool& dir) {
#warning use new EdgeIndex VPACK lookup here.
// builderSearchValue(dir, startVertex, builder);
// trx->indexScan();
/*
std::string eColName;
TRI_edge_direction_e direction;
while (true) {
@ -1071,4 +1119,5 @@ void DepthFirstTraverser::EdgeGetter::operator()(
edges.push_back(e);
return;
}
*/
}

View File

@ -30,6 +30,9 @@
#include "VocBase/Traverser.h"
namespace arangodb {
struct OperationCursor;
namespace velocypack {
class Slice;
}
@ -77,13 +80,11 @@ struct VertexFilterInfo {
/// @brief typedef the template instantiation of the PathFinder
////////////////////////////////////////////////////////////////////////////////
typedef arangodb::basics::PathFinder<arangodb::traverser::VertexId,
arangodb::traverser::EdgeId,
double> ArangoDBPathFinder;
typedef arangodb::basics::PathFinder<std::string, std::string, double>
ArangoDBPathFinder;
typedef arangodb::basics::ConstDistanceFinder<arangodb::traverser::VertexId,
arangodb::traverser::EdgeId>
ArangoDBConstDistancePathFinder;
typedef arangodb::basics::ConstDistanceFinder<
std::string, std::string> ArangoDBConstDistancePathFinder;
namespace arangodb {
namespace traverser {
@ -92,7 +93,7 @@ namespace traverser {
// Should not be used directly, use specialization instead.
struct BasicOptions {
protected:
std::unordered_map<TRI_voc_cid_t, arangodb::ExampleMatcher*> _edgeFilter;
std::unordered_map<std::string, arangodb::ExampleMatcher*> _edgeFilter;
std::unordered_map<TRI_voc_cid_t, VertexFilterInfo> _vertexFilter;
BasicOptions() : useEdgeFilter(false), useVertexFilter(false) {}
@ -109,20 +110,16 @@ struct BasicOptions {
}
public:
VertexId start;
std::string start;
bool useEdgeFilter;
bool useVertexFilter;
void addEdgeFilter(v8::Isolate* isolate, v8::Handle<v8::Value> const& example,
VocShaper* shaper, TRI_voc_cid_t const& cid,
std::string const&,
std::string& errorMessage);
void addEdgeFilter(arangodb::basics::Json const& example, VocShaper* shaper,
TRI_voc_cid_t const& cid,
arangodb::CollectionNameResolver const* resolver);
void addEdgeFilter(arangodb::velocypack::Slice const& example,
TRI_voc_cid_t const& cid);
std::string const&);
void addVertexFilter(v8::Isolate* isolate,
v8::Handle<v8::Value> const& example,
@ -130,9 +127,9 @@ struct BasicOptions {
TRI_document_collection_t* col, VocShaper* shaper,
TRI_voc_cid_t const& cid, std::string& errorMessage);
bool matchesEdge(EdgeId& e, TRI_doc_mptr_t* edge) const;
bool matchesEdge(arangodb::velocypack::Slice edge) const;
bool matchesVertex(VertexId const& v) const;
bool matchesVertex(std::string const& v) const;
};
struct NeighborsOptions : BasicOptions {
@ -146,7 +143,7 @@ struct NeighborsOptions : BasicOptions {
NeighborsOptions() : direction(TRI_EDGE_OUT), minDepth(1), maxDepth(1) {}
bool matchesVertex(VertexId const&) const;
bool matchesVertex(std::string const&) const;
void addCollectionRestriction(TRI_voc_cid_t cid);
};
@ -159,7 +156,7 @@ struct ShortestPathOptions : BasicOptions {
double defaultWeight;
bool bidirectional;
bool multiThreaded;
VertexId end;
std::string end;
ShortestPathOptions()
: direction("outbound"),
@ -169,37 +166,35 @@ struct ShortestPathOptions : BasicOptions {
bidirectional(true),
multiThreaded(true) {}
bool matchesVertex(VertexId const&) const;
bool matchesVertex(std::string const&) const;
};
class SingleServerTraversalPath : public TraversalPath {
public:
explicit SingleServerTraversalPath(
arangodb::basics::EnumeratedPath<EdgeInfo,
arangodb::velocypack::Slice> const& path)
arangodb::basics::EnumeratedPath<std::string, std::string> const& path)
: _path(path) {}
~SingleServerTraversalPath() {}
arangodb::basics::Json* pathToJson(
arangodb::Transaction*, arangodb::CollectionNameResolver*) override;
void pathToVelocyPack(arangodb::Transaction*,
arangodb::velocypack::Builder&) override;
arangodb::basics::Json* lastEdgeToJson(
arangodb::Transaction*, arangodb::CollectionNameResolver*) override;
void lastEdgeToVelocyPack(arangodb::Transaction*,
arangodb::velocypack::Builder&) override;
arangodb::basics::Json* lastVertexToJson(
arangodb::Transaction*, arangodb::CollectionNameResolver*) override;
void lastVertexToVelocyPack(arangodb::Transaction*,
arangodb::velocypack::Builder&) override;
private:
arangodb::basics::Json* edgeToJson(Transaction* trx,
CollectionNameResolver* resolver,
EdgeInfo const& e);
arangodb::basics::Json* vertexToJson(Transaction* trx,
CollectionNameResolver* resolver,
arangodb::velocypack::Slice const& v);
void getDocumentByIdentifier(Transaction*, std::string const&,
arangodb::velocypack::Builder&);
arangodb::basics::EnumeratedPath<std::string, std::string> _path;
arangodb::velocypack::Builder _searchBuilder;
arangodb::basics::EnumeratedPath<EdgeInfo, arangodb::velocypack::Slice> _path;
};
class DepthFirstTraverser : public Traverser {
@ -220,7 +215,7 @@ class DepthFirstTraverser : public Traverser {
/// @brief Function to fill the list of edges properly.
//////////////////////////////////////////////////////////////////////////////
void operator()(arangodb::velocypack::Slice const&, std::vector<EdgeInfo>&,
void operator()(std::string const&, std::vector<std::string>&,
TRI_doc_mptr_t*&, size_t&, bool&);
private:
@ -272,9 +267,8 @@ class DepthFirstTraverser : public Traverser {
/// @brief internal cursor to enumerate the paths of a graph
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<arangodb::basics::PathEnumerator<
EdgeInfo, arangodb::velocypack::Slice, TRI_doc_mptr_t>>
_enumerator;
std::unique_ptr<arangodb::basics::PathEnumerator<std::string, std::string,
TRI_doc_mptr_t>> _enumerator;
//////////////////////////////////////////////////////////////////////////////
/// @brief internal getter to extract an edge
@ -286,8 +280,8 @@ class DepthFirstTraverser : public Traverser {
/// @brief internal function to extract vertex information
//////////////////////////////////////////////////////////////////////////////
std::function<bool(EdgeInfo const&, arangodb::velocypack::Slice const&,
size_t, arangodb::velocypack::Slice&)> _getVertex;
std::function<bool(std::string const&, std::string const&,
size_t, std::string&)> _getVertex;
//////////////////////////////////////////////////////////////////////////////
/// @brief a vector containing all required edge collection structures
@ -337,7 +331,7 @@ class DepthFirstTraverser : public Traverser {
/// @brief callback to weight an edge
////////////////////////////////////////////////////////////////////////////////
typedef std::function<double(TRI_doc_mptr_t& edge)>
typedef std::function<double(arangodb::velocypack::Slice const)>
WeightCalculatorFunction;
////////////////////////////////////////////////////////////////////////////////
@ -355,51 +349,46 @@ class EdgeCollectionInfo {
arangodb::Transaction* _trx;
//////////////////////////////////////////////////////////////////////////////
/// @brief edge collection
/// @brief edge collection name
//////////////////////////////////////////////////////////////////////////////
TRI_voc_cid_t _edgeCollectionCid;
std::string _collectionName;
//////////////////////////////////////////////////////////////////////////////
/// @brief edge collection
/// @brief index id
//////////////////////////////////////////////////////////////////////////////
TRI_document_collection_t* _edgeCollection;
std::string _indexId;
//////////////////////////////////////////////////////////////////////////////
/// @brief weighter functions
/// @brief VPackBuilder to build edge index search value in place.
/// Reused for every request.
//////////////////////////////////////////////////////////////////////////////
arangodb::velocypack::Builder _searchBuilder;
WeightCalculatorFunction _weighter;
public:
EdgeCollectionInfo(arangodb::Transaction* trx,
TRI_voc_cid_t& edgeCollectionCid,
TRI_document_collection_t* edgeCollection,
WeightCalculatorFunction weighter)
: _trx(trx),
_edgeCollectionCid(edgeCollectionCid),
_edgeCollection(edgeCollection),
_weighter(weighter) {}
std::string const& collectionName,
WeightCalculatorFunction weighter);
arangodb::traverser::EdgeId extractEdgeId(TRI_doc_mptr_t& ptr) {
return arangodb::traverser::EdgeId(_edgeCollectionCid,
TRI_EXTRACT_MARKER_KEY(&ptr));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get edges for the given direction and start vertex.
////////////////////////////////////////////////////////////////////////////////
std::vector<TRI_doc_mptr_t> getEdges(
TRI_edge_direction_e direction,
arangodb::traverser::VertexId const& vertexId) const {
return TRI_LookupEdgesDocumentCollection(_trx, _edgeCollection, direction,
vertexId.cid,
const_cast<char*>(vertexId.key));
}
arangodb::OperationCursor getEdges(TRI_edge_direction_e direction,
std::string const&);
TRI_voc_cid_t getCid() { return _edgeCollectionCid; }
double weightEdge(arangodb::velocypack::Slice const);
VocShaper* getShaper() { return _edgeCollection->getShaper(); }
////////////////////////////////////////////////////////////////////////////////
/// @brief Return name of the wrapped collection
////////////////////////////////////////////////////////////////////////////////
std::string const& getName();
double weightEdge(TRI_doc_mptr_t& ptr) { return _weighter(ptr); }
};
////////////////////////////////////////////////////////////////////////////////
@ -456,6 +445,6 @@ TRI_RunSimpleShortestPathSearch(
void TRI_RunNeighborsSearch(
std::vector<EdgeCollectionInfo*>& collectionInfos,
arangodb::traverser::NeighborsOptions& opts,
std::unordered_set<arangodb::traverser::VertexId>& distinct);
std::unordered_set<std::string>& distinct);
#endif

View File

@ -38,6 +38,7 @@
#include "Cluster/ClusterInfo.h"
#include "Cluster/ClusterMethods.h"
#include "Cluster/ServerState.h"
#include "Indexes/Index.h"
#include "HttpServer/ApplicationEndpointServer.h"
#include "RestServer/ConsoleThread.h"
#include "RestServer/VocbaseContext.h"
@ -1704,11 +1705,11 @@ static void JS_ThrowCollectionNotLoaded(
////////////////////////////////////////////////////////////////////////////////
static v8::Local<v8::String> VertexIdToString(
v8::Isolate* isolate, CollectionNameResolver const* resolver,
VertexId const& id) {
return TRI_V8_STD_STRING(
(resolver->getCollectionName(id.cid) + "/" + std::string(id.key)));
v8::Isolate* isolate,
std::string const& id) {
return TRI_V8_STD_STRING(id);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Transforms EdgeId to v8String
////////////////////////////////////////////////////////////////////////////////
@ -1721,56 +1722,53 @@ static v8::Local<v8::String> EdgeIdToString(
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Transforms VertexId to v8 json
/// @brief Transforms VertexId to v8 object
/// NOTE: Collection has to be known to the transaction.
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> VertexIdToData(
v8::Isolate* isolate, CollectionNameResolver const* resolver,
ExplicitTransaction* trx,
std::unordered_map<TRI_voc_cid_t, CollectionDitchInfo> const& ditches,
VertexId const& vertexId) {
auto i = ditches.find(vertexId.cid);
if (i == ditches.end()) {
v8::EscapableHandleScope scope(isolate);
return scope.Escape<v8::Value>(v8::Null(isolate));
}
v8::Isolate* isolate,
Transaction* trx,
std::string const& vertexId) {
OperationOptions options;
std::vector<std::string> parts =
arangodb::basics::StringUtils::split(vertexId, "/");
TRI_ASSERT(parts.size() == 2); // All internal _id attributes
VPackSlice slice;
#warning fill slice from vertexId.key
OperationResult opRes = trx->document(i->second.col->_info.name(), slice, options);
#warning fill document
TRI_doc_mptr_t document;
VPackBuilder builder;
builder.openArray();
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, VPackValue(parts[1]));
builder.close();
builder.close();
OperationResult opRes = trx->document(parts[0], builder.slice(), options);
if (!opRes.successful()) {
v8::EscapableHandleScope scope(isolate);
return scope.Escape<v8::Value>(v8::Null(isolate));
}
return TRI_WrapShapedJson(isolate, resolver, i->second.ditch, vertexId.cid,
i->second.col,
document.getDataPtr());
VPackOptions resultOptions = VPackOptions::Defaults;
resultOptions.customTypeHandler = opRes.customTypeHandler.get();
return TRI_VPackToV8(isolate, opRes.slice(), &resultOptions);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Transforms EdgeId to v8 json
/// @brief Transforms EdgeId to v8 object
/// NOTE: Collection has to be known to the transaction.
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> EdgeIdToData(
v8::Isolate* isolate, CollectionNameResolver const* resolver,
ExplicitTransaction* trx,
std::unordered_map<TRI_voc_cid_t, CollectionDitchInfo> const& ditches,
EdgeId const& edgeId) {
// EdgeId is a typedef of VertexId.
return VertexIdToData(isolate, resolver, trx, ditches, edgeId);
v8::Isolate* isolate,
Transaction* trx,
std::string const& edgeId) {
return VertexIdToData(isolate, trx, edgeId);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Extracts all touched collections from ArangoDBPathFinder::Path
////////////////////////////////////////////////////////////////////////////////
/*
static void ExtractCidsFromPath(TRI_vocbase_t* vocbase,
ArangoDBPathFinder::Path const& p,
std::vector<TRI_voc_cid_t>& result) {
@ -1842,7 +1840,7 @@ static void ExtractCidsFromPath(TRI_vocbase_t* vocbase,
}
}
}
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief Request a ditch for the given collection
////////////////////////////////////////////////////////////////////////////////
@ -1901,7 +1899,7 @@ static ExplicitTransaction* BeginTransaction(
////////////////////////////////////////////////////////////////////////////////
/// @brief Transforms an ArangoDBPathFinder::Path to v8 json values
////////////////////////////////////////////////////////////////////////////////
/*
static v8::Handle<v8::Value> PathIdsToV8(
v8::Isolate* isolate, TRI_vocbase_t* vocbase,
CollectionNameResolver const* resolver, ArangoDBPathFinder::Path const& p,
@ -1953,11 +1951,11 @@ static v8::Handle<v8::Value> PathIdsToV8(
return scope.Escape<v8::Value>(result);
}
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief Transforms an ConstDistanceFinder::Path to v8 json values
////////////////////////////////////////////////////////////////////////////////
/*
static v8::Handle<v8::Value> PathIdsToV8(
v8::Isolate* isolate, TRI_vocbase_t* vocbase,
CollectionNameResolver const* resolver,
@ -2010,6 +2008,7 @@ static v8::Handle<v8::Value> PathIdsToV8(
return scope.Escape<v8::Value>(result);
}
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief Extract collection names from v8 array.
@ -2039,7 +2038,7 @@ class HopWeightCalculator {
/// @brief Callable weight calculator for edge
//////////////////////////////////////////////////////////////////////////////
double operator()(TRI_doc_mptr_t& edge) { return 1; }
double operator()(VPackSlice const edge) { return 1; }
};
////////////////////////////////////////////////////////////////////////////////
@ -2048,35 +2047,27 @@ class HopWeightCalculator {
////////////////////////////////////////////////////////////////////////////////
class AttributeWeightCalculator {
std::string _attribute;
double _defaultWeight;
VocShaper* _shaper;
std::string const _attribute;
double const _defaultWeight;
public:
AttributeWeightCalculator(std::string const& attribute, double defaultWeight,
VocShaper* shaper)
: _attribute(attribute), _defaultWeight(defaultWeight), _shaper(shaper) {
}
AttributeWeightCalculator(std::string const& attribute, double defaultWeight)
: _attribute(attribute), _defaultWeight(defaultWeight) {}
//////////////////////////////////////////////////////////////////////////////
/// @brief Callable weight calculator for edge
//////////////////////////////////////////////////////////////////////////////
double operator()(TRI_doc_mptr_t const& edge) {
double operator()(VPackSlice const edge) {
if (_attribute.empty()) {
return _defaultWeight;
}
VPackSlice slice(edge.vpack());
if (!slice.isObject()) {
VPackSlice attr = edge.get(_attribute);
if (!attr.isNumber()) {
return _defaultWeight;
}
VPackSlice attribute = slice.get(_attribute);
if (!attribute.isNumber()) {
return _defaultWeight;
}
return attribute.getNumber<double>();
return attr.getNumericValue<double>();
}
};
@ -2086,6 +2077,12 @@ class AttributeWeightCalculator {
static void JS_QueryShortestPath(
v8::FunctionCallbackInfo<v8::Value> const& args) {
#warning Re-implement Shortest Path with new TRX and VPAck
TRI_V8_TRY_CATCH_BEGIN(isolate);
v8::HandleScope scope(isolate);
TRI_V8_THROW_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
TRI_V8_TRY_CATCH_END
/*
TRI_V8_TRY_CATCH_BEGIN(isolate);
v8::HandleScope scope(isolate);
@ -2377,6 +2374,7 @@ static void JS_QueryShortestPath(
}
}
TRI_V8_TRY_CATCH_END
*/
}
////////////////////////////////////////////////////////////////////////////////
@ -2385,7 +2383,7 @@ static void JS_QueryShortestPath(
static v8::Handle<v8::Value> VertexIdsToV8(
v8::Isolate* isolate, ExplicitTransaction* trx,
CollectionNameResolver const* resolver, std::unordered_set<VertexId>& ids,
CollectionNameResolver const* resolver, std::unordered_set<std::string>& ids,
std::unordered_map<TRI_voc_cid_t, CollectionDitchInfo>& ditches,
bool includeData = false) {
v8::EscapableHandleScope scope(isolate);
@ -2396,12 +2394,12 @@ static v8::Handle<v8::Value> VertexIdsToV8(
uint32_t j = 0;
if (includeData) {
for (auto& it : ids) {
vertices->Set(j, VertexIdToData(isolate, resolver, trx, ditches, it));
vertices->Set(j, VertexIdToData(isolate, trx, it));
++j;
}
} else {
for (auto& it : ids) {
vertices->Set(j, VertexIdToString(isolate, resolver, it));
vertices->Set(j, VertexIdToString(isolate, it));
++j;
}
}
@ -2562,10 +2560,8 @@ static void JS_QueryNeighbors(v8::FunctionCallbackInfo<v8::Value> const& args) {
}};
for (auto const& it : edgeCollectionNames) {
auto cid = resolver->getCollectionIdLocal(it);
TRI_document_collection_t* colObj = ditches.find(cid)->second.col;
edgeCollectionInfos.emplace_back(
new EdgeCollectionInfo(trx.get(), cid, colObj, HopWeightCalculator()));
new EdgeCollectionInfo(trx.get(), it, HopWeightCalculator()));
TRI_IF_FAILURE("EdgeCollectionDitchOOM") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
@ -2582,14 +2578,13 @@ static void JS_QueryNeighbors(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
}
std::unordered_set<VertexId> neighbors;
std::unordered_set<std::string> neighbors;
if (opts.useEdgeFilter) {
std::string errorMessage;
for (auto const& it : edgeCollectionInfos) {
try {
opts.addEdgeFilter(isolate, edgeExample, it->getShaper(), it->getCid(),
errorMessage);
opts.addEdgeFilter(isolate, edgeExample, it->getName(), errorMessage);
} catch (Exception& e) {
// ELEMENT not found is expected, if there is no shape of this type in
// this collection
@ -2618,13 +2613,7 @@ static void JS_QueryNeighbors(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
for (auto const& startVertex : startVertices) {
try {
opts.start = IdStringToVertexId(resolver, startVertex);
} catch (Exception& e) {
// Id string might have illegal collection name
trx->finish(e.code());
TRI_V8_THROW_EXCEPTION(e.code());
}
opts.start = startVertex;
try {
TRI_RunNeighborsSearch(edgeCollectionInfos, opts, neighbors);
} catch (Exception& e) {

View File

@ -140,30 +140,39 @@ class TraversalPath {
virtual ~TraversalPath() {}
//////////////////////////////////////////////////////////////////////////////
/// @brief Builds the complete path as Json
/// @brief Builds the complete path as VelocyPack
/// Has the format:
/// {
/// vertices: [<vertex-as-json>],
/// edges: [<edge-as-json>]
/// vertices: [<vertex-as-velocypack>],
/// edges: [<edge-as-velocypack>]
/// }
//////////////////////////////////////////////////////////////////////////////
virtual void pathToVelocyPack(Transaction*,
arangodb::velocypack::Builder&) = 0;
virtual arangodb::basics::Json* pathToJson(Transaction*,
CollectionNameResolver*) = 0;
CollectionNameResolver*) { return nullptr;}
//////////////////////////////////////////////////////////////////////////////
/// @brief Builds only the last edge on the path as Json
/// @brief Builds only the last edge on the path as VelocyPack
//////////////////////////////////////////////////////////////////////////////
virtual void lastEdgeToVelocyPack(Transaction*,
arangodb::velocypack::Builder&) = 0;
virtual arangodb::basics::Json* lastEdgeToJson(Transaction*,
CollectionNameResolver*) = 0;
CollectionNameResolver*) { return nullptr;}
//////////////////////////////////////////////////////////////////////////////
/// @brief Builds only the last vertex as Json
/// @brief Builds only the last vertex as VelocyPack
//////////////////////////////////////////////////////////////////////////////
virtual void lastVertexToVelocyPack(Transaction*,
arangodb::velocypack::Builder&) = 0;
virtual arangodb::basics::Json* lastVertexToJson(Transaction*,
CollectionNameResolver*) = 0;
CollectionNameResolver*) { return nullptr;}
//////////////////////////////////////////////////////////////////////////////
/// @brief Gets the amount of read documents

View File

@ -435,7 +435,7 @@ class PathFinder {
Step() : _done(false) {}
Step(VertexId& vert, VertexId& pred, EdgeWeight weig, EdgeId const& edge)
Step(VertexId const& vert, VertexId const& pred, EdgeWeight weig, EdgeId const& edge)
: _weight(weig),
_vertex(vert),
_predecessor(pred),
@ -459,14 +459,14 @@ class PathFinder {
/// @brief callback to find neighbours
//////////////////////////////////////////////////////////////////////////////
typedef std::function<void(VertexId& V, std::vector<Step*>& result)>
typedef std::function<void(std::string const&, std::vector<Step*>&)>
ExpanderFunction;
//////////////////////////////////////////////////////////////////////////////
/// @brief our specialization of the priority queue
//////////////////////////////////////////////////////////////////////////////
typedef arangodb::basics::PriorityQueue<VertexId, Step, EdgeWeight> PQueue;
typedef arangodb::basics::PriorityQueue<std::string, Step, EdgeWeight> PQueue;
//////////////////////////////////////////////////////////////////////////////
/// @brief information for each thread
@ -818,7 +818,7 @@ class PathFinder {
_bingo = false;
// Forward with initialization:
VertexId emptyVertex(0, "");
VertexId emptyVertex;
EdgeId emptyEdge;
ThreadInfo forward;
forward._pq.insert(start, new Step(start, emptyVertex, 0, emptyEdge));
@ -859,8 +859,7 @@ class PathFinder {
// FORWARD Go path back from intermediate -> start.
// Insert all vertices and edges at front of vector
// Do NOT! insert the intermediate vertex
while (s->_predecessor.key != nullptr &&
strcmp(s->_predecessor.key, "") != 0) {
while (!s->_predecessor.empty()) {
r_edges.push_front(s->_edge);
r_vertices.push_front(s->_predecessor);
s = forward._pq.find(s->_predecessor);
@ -870,9 +869,7 @@ class PathFinder {
// Insert all vertices and edges at back of vector
// Also insert the intermediate vertex
s = backward._pq.find(_intermediate);
while (s->_predecessor.key != nullptr &&
strcmp(s->_predecessor.key, "") != 0) {
r_edges.emplace_back(s->_edge);
while (!s->_predecessor.empty()) {
r_vertices.emplace_back(s->_predecessor);
s = backward._pq.find(s->_predecessor);
}
@ -950,8 +947,7 @@ class PathFinder {
// FORWARD Go path back from intermediate -> start.
// Insert all vertices and edges at front of vector
// Do NOT! insert the intermediate vertex
while (s->_predecessor.key != nullptr &&
strcmp(s->_predecessor.key, "") != 0) {
while (!s->_predecessor.empty()) {
r_edges.push_front(s->_edge);
r_vertices.push_front(s->_predecessor);
s = forward._pq.find(s->_predecessor);
@ -961,8 +957,7 @@ class PathFinder {
// Insert all vertices and edges at back of vector
// Also insert the intermediate vertex
s = backward._pq.find(_intermediate);
while (s->_predecessor.key != nullptr &&
strcmp(s->_predecessor.key, "") != 0) {
while (!s->_predecessor.empty()) {
r_edges.emplace_back(s->_edge);
r_vertices.emplace_back(s->_predecessor);
s = backward._pq.find(s->_predecessor);