mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'spdvpk' of ssh://github.com/ArangoDB/ArangoDB into spdvpk
This commit is contained in:
commit
3ed256a478
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue