mirror of https://gitee.com/bigwinds/arangodb
Started implementing the Expander function. Not et finished does not compile but i am moving over to a new machine
This commit is contained in:
parent
015c197e2a
commit
9f1830b4c5
|
@ -106,6 +106,7 @@ arangod_libarangod_a_SOURCES = \
|
||||||
arangod/V8Server/V8PeriodicTask.cpp \
|
arangod/V8Server/V8PeriodicTask.cpp \
|
||||||
arangod/V8Server/V8QueueJob.cpp \
|
arangod/V8Server/V8QueueJob.cpp \
|
||||||
arangod/V8Server/V8TimerTask.cpp \
|
arangod/V8Server/V8TimerTask.cpp \
|
||||||
|
arangod/V8Server/V8Traverser.cpp \
|
||||||
arangod/V8Server/v8-actions.cpp \
|
arangod/V8Server/v8-actions.cpp \
|
||||||
arangod/V8Server/v8-collection.cpp \
|
arangod/V8Server/v8-collection.cpp \
|
||||||
arangod/V8Server/v8-collection-util.cpp \
|
arangod/V8Server/v8-collection-util.cpp \
|
||||||
|
|
|
@ -0,0 +1,300 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief V8 Traverser
|
||||||
|
///
|
||||||
|
/// @file
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
|
||||||
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Michael Hackstein
|
||||||
|
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
|
||||||
|
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "v8.h"
|
||||||
|
#include "V8/v8-conv.h"
|
||||||
|
#include "V8/v8-utils.h"
|
||||||
|
#include "V8Server/v8-vocbaseprivate.h"
|
||||||
|
#include "V8Server/v8-wrapshapedjson.h"
|
||||||
|
#include "V8Server/v8-vocindex.h"
|
||||||
|
#include "V8Server/v8-collection.h"
|
||||||
|
#include "Utils/transactions.h"
|
||||||
|
#include "Utils/V8ResolverGuard.h"
|
||||||
|
#include "Utils/CollectionNameResolver.h"
|
||||||
|
#include "Traverser.h"
|
||||||
|
#include "VocBase/key-generator.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace triagens::basics;
|
||||||
|
using namespace triagens::arango;
|
||||||
|
|
||||||
|
class SimpleEdgeExpander {
|
||||||
|
|
||||||
|
private:
|
||||||
|
TRI_edge_direction_e forwardDirection;
|
||||||
|
TRI_edge_direction_e backwardDirection;
|
||||||
|
TRI_document_collection_t* edgeCollection;
|
||||||
|
CollectionNameResolver const* resolver;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void operator() ( Traverser::VertexId source,
|
||||||
|
Traverser::Direction dir,
|
||||||
|
vector<Traverser::Neighbor>& result
|
||||||
|
) {
|
||||||
|
std::vector<TRI_doc_mptr_copy_t> edges;
|
||||||
|
// Process Vertex Id!
|
||||||
|
size_t split;
|
||||||
|
char const* str = source.c_str();
|
||||||
|
if (!TRI_ValidateDocumentIdKeyGenerator(str, &split)) {
|
||||||
|
// TODO Error Handling
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::unique_ptr<char[]>& key;
|
||||||
|
string& collectionName = string(str, split);
|
||||||
|
auto const length = str->length() - split - 1;
|
||||||
|
auto buffer = new char[length + 1];
|
||||||
|
memcpy(buffer, *str + split + 1, length);
|
||||||
|
buffer[length] = '\0';
|
||||||
|
key.reset(buffer);
|
||||||
|
|
||||||
|
auto col = resolver->getCollectionStruct(collectionName);
|
||||||
|
if (col == nullptr) {
|
||||||
|
// collection not found
|
||||||
|
throw TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||||
|
}
|
||||||
|
auto collectionCId = col->_cid;
|
||||||
|
if (dir == Traverser::FORWARD) {
|
||||||
|
edges = TRI_LookupEdgesDocumentCollection(edgeCollection, forwardDirection, collectionCId, key.get());
|
||||||
|
} else {
|
||||||
|
edges = TRI_LookupEdgesDocumentCollection(edgeCollection, backwardDirection, collectionCId, key.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Build result
|
||||||
|
}
|
||||||
|
SimpleEdgeExpander(
|
||||||
|
TRI_edge_direction_e edgeDirection,
|
||||||
|
TRI_document_collection_t* edgeCollection,
|
||||||
|
CollectionNameResolver const* resolver
|
||||||
|
) :
|
||||||
|
edgeCollection(edgeCollection),
|
||||||
|
resolver(resolver)
|
||||||
|
{
|
||||||
|
if (edgeDirection == TRI_EDGE_OUT) {
|
||||||
|
forwardDirection = TRI_EDGE_OUT;
|
||||||
|
backwardDirection = TRI_EDGE_IN;
|
||||||
|
} else if (edgeDirection == TRI_EDGE_IN) {
|
||||||
|
forwardDirection = TRI_EDGE_IN;
|
||||||
|
backwardDirection = TRI_EDGE_OUT;
|
||||||
|
} else {
|
||||||
|
forwardDirection = TRI_EDGE_ANY;
|
||||||
|
backwardDirection = TRI_EDGE_ANY;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct LocalCollectionGuard {
|
||||||
|
LocalCollectionGuard (TRI_vocbase_col_t* collection)
|
||||||
|
: _collection(collection) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~LocalCollectionGuard () {
|
||||||
|
if (_collection != nullptr && ! _collection->_isLocal) {
|
||||||
|
FreeCoordinatorCollection(_collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_vocbase_col_t* _collection;
|
||||||
|
};
|
||||||
|
|
||||||
|
void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||||
|
v8::Isolate* isolate = args.GetIsolate();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
|
||||||
|
if (args.Length() < 4 || args.Length() > 5) {
|
||||||
|
TRI_V8_THROW_EXCEPTION_USAGE("AQL_SHORTEST_PATH(<vertexcollection>, <edgecollection>, <start>, <end>, <options>)");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<char[]> key;
|
||||||
|
TRI_vocbase_t* vocbase;
|
||||||
|
TRI_vocbase_col_t const* col = nullptr;
|
||||||
|
|
||||||
|
vocbase = GetContextVocBase(isolate);
|
||||||
|
|
||||||
|
vector<string> readCollections;
|
||||||
|
vector<string> writeCollections;
|
||||||
|
TRI_voc_cid_t vertexCollectionCId;
|
||||||
|
TRI_voc_cid_t edgeCollectionCId;
|
||||||
|
TRI_voc_rid_t rid;
|
||||||
|
|
||||||
|
double lockTimeout = (double) (TRI_TRANSACTION_DEFAULT_LOCK_TIMEOUT / 1000000ULL);
|
||||||
|
bool embed = false;
|
||||||
|
bool waitForSync = false;
|
||||||
|
|
||||||
|
// get the vertex collection
|
||||||
|
if (! args[0]->IsString()) {
|
||||||
|
TRI_V8_THROW_TYPE_ERROR("expecting string for <vertexcollection>");
|
||||||
|
}
|
||||||
|
string vertexCollectionName = TRI_ObjectToString(args[0]);
|
||||||
|
|
||||||
|
// get the edge collection
|
||||||
|
if (! args[1]->IsString()) {
|
||||||
|
TRI_V8_THROW_TYPE_ERROR("expecting string for <edgecollection>");
|
||||||
|
}
|
||||||
|
string const edgeCollectionName = TRI_ObjectToString(args[1]);
|
||||||
|
|
||||||
|
vocbase = GetContextVocBase(isolate);
|
||||||
|
|
||||||
|
if (vocbase == nullptr) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
V8ResolverGuard resolver(vocbase);
|
||||||
|
|
||||||
|
readCollections.push_back(vertexCollectionName);
|
||||||
|
readCollections.push_back(edgeCollectionName);
|
||||||
|
|
||||||
|
if (! args[2]->IsString()) {
|
||||||
|
TRI_V8_THROW_TYPE_ERROR("expecting string for <startVertex>");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string vertexColName;
|
||||||
|
|
||||||
|
if (! ExtractDocumentHandle(isolate, args[2], vertexColName, key, rid)) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.get() == nullptr) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_ASSERT(key.get() != nullptr);
|
||||||
|
|
||||||
|
// IHHF isCoordinator
|
||||||
|
|
||||||
|
// Start Transaction to collect all parts of the path
|
||||||
|
ExplicitTransaction trx(
|
||||||
|
vocbase,
|
||||||
|
readCollections,
|
||||||
|
writeCollections,
|
||||||
|
lockTimeout,
|
||||||
|
waitForSync,
|
||||||
|
embed
|
||||||
|
);
|
||||||
|
|
||||||
|
int res = trx.begin();
|
||||||
|
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
col = resolver.getResolver()->getCollectionStruct(vertexCollectionName);
|
||||||
|
if (col == nullptr) {
|
||||||
|
// collection not found
|
||||||
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||||
|
}
|
||||||
|
vertexCollectionCId = col->_cid;
|
||||||
|
if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
|
||||||
|
TRI_V8_THROW_EXCEPTION_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
col = resolver.getResolver()->getCollectionStruct(edgeCollectionName);
|
||||||
|
if (col == nullptr) {
|
||||||
|
// collection not found
|
||||||
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||||
|
}
|
||||||
|
edgeCollectionCId = col->_cid;
|
||||||
|
if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
|
||||||
|
TRI_V8_THROW_EXCEPTION_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Handle<v8::Value> result;
|
||||||
|
v8::Handle<v8::Array> documents;
|
||||||
|
|
||||||
|
// This is how to get the data out of the collections!
|
||||||
|
// Vertices
|
||||||
|
TRI_doc_mptr_copy_t document;
|
||||||
|
res = trx.readSingle(trx.trxCollection(vertexCollectionCId), &document, key.get());
|
||||||
|
|
||||||
|
// Edges TRI_EDGE_OUT is hardcoded
|
||||||
|
TRI_document_collection_t* ecol = trx.trxCollection(edgeCollectionCId)->_collection->_collection;
|
||||||
|
std::vector<TRI_doc_mptr_copy_t>&& edges = TRI_LookupEdgesDocumentCollection(ecol, TRI_EDGE_OUT, vertexCollectionCId, key.get());
|
||||||
|
|
||||||
|
// Add Dijkstra here
|
||||||
|
|
||||||
|
// Now build up the result use Subtransactions for each used collection
|
||||||
|
if (res == TRI_ERROR_NO_ERROR) {
|
||||||
|
{
|
||||||
|
// Collect all vertices
|
||||||
|
SingleCollectionReadOnlyTransaction subtrx(new V8TransactionContext(true), vocbase, vertexCollectionCId);
|
||||||
|
|
||||||
|
res = subtrx.begin();
|
||||||
|
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = TRI_WrapShapedJson(isolate, subtrx, vertexCollectionCId, document.getDataPtr());
|
||||||
|
|
||||||
|
if (document.getDataPtr() == nullptr) {
|
||||||
|
res = TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
|
||||||
|
TRI_V8_THROW_EXCEPTION(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = subtrx.finish(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Collect all edges
|
||||||
|
SingleCollectionReadOnlyTransaction subtrx2(new V8TransactionContext(true), vocbase, edgeCollectionCId);
|
||||||
|
|
||||||
|
res = subtrx2.begin();
|
||||||
|
|
||||||
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
|
TRI_V8_THROW_EXCEPTION(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
uint32_t const n = static_cast<uint32_t>(edges.size());
|
||||||
|
documents = v8::Array::New(isolate, static_cast<int>(n));
|
||||||
|
for (size_t j = 0; j < n; ++j) {
|
||||||
|
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(isolate, subtrx2, edgeCollectionCId, edges[j].getDataPtr());
|
||||||
|
|
||||||
|
if (doc.IsEmpty()) {
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
documents->Set(static_cast<uint32_t>(j), doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
TRI_V8_THROW_EXCEPTION_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
res = subtrx2.finish(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = trx.finish(res);
|
||||||
|
|
||||||
|
// Not yet correct. Needs to build an object first.
|
||||||
|
// TRI_V8_RETURN(result);
|
||||||
|
TRI_V8_RETURN(documents);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief V8 Traverser
|
||||||
|
///
|
||||||
|
/// @file
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
|
||||||
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Michael Hackstein
|
||||||
|
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
|
||||||
|
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
#include "Wal/LogfileManager.h"
|
#include "Wal/LogfileManager.h"
|
||||||
|
|
||||||
#include "VocBase/auth.h"
|
#include "VocBase/auth.h"
|
||||||
#include "VocBase/traversal.h"
|
|
||||||
#include "v8.h"
|
#include "v8.h"
|
||||||
#include "V8/JSLoader.h"
|
#include "V8/JSLoader.h"
|
||||||
|
|
||||||
|
@ -1483,7 +1482,7 @@ static void JS_QueryIsKilledAql (const v8::FunctionCallbackInfo<v8::Value>& args
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void JS_QueryShortestPath (const v8::FunctionCallbackInfo<v8::Value>& args) {
|
static void JS_QueryShortestPath (const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||||
TRI_RunDijkstraSearch(args);
|
// TRI_RunDijkstraSearch(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,20 +28,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "Traverser.h"
|
#include "Traverser.h"
|
||||||
|
#include <thread>
|
||||||
/*
|
|
||||||
#include "v8.h"
|
|
||||||
#include "V8/v8-conv.h"
|
|
||||||
#include "V8/v8-utils.h"
|
|
||||||
#include "V8Server/v8-vocbaseprivate.h"
|
|
||||||
#include "V8Server/v8-wrapshapedjson.h"
|
|
||||||
#include "V8Server/v8-vocindex.h"
|
|
||||||
#include "V8Server/v8-collection.h"
|
|
||||||
#include "Utils/transactions.h"
|
|
||||||
#include "Utils/V8ResolverGuard.h"
|
|
||||||
|
|
||||||
using namespace triagens::arango;
|
|
||||||
*/
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace triagens::basics;
|
using namespace triagens::basics;
|
||||||
|
@ -100,21 +87,33 @@ void Traverser::lookupPeer (ThreadInfo& info,
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void Traverser::searchFromVertex (
|
void Traverser::searchFromVertex (
|
||||||
ThreadInfo& myInfo,
|
ThreadInfo myInfo,
|
||||||
ThreadInfo& peerInfo,
|
ThreadInfo peerInfo,
|
||||||
VertexId start,
|
VertexId start,
|
||||||
Direction dir
|
Direction dir
|
||||||
) {
|
) {
|
||||||
insertNeighbor(myInfo, start, nullptr, nullptr, 0);
|
insertNeighbor(myInfo, start, "", "", 0);
|
||||||
auto nextVertex = myInfo.queue.begin();
|
auto nextVertex = myInfo.queue.begin();
|
||||||
|
std::vector<Neighbor> neighbors;
|
||||||
|
|
||||||
// Iterate while no bingo found and
|
// Iterate while no bingo found and
|
||||||
// there still is a vertex on the stack.
|
// there still is a vertex on the stack.
|
||||||
while (!bingo && nextVertex != myInfo.queue.end()) {
|
while (!bingo && nextVertex != myInfo.queue.end()) {
|
||||||
myInfo.queue.erase(nextVertex);
|
myInfo.queue.erase(nextVertex);
|
||||||
|
_neighborFunction(nextVertex->vertex, dir, neighbors);
|
||||||
|
for (auto neighbor : neighbors) {
|
||||||
|
insertNeighbor(myInfo, neighbor.neighbor, nextVertex->vertex,
|
||||||
|
neighbor.edge, nextVertex->weight + neighbor.weight);
|
||||||
|
}
|
||||||
|
lookupPeer(peerInfo, nextVertex->vertex, nextVertex->weight);
|
||||||
|
myInfo.mutex.lock();
|
||||||
|
// Can move nextVertexLookup up?
|
||||||
|
auto nextVertexLookup = myInfo.lookup.find(nextVertex->vertex);
|
||||||
|
nextVertexLookup->second.done = true;
|
||||||
|
myInfo.mutex.unlock();
|
||||||
nextVertex = myInfo.queue.begin();
|
nextVertex = myInfo.queue.begin();
|
||||||
}
|
}
|
||||||
|
// No possible path, can possibly terminate other thread
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -122,204 +121,57 @@ void Traverser::searchFromVertex (
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Traverser::Path* Traverser::ShortestPath (VertexId const& start,
|
Traverser::Path* Traverser::ShortestPath (VertexId const& start,
|
||||||
VertexId const& target,
|
VertexId const& target) {
|
||||||
Direction direction) {
|
|
||||||
|
|
||||||
return nullptr;
|
std::vector<VertexId> r_vertices;
|
||||||
|
std::vector<VertexId> r_edges;
|
||||||
|
highscore = 1e50;
|
||||||
|
|
||||||
|
// Forward
|
||||||
|
_forwardLookup.clear();
|
||||||
|
_forwardQueue.clear();
|
||||||
|
ThreadInfo forwardInfo(_forwardLookup, _forwardQueue, _forwardMutex);
|
||||||
|
|
||||||
|
_backwardLookup.clear();
|
||||||
|
_backwardQueue.clear();
|
||||||
|
ThreadInfo backwardInfo(_backwardLookup, _backwardQueue, _backwardMutex);
|
||||||
|
|
||||||
|
std::thread forwardSearcher(&Traverser::searchFromVertex,
|
||||||
|
this, forwardInfo, backwardInfo, start, FORWARD);
|
||||||
|
std::thread backwardSearcher(&Traverser::searchFromVertex,
|
||||||
|
this, backwardInfo, forwardInfo, target, BACKWARD);
|
||||||
|
forwardSearcher.join();
|
||||||
|
backwardSearcher.join();
|
||||||
|
|
||||||
|
// TODO Return result
|
||||||
|
if (!bingo) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pathLookup = _forwardLookup.find(intermediate);
|
||||||
|
// FORWARD Go path back from intermediate -> start.
|
||||||
|
// Insert all vertices and edges at front of vector
|
||||||
|
// Do NOT! insert the intermediate vertex
|
||||||
|
do {
|
||||||
|
r_edges.insert(r_edges.begin(), pathLookup->second.edge);
|
||||||
|
r_vertices.insert(r_vertices.begin(), pathLookup->first);
|
||||||
|
pathLookup = _forwardLookup.find(pathLookup->second.predecessor);
|
||||||
|
} while (pathLookup->second.predecessor != "");
|
||||||
|
r_vertices.insert(r_vertices.begin(), pathLookup->first);
|
||||||
|
|
||||||
|
// BACKWARD Go path back from intermediate -> target.
|
||||||
|
// Insert all vertices and edges at back of vector
|
||||||
|
// Also insert the intermediate vertex
|
||||||
|
pathLookup = _backwardLookup.find(intermediate);
|
||||||
|
r_vertices.push_back(intermediate);
|
||||||
|
r_edges.push_back(pathLookup->second.edge);
|
||||||
|
pathLookup = _backwardLookup.find(pathLookup->second.predecessor);
|
||||||
|
while (pathLookup->second.predecessor != "") {
|
||||||
|
r_vertices.push_back(pathLookup->first);
|
||||||
|
r_edges.push_back(pathLookup->second.edge);
|
||||||
|
pathLookup = _backwardLookup.find(pathLookup->second.predecessor);
|
||||||
|
}
|
||||||
|
r_vertices.push_back(pathLookup->first);
|
||||||
|
Path* res = new Path(r_vertices, r_edges, highscore);
|
||||||
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct LocalCollectionGuard {
|
|
||||||
LocalCollectionGuard (TRI_vocbase_col_t* collection)
|
|
||||||
: _collection(collection) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~LocalCollectionGuard () {
|
|
||||||
if (_collection != nullptr && ! _collection->_isLocal) {
|
|
||||||
FreeCoordinatorCollection(_collection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_vocbase_col_t* _collection;
|
|
||||||
};
|
|
||||||
|
|
||||||
void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
||||||
v8::Isolate* isolate = args.GetIsolate();
|
|
||||||
v8::HandleScope scope(isolate);
|
|
||||||
|
|
||||||
if (args.Length() < 4 || args.Length() > 5) {
|
|
||||||
TRI_V8_THROW_EXCEPTION_USAGE("AQL_SHORTEST_PATH(<vertexcollection>, <edgecollection>, <start>, <end>, <options>)");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<char[]> key;
|
|
||||||
TRI_vocbase_t* vocbase;
|
|
||||||
TRI_vocbase_col_t const* col = nullptr;
|
|
||||||
|
|
||||||
vocbase = GetContextVocBase(isolate);
|
|
||||||
|
|
||||||
vector<string> readCollections;
|
|
||||||
vector<string> writeCollections;
|
|
||||||
TRI_voc_cid_t vertexCollectionCId;
|
|
||||||
TRI_voc_cid_t edgeCollectionCId;
|
|
||||||
TRI_voc_rid_t rid;
|
|
||||||
|
|
||||||
double lockTimeout = (double) (TRI_TRANSACTION_DEFAULT_LOCK_TIMEOUT / 1000000ULL);
|
|
||||||
bool embed = false;
|
|
||||||
bool waitForSync = false;
|
|
||||||
|
|
||||||
// get the vertex collection
|
|
||||||
if (! args[0]->IsString()) {
|
|
||||||
TRI_V8_THROW_TYPE_ERROR("expecting string for <vertexcollection>");
|
|
||||||
}
|
|
||||||
string vertexCollectionName = TRI_ObjectToString(args[0]);
|
|
||||||
|
|
||||||
// get the edge collection
|
|
||||||
if (! args[1]->IsString()) {
|
|
||||||
TRI_V8_THROW_TYPE_ERROR("expecting string for <edgecollection>");
|
|
||||||
}
|
|
||||||
string const edgeCollectionName = TRI_ObjectToString(args[1]);
|
|
||||||
|
|
||||||
vocbase = GetContextVocBase(isolate);
|
|
||||||
|
|
||||||
if (vocbase == nullptr) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
|
||||||
}
|
|
||||||
V8ResolverGuard resolver(vocbase);
|
|
||||||
|
|
||||||
readCollections.push_back(vertexCollectionName);
|
|
||||||
readCollections.push_back(edgeCollectionName);
|
|
||||||
|
|
||||||
if (! args[2]->IsString()) {
|
|
||||||
TRI_V8_THROW_TYPE_ERROR("expecting string for <startVertex>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string vertexColName;
|
|
||||||
|
|
||||||
if (! ExtractDocumentHandle(isolate, args[2], vertexColName, key, rid)) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.get() == nullptr) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_ASSERT(key.get() != nullptr);
|
|
||||||
|
|
||||||
// IHHF isCoordinator
|
|
||||||
|
|
||||||
// Start Transaction to collect all parts of the path
|
|
||||||
ExplicitTransaction trx(
|
|
||||||
vocbase,
|
|
||||||
readCollections,
|
|
||||||
writeCollections,
|
|
||||||
lockTimeout,
|
|
||||||
waitForSync,
|
|
||||||
embed
|
|
||||||
);
|
|
||||||
|
|
||||||
int res = trx.begin();
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
col = resolver.getResolver()->getCollectionStruct(vertexCollectionName);
|
|
||||||
if (col == nullptr) {
|
|
||||||
// collection not found
|
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
|
||||||
}
|
|
||||||
vertexCollectionCId = col->_cid;
|
|
||||||
if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
|
|
||||||
TRI_V8_THROW_EXCEPTION_MEMORY();
|
|
||||||
}
|
|
||||||
|
|
||||||
col = resolver.getResolver()->getCollectionStruct(edgeCollectionName);
|
|
||||||
if (col == nullptr) {
|
|
||||||
// collection not found
|
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
|
||||||
}
|
|
||||||
edgeCollectionCId = col->_cid;
|
|
||||||
if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
|
|
||||||
TRI_V8_THROW_EXCEPTION_MEMORY();
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::Handle<v8::Value> result;
|
|
||||||
v8::Handle<v8::Array> documents;
|
|
||||||
|
|
||||||
// This is how to get the data out of the collections!
|
|
||||||
// Vertices
|
|
||||||
TRI_doc_mptr_copy_t document;
|
|
||||||
res = trx.readSingle(trx.trxCollection(vertexCollectionCId), &document, key.get());
|
|
||||||
|
|
||||||
// Edges TRI_EDGE_OUT is hardcoded
|
|
||||||
TRI_document_collection_t * ecol = trx.trxCollection(edgeCollectionCId)->_collection->_collection;
|
|
||||||
std::cout << key.get() << "\n";
|
|
||||||
std::vector<TRI_doc_mptr_copy_t>&& edges = TRI_LookupEdgesDocumentCollection(ecol, TRI_EDGE_OUT, vertexCollectionCId, key.get());
|
|
||||||
|
|
||||||
// Add Dijkstra here
|
|
||||||
|
|
||||||
// Now build up the result use Subtransactions for each used collection
|
|
||||||
if (res == TRI_ERROR_NO_ERROR) {
|
|
||||||
{
|
|
||||||
// Collect all vertices
|
|
||||||
SingleCollectionReadOnlyTransaction subtrx(new V8TransactionContext(true), vocbase, vertexCollectionCId);
|
|
||||||
|
|
||||||
res = subtrx.begin();
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = TRI_WrapShapedJson(isolate, subtrx, vertexCollectionCId, document.getDataPtr());
|
|
||||||
|
|
||||||
if (document.getDataPtr() == nullptr) {
|
|
||||||
res = TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
|
|
||||||
TRI_V8_THROW_EXCEPTION(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = subtrx.finish(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Collect all edges
|
|
||||||
SingleCollectionReadOnlyTransaction subtrx2(new V8TransactionContext(true), vocbase, edgeCollectionCId);
|
|
||||||
|
|
||||||
res = subtrx2.begin();
|
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
|
||||||
TRI_V8_THROW_EXCEPTION(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool error = false;
|
|
||||||
|
|
||||||
uint32_t const n = static_cast<uint32_t>(edges.size());
|
|
||||||
documents = v8::Array::New(isolate, static_cast<int>(n));
|
|
||||||
for (size_t j = 0; j < n; ++j) {
|
|
||||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(isolate, subtrx2, edgeCollectionCId, edges[j].getDataPtr());
|
|
||||||
|
|
||||||
if (doc.IsEmpty()) {
|
|
||||||
error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
documents->Set(static_cast<uint32_t>(j), doc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error) {
|
|
||||||
TRI_V8_THROW_EXCEPTION_MEMORY();
|
|
||||||
}
|
|
||||||
|
|
||||||
res = subtrx2.finish(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res = trx.finish(res);
|
|
||||||
|
|
||||||
// Not yet correct. Needs to build an object first.
|
|
||||||
// TRI_V8_RETURN(result);
|
|
||||||
TRI_V8_RETURN(documents);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef ARANGODB_VOC_BASE_TRAVERSAL_H
|
#ifndef ARANGODB_TRAVERSAL_H
|
||||||
#define ARANGODB_VOC_BASE_TRAVERSAL_H 1
|
#define ARANGODB_TRAVERSAL_H 1
|
||||||
|
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
|
|
||||||
|
@ -61,12 +61,30 @@ namespace triagens {
|
||||||
std::vector<VertexId> vertices;
|
std::vector<VertexId> vertices;
|
||||||
std::vector<EdgeId> edges;
|
std::vector<EdgeId> edges;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
|
|
||||||
|
Path (
|
||||||
|
std::vector<VertexId> vertices,
|
||||||
|
std::vector<EdgeId> edges,
|
||||||
|
EdgeWeight weight
|
||||||
|
) : vertices(vertices),
|
||||||
|
edges(edges),
|
||||||
|
weight(weight) {
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Neighbor {
|
struct Neighbor {
|
||||||
VertexId neighbor;
|
VertexId neighbor;
|
||||||
EdgeId edge;
|
EdgeId edge;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
|
|
||||||
|
Neighbor (
|
||||||
|
VertexId neighbor,
|
||||||
|
EdgeId edge,
|
||||||
|
EdgeWeight weight
|
||||||
|
) : neighbor(neighbor),
|
||||||
|
edge(edge),
|
||||||
|
weight(weight) {
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -75,7 +93,7 @@ namespace triagens {
|
||||||
typedef enum {FORWARD, BACKWARD} Direction;
|
typedef enum {FORWARD, BACKWARD} Direction;
|
||||||
|
|
||||||
typedef std::function<void(VertexId source, Direction dir, std::vector<Neighbor>& result)>
|
typedef std::function<void(VertexId source, Direction dir, std::vector<Neighbor>& result)>
|
||||||
NeighborFunction;
|
ExpanderFunction;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- constructors and destructors
|
// --SECTION-- constructors and destructors
|
||||||
|
@ -85,7 +103,7 @@ namespace triagens {
|
||||||
/// @brief create the Traverser
|
/// @brief create the Traverser
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Traverser (NeighborFunction const& n) : _neighborFunction(n) {
|
Traverser (ExpanderFunction const& n) : _neighborFunction(n) {
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -109,8 +127,7 @@ namespace triagens {
|
||||||
// nullptr indicates there is no path
|
// nullptr indicates there is no path
|
||||||
Path* ShortestPath (
|
Path* ShortestPath (
|
||||||
VertexId const& start,
|
VertexId const& start,
|
||||||
VertexId const& target,
|
VertexId const& target
|
||||||
Direction direction
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -155,11 +172,11 @@ namespace triagens {
|
||||||
vertex(vertex) {
|
vertex(vertex) {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator< (QueueInfo const& a) {
|
friend bool operator< (QueueInfo const& a, QueueInfo const& b) {
|
||||||
if (weight == a.weight) {
|
if (a.weight == b.weight) {
|
||||||
return vertex < a.vertex;
|
return a.vertex < b.vertex;
|
||||||
}
|
}
|
||||||
return weight < a.weight;
|
return a.weight < b.weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -169,11 +186,21 @@ namespace triagens {
|
||||||
std::unordered_map<VertexId, LookupInfo>& lookup;
|
std::unordered_map<VertexId, LookupInfo>& lookup;
|
||||||
std::set<QueueInfo, std::less<QueueInfo>>& queue;
|
std::set<QueueInfo, std::less<QueueInfo>>& queue;
|
||||||
std::mutex& mutex;
|
std::mutex& mutex;
|
||||||
|
|
||||||
|
ThreadInfo (
|
||||||
|
std::unordered_map<VertexId, LookupInfo>& lookup,
|
||||||
|
std::set<QueueInfo, std::less<QueueInfo>>& queue,
|
||||||
|
std::mutex& mutex
|
||||||
|
) : lookup(lookup),
|
||||||
|
queue(queue),
|
||||||
|
mutex(mutex) {
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
NeighborFunction const& _neighborFunction;
|
ExpanderFunction const& _neighborFunction;
|
||||||
|
|
||||||
|
// Are they needed anyway??
|
||||||
// ShortestPath will create these variables
|
// ShortestPath will create these variables
|
||||||
std::unordered_map<VertexId, LookupInfo> _forwardLookup;
|
std::unordered_map<VertexId, LookupInfo> _forwardLookup;
|
||||||
std::set<QueueInfo, std::less<QueueInfo>> _forwardQueue;
|
std::set<QueueInfo, std::less<QueueInfo>> _forwardQueue;
|
||||||
|
@ -195,8 +222,8 @@ namespace triagens {
|
||||||
VertexId neighbor,
|
VertexId neighbor,
|
||||||
EdgeWeight weight
|
EdgeWeight weight
|
||||||
);
|
);
|
||||||
void searchFromVertex ( ThreadInfo& myInfo,
|
void searchFromVertex ( ThreadInfo myInfo,
|
||||||
ThreadInfo& peerInfo,
|
ThreadInfo peerInfo,
|
||||||
VertexId start,
|
VertexId start,
|
||||||
Direction dir
|
Direction dir
|
||||||
);
|
);
|
||||||
|
|
|
@ -93,6 +93,7 @@ add_library(
|
||||||
Basics/Thread.cpp
|
Basics/Thread.cpp
|
||||||
Basics/ThreadPool.cpp
|
Basics/ThreadPool.cpp
|
||||||
Basics/Timing.cpp
|
Basics/Timing.cpp
|
||||||
|
Basics/Traversal.cpp
|
||||||
Basics/tri-strings.cpp
|
Basics/tri-strings.cpp
|
||||||
Basics/tri-zip.cpp
|
Basics/tri-zip.cpp
|
||||||
Basics/Utf8Helper.cpp
|
Basics/Utf8Helper.cpp
|
||||||
|
|
Loading…
Reference in New Issue