1
0
Fork 0

Finished implementation

This commit is contained in:
Simon Grätzer 2016-10-07 11:51:15 +02:00
parent 2c8cd5c2b6
commit a95ef5ed53
18 changed files with 558 additions and 102 deletions

View File

@ -362,7 +362,8 @@ add_executable(${BIN_ARANGOD}
Wal/SynchronizerThread.cpp
Pregel/Conductor.cpp
Pregel/JobMapping.cpp
Pregel/MessageQueue.cpp
Pregel/InMessageCache.cpp
Pregel/OutMessageCache.cpp
Pregel/Vertex.cpp
Pregel/Worker.cpp
Pregel/Utils.cpp

View File

@ -51,7 +51,7 @@ Conductor::Conductor(int executionNumber,
string coordinatorId = ServerState::instance()->getId();
VPackBuilder b;
b(VPackValue(VPackValueType::Object));
b.openObject();
b.add(Utils::executionNumberKey, VPackValue(executionNumber));
b.add(Utils::coordinatorIdKey, VPackValue(coordinatorId));
b.add(Utils::vertexCollectionKey, VPackValue(vertexCollection));
@ -72,7 +72,9 @@ void Conductor::finishedGlobalStep(VPackSlice &data) {
_globalSuperstep++;
VPackBuilder b;
b.openObject();
b.add("gss", VPackValue(_globalSuperstep));
b.close();
sendToAllDBServers(Utils::nextGSSPath, b.slice());
}
@ -83,40 +85,49 @@ void Conductor::cancel() {
_state = ExecutionState::ERROR;
}
int Conductor::sendToAllDBServers(std::string url, VPackSlice const& config) {
int Conductor::sendToAllDBServers(std::string path, VPackSlice const& config) {
ClusterInfo* ci = ClusterInfo::instance();
ClusterComm* cc = ClusterComm::instance();
CoordTransactionID coordTransactionID = TRI_NewTickServer();
//CoordTransactionID coordTransactionID = TRI_NewTickServer();
std::vector<ServerID> DBservers = ci->getCurrentDBServers();
_dbServerCount = DBservers.size();
shared_ptr<vector<ShardID>> DBservers = ci->getShardList(_vertexCollection);// ->getCurrentDBServers();
assert(_dbServerCount == 0 || (int64_t)DBservers->size() == _dbServerCount);
_dbServerCount = DBservers->size();
_responseCount = 0;
auto body = std::make_shared<std::string const>(config.toString());
for (auto it = DBservers.begin(); it != DBservers.end(); ++it) {
vector<ClusterCommRequest> requests;
for (auto it = DBservers->begin(); it != DBservers->end(); ++it) {
ClusterCommRequest r("shard:" + *it, rest::RequestType::POST, path, body);
requests.push_back(r);
}
size_t nrDone = 0;
size_t nrGood = cc->performRequests(requests, 120.0, nrDone, LogTopic("Pregel Conductor"));
/*for (auto it = DBservers->begin(); it != DBservers->end(); ++it) {
auto headers =
std::make_unique<std::unordered_map<std::string, std::string>>();
// set collection name (shard id)
cc->asyncRequest("", coordTransactionID, "server:" + *it,
arangodb::rest::RequestType::PUT, url, body,
cc->asyncRequest("", coordTransactionID, "shard:" + *it,
arangodb::rest::RequestType::PUT, path, body,
headers, nullptr, 120.0);
}
// Now listen to the results:
int count;
int nrok = 0;
for (count = (int)DBservers.size(); count > 0; count--) {
for (count = (int)DBservers->size(); count > 0; count--) {
auto res = cc->wait("", coordTransactionID, 0, "", 0.0);
if (res.status == CL_COMM_RECEIVED) {
if (res.answer_code == arangodb::rest::ResponseCode::OK) {
nrok++;
nrDone++;
}
}
}
}*/
if (nrok != (int)DBservers.size()) {
if (nrDone != nrGood) {
return TRI_ERROR_INTERNAL;
}

View File

@ -23,6 +23,7 @@
#ifndef ARANGODB_PREGEL_CONDUCTOR_H
#define ARANGODB_PREGEL_CONDUCTOR_H 1
#include <string>
#include <mutex>
#include "Basics/Common.h"
#include "Cluster/ClusterInfo.h"
@ -53,11 +54,12 @@ namespace pregel {
private:
std::mutex mtx;
int _executionNumber;
size_t _globalSuperstep;
size_t _dbServerCount = 0;
size_t _responseCount = 0;
int64_t _globalSuperstep;
int64_t _dbServerCount = 0;
int64_t _responseCount = 0;
TRI_vocbase_t *_vocbase;
std::string _vertexCollection, _edgeCollection;
ExecutionState _state = ExecutionState::RUNNING;
int sendToAllDBServers(std::string url, VPackSlice const& body);

View File

@ -0,0 +1,93 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB 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 Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
#include "InMessageCache.h"
#include "Utils.h"
#include "Basics/MutexLocker.h"
#include "Basics/StaticStrings.h"
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
using namespace arangodb::pregel;
InMessageCache::~InMessageCache() {
for (auto const &it : _messages) {
delete(it.second);
}
_messages.clear();
}
void InMessageCache::clean() {
for (auto const &it : _messages) {
it.second->clear();
}
}
void InMessageCache::addMessages(VPackArrayIterator incomingMessages) {
MUTEX_LOCKER(locker, writeMutex);
//unordered_map<string, vector<VPackSlice>> messageBucket;
//VPackSlice messages = data.get(Utils::messagesKey);
for (auto const &it : incomingMessages) {
std::string vertexId = it.get(StaticStrings::ToString).copyString();
int64_t newValue = it.get("value").getInt();
auto vmsg = _messages.find(vertexId);
if (vmsg != _messages.end()) {
// if no combiner
// vmsg->add(it.slice())
// TODO hardcoded combiner
VPackBuilder *current = vmsg->second;
int64_t oldValue = current->slice().get("value").getInt();
if (newValue < oldValue) {
current->clear();
current->openObject();
current->add(StaticStrings::ToString, it.get(StaticStrings::ToString));
current->add("value", VPackValue(newValue));
current->close();
}
} else {
// with a combiner
std::unique_ptr<VPackBuilder> b(new VPackBuilder());
b->add(it);
_messages[vertexId] = b.get();
b.release();
// if no combiner
// VPackBuilder *arr = new VPackBuilder(it);
// arr->openArray();
// arr->add(it)
// _messages[vertexId] = arr;
}
}
}
VPackArrayIterator InMessageCache::getMessages(std::string const& vertexId) {
auto vmsg = _messages.find(vertexId);
if (vmsg != _messages.end()) return VPackArrayIterator(vmsg->second->slice());
else return VPackArrayIterator(VPackSlice());
}

View File

@ -20,14 +20,38 @@
/// @author Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
#include
#ifndef ARANGODB_IN_MESSAGE_CACHE_H
#define ARANGODB_IN_MESSAGE_CACHE_H 1
#include <string>
#include <velocypack/vpack.h>
#include <velocypack/velocypack-aliases.h>
#include "Basics/Common.h"
#include "Basics/Mutex.h"
#include "Cluster/ClusterInfo.h"
namespace arangodb {
//class Mutex;
namespace pregel {
class MessageQueue {
/* In the longer run, maybe write optimized implementations for certain use cases. For example threaded
processing */
class InMessageCache {
public:
addMessage()
InMessageCache() {}
~InMessageCache();
void addMessages(VPackArrayIterator messages);
arangodb::velocypack::ArrayIterator getMessages(ShardID const& shardId);
void clean();
private:
std::unordered_map<std::string, VPackBuilder*> _messages;
Mutex writeMutex;
};
}}
#endif

View File

@ -1,23 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB 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 Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
//using namespace arangodb;

View File

@ -0,0 +1,147 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB 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 Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
#include "OutMessageCache.h"
#include "Utils.h"
#include "Basics/MutexLocker.h"
#include "Basics/StaticStrings.h"
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
using namespace arangodb::pregel;
OutMessageCache::OutMessageCache(CollectionID vertexCollection) : _vertexCollection(vertexCollection) {
_ci = ClusterInfo::instance();
auto shardMap = _ci->getShardList(vertexCollection);
for (ShardID const &it : *shardMap) {
_map[it];
}
}
OutMessageCache::~OutMessageCache() {
for (auto const &it : _map) {
for (auto const &it2 : it.second) {
delete(it2.second);
}
}
_map.clear();
}
void OutMessageCache::clean() {
//TODO better way?
for (auto const &it : _map) {
for (auto const &it2 : it.second) {
it2.second->clear();// clears VPackBuilder
}
}
_map.clear();
}
void OutMessageCache::addMessage(std::string key, VPackSlice slice) {
ShardID responsibleShard;
bool usesDefaultShardingAttributes;
VPackBuilder keyDoc;
keyDoc.openObject();
keyDoc.add(StaticStrings::KeyString, VPackValue(key));
keyDoc.close();
int res = _ci->getResponsibleShard(_vertexCollection, keyDoc.slice(), true,
responsibleShard, usesDefaultShardingAttributes);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
TRI_ASSERT(usesDefaultShardingAttributes);// should be true anyway
//std::unordered_map<std::string, VPackBuilder*> vertexMap =;
auto it = _map[responsibleShard].find(key);
if (it != _map[responsibleShard].end()) {// more than one message
VPackBuilder *b = it->second;
// hardcoded combiner
int64_t oldValue = b->slice().get("value").getInt();
int64_t newValue = slice.get("value").getInt();
if (newValue < oldValue) {
b->clear();
b->add(slice);
}
} else {// first message for this vertex
std::unique_ptr<VPackBuilder> b(new VPackBuilder());
b->add(slice);
_map[responsibleShard][key] = b.get();
b.release();
}
}
/*
void OutMessageCache::addMessages(VPackArrayIterator incomingMessages) {
//unordered_map<string, vector<VPackSlice>> messageBucket;
//VPackSlice messages = data.get(Utils::messagesKey);
for (auto const &it : incomingMessages) {
std::string vertexId = it.get(StaticStrings::ToString).copyString();
auto vmsg = _messages.find(vertexId);
if (vmsg != _messages.end()) {
// if no combiner
// vmsg->add(it.slice())
// TODO do not hardcode combiner
int64_t old = vmsg->second->slice().get("value").getInt();
int64_t nw = it.get("value").getInt();
if (nw < old) {
vmsg->second->clear();
vmsg->second->add(it);
}
} else {
// assuming we have a combiner
std::unique_ptr<VPackBuilder> b(new VPackBuilder());
b->add(it);
_messages[vertexId] = b.get();
b.release();
// if no combiner
// VPackBuilder *arr = new VPackBuilder(it);
// arr->openArray();
// arr->add(it)
// _messages[vertexId] = arr;
}
}
}*/
void OutMessageCache::getMessages(ShardID const& shardId, VPackBuilder &outBuilder) {
auto shardIt = _map.find(shardId);
if (shardIt != _map.end()) {
//auto vertices = *shardIt;
outBuilder.openArray();
for (auto messagesPair : shardIt->second) {
outBuilder.add(VPackArrayIterator(messagesPair.second->slice()));
}
outBuilder.close();
//return ArrayIterator(vmsg->second->slice())
}
//else return VPackSlice();
}

View File

@ -0,0 +1,59 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB 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 Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_OUT_MESSAGE_CACHE_H
#define ARANGODB_OUT_MESSAGE_CACHE_H 1
#include <string>
#include <velocypack/vpack.h>
#include <velocypack/velocypack-aliases.h>
#include "Basics/Common.h"
#include "Basics/Mutex.h"
#include "Cluster/ClusterInfo.h"
namespace arangodb {
namespace pregel {
/* In the longer run, maybe write optimized implementations for certain use cases. For example threaded
processing */
class OutMessageCache {
public:
OutMessageCache(CollectionID vertexCollection);
~OutMessageCache();
void addMessage(std::string key, VPackSlice slice);
//void addMessages(VPackArrayIterator messages);
void getMessages(ShardID const& shardId, VPackBuilder &outBuilder);
void clean();
private:
// two stage map: shard -> vertice -> message
CollectionID _vertexCollection;
std::unordered_map<std::string, std::unordered_map<std::string, VPackBuilder*>> _map;
ClusterInfo *_ci;
};
}}
#endif

View File

@ -26,6 +26,7 @@ using namespace arangodb::pregel;
std::string const Utils::nextGSSPath = "/_api/pregel/nextGSS";
std::string const Utils::finishedGSSPath = "/_api/pregel/finishedGSS";
std::string const Utils::messagesPath = "/_api/pregel/messages";
std::string const Utils::executionNumberKey = "extn";
std::string const Utils::vertexCollectionKey = "vxcln";

View File

@ -34,6 +34,7 @@ namespace pregel {
// constants
static std::string const nextGSSPath;
static std::string const finishedGSSPath;
static std::string const messagesPath;
static std::string const executionNumberKey;
static std::string const vertexCollectionKey;

View File

@ -21,18 +21,46 @@
////////////////////////////////////////////////////////////////////////////////
#include "Vertex.h"
#include "OutMessageCache.h"
#include "Basics/StaticStrings.h"
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace std;
using namespace arangodb;
using namespace arangodb::velocypack;
using namespace arangodb::pregel;
Vertex::Vertex(VPackSlice &document) {
Vertex::Vertex(VPackSlice document) {
documentId = document.get(StaticStrings::IdString).copyString();
_vertexState = document.get("value").getInt();
}
void Vertex::compute(velocypack::ArrayIterator &messages) {
Vertex::~Vertex() {
for (auto const &it : _edges) {
delete(it);
}
_edges.clear();
}
void Vertex::compute(int64_t gss, VPackArrayIterator const &messages, OutMessageCache *outCache) {
int current = _vertexState;
for (auto const &msg : messages) {
int val = msg.getInt();
if (val < current) current = val;
}
if (current == _vertexState) voteHalt();
else {
_vertexState = current;
for (auto const &edge : _edges) {
VPackBuilder b;
b.openObject();
b.add(StaticStrings::ToString, VPackValue(edge->toId));
b.add("val", VPackValue(edge->value + current));
b.close();
outCache->addMessage(edge->toId, b.slice());
}
}
}

View File

@ -20,11 +20,10 @@
/// @author Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
#include <string>
#include <iterator>
#include "Basics/Common.h"
#include "VocBase/vocbase.h"
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
#ifndef ARANGODB_PREGEL_VERTEX_H
#define ARANGODB_PREGEL_VERTEX_H 1
@ -36,8 +35,10 @@ namespace pregel {
STOPPED
};
class OutMessageCache;
struct Edge {
public:
std::string edgeId;
std::string toId;
@ -47,21 +48,23 @@ namespace pregel {
class Vertex {
public:
//typedef std::iterator<std::forward_iterator_tag, VPackSlice> MessageIterator;
Vertex(VPackSlice &document);
void compute(velocypack::ArrayIterator &messages);
Vertex(VPackSlice document);
~Vertex();
void compute(int64_t gss, VPackArrayIterator const &messages, OutMessageCache* cache);
VertexActivationState state() {return _activationState;}
std::vector<VPackSlice> messages() {return _messages;}
//std::vector<VPackSlice> messages() {return _messages;}
std::vector<Edge> _edges;
std::vector<Edge*> _edges;
std::string documentId;
protected:
void voteHalt() {_activationState = VertexActivationState::STOPPED;}
void sendMessage(VPackBuilder &message) {_messages.push_back(message.slice());}
//void sendMessage(VPackBuilder &message) {_messages.push_back(message.slice());}
private:
VertexActivationState _activationState;
std::vector<VPackSlice> _messages;
//std::vector<VPackSlice> _messages;
int _vertexState;// demo
};

View File

@ -22,6 +22,9 @@
#include "Worker.h"
#include "Vertex.h"
#include "Utils.h"
#include "InMessageCache.h"
#include "OutMessageCache.h"
#include "Cluster/ClusterInfo.h"
#include "Cluster/ClusterComm.h"
@ -29,6 +32,7 @@
#include "VocBase/vocbase.h"
#include "Utils/SingleCollectionTransaction.h"
#include "Utils/StandaloneTransactionContext.h"
#include "Indexes/EdgeIndex.h"
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
@ -39,13 +43,18 @@ using namespace arangodb::pregel;
Worker::Worker(int executionNumber,
TRI_vocbase_t *vocbase,
VPackSlice &s) {
VPackSlice s) {
LOG(DEBUG) << "starting worker";
//VPackSlice algo = s.get("algo");
string vertexCollection = s.get("vertex").copyString();
string edgeCollection = s.get("edge").copyString();
_cache1 = new InMessageCache();
_cache2 = new InMessageCache();
_currentCache = _cache1;
_outCache = new OutMessageCache(vertexCollection);
SingleCollectionTransaction trx(StandaloneTransactionContext::Create(vocbase),
vertexCollection, TRI_TRANSACTION_READ);
@ -83,7 +92,7 @@ Worker::Worker(int executionNumber,
return;
}
OperationResult result2 = trx2.all(edgeCollection, 0, UINT64_MAX, OperationOptions());
/*OperationResult result2 = trx2.all(edgeCollection, 0, UINT64_MAX, OperationOptions());
// Commit or abort.
res = trx.finish(result.code);
@ -94,36 +103,118 @@ Worker::Worker(int executionNumber,
VPackSlice edges = result.slice();
if (edges.isExternal()) {
edges = vertices.resolveExternal();
}*/
SingleCollectionTransaction::IndexHandle handle = trx2.edgeIndexHandle(edgeCollection);
shared_ptr<Index> edgeIndexPtr = handle.getIndex();
EdgeIndex* edgeIndex = static_cast<EdgeIndex*>(edgeIndexPtr.get());
/*map<std::string, vector<Edge*>> sortBucket;// TODO hash_map ?
for (auto const& it : velocypack::ArrayIterator(edges)) {
Edge *e = new Edge();
e->edgeId = it.get(StaticStrings::IdString).copyString();
e->toId = it.get(StaticStrings::ToString).copyString();
e->value = it.get("value").getInt();
sortBucket[e->toId].push_back(e);
}*/
for (auto const &it : velocypack::ArrayIterator(vertices)) {
Vertex *v = new Vertex(it);
_vertices[v->documentId] = v;
//v._edges = sortBucket[v.documentId];
TransactionBuilderLeaser b(&trx2);
b->openArray();
b->add(it.get(StaticStrings::IdString));
b->add(VPackValue(VPackValueType::Null));
b->close();
IndexIterator* vit = edgeIndex->iteratorForSlice(&trx2, nullptr, b->slice(), false);
TRI_doc_mptr_t *edgePack;
while((edgePack = vit->next()) != nullptr) {
VPackSlice s(edgePack->vpack());
std::unique_ptr<Edge> e(new Edge());
e->edgeId = it.get(StaticStrings::IdString).copyString();
e->toId = it.get(StaticStrings::ToString).copyString();
e->value = it.get("value").getInt();
v->_edges.push_back(e.get());
e.release();
}
}
}
Worker::~Worker() {
for (auto const &it : _vertices) {
delete(it.second);
}
_vertices.clear();
}
void Worker::nextGlobalStep(VPackSlice data) {
// TODO do some work?
VPackSlice gssSlice = data.get(Utils::globalSuperstepKey);
if (!gssSlice.isInt()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "Invalid gss in body");
}
int64_t gss = gssSlice.getInt();
if (gss == 0) {
VPackSlice cid = data.get(Utils::coordinatorIdKey);
//VPackSlice algo = data.get(Utils::algorithmKey);
if (cid.isString())
_coordinatorId = cid.copyString();
}
_globalSuperstep = gss;
InMessageCache *cache = _currentCache;
if (_currentCache == _cache1) _currentCache = _cache2;
else _currentCache = _cache1;
// TODO start task
if (_globalSuperstep == 0) {
for (auto const &it : _vertices) {
Vertex *v = it.second;
VPackArrayIterator messages = cache->getMessages(v->documentId);
v->compute(_globalSuperstep, messages, _outCache);
_activationMap[it.first] = v->state() == VertexActivationState::ACTIVE;
}
} else {
bool isDone = true;
for (auto &it : _activationMap) {
VPackArrayIterator messages = cache->getMessages(it.first);
if (messages.size() > 0 || it.second) {
isDone = false;
Vertex *v = _vertices[it.first];
v->compute(_globalSuperstep, messages, _outCache);
it.second = v->state() == VertexActivationState::ACTIVE;
}
}
}
/*
for (auto const &it : velocypack::ArrayIterator(vertices)) {
Vertex v(it);
for (auto const& it : edges) {
Edge e;
e.edgeId = it.get(StaticStrings::IdString).copyString();
e.toId = it.get(StaticStrings::ToString).copyString();
e.value = it.get("value").getInt();
v.edges.push_back(e);
}
ClusterComm *cc = ClusterComm::instance();
auto body = std::make_shared<std::string const>(messages.toString());
vector<ClusterCommRequest> requests;
for (auto it = DBservers->begin(); it != DBservers->end(); ++it) {
ClusterCommRequest r("shard:" + *it, rest::RequestType::POST, path, body);
requests.push_back(r);
}*/
}
void Worker::nextGlobalStep(VPackSlice &data) {
// TODO do some work?
VPackSlice gss = data.get("gss");
if (gss.isInt() && gss.getInt() == 0) {
VPackSlice cid = data.get("coordinator");
if (cid.isString())
_coordinatorId = cid.copyString();
}
// TODO queue tasks
void Worker::receivedMessages(VPackSlice data) {
VPackSlice gssSlice = data.get(Utils::globalSuperstepKey);
VPackSlice messageSlice = data.get(Utils::messagesKey);
if (!gssSlice.isInt() || !messageSlice.isArray()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "Bad parameters in body");
}
int64_t gss = gssSlice.getInt();
if (gss != _globalSuperstep+1) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "Superstep out of sync");
}
_currentCache->addMessages(VPackArrayIterator(messageSlice));
}

View File

@ -23,24 +23,35 @@
#ifndef ARANGODB_PREGEL_WORKER_H
#define ARANGODB_PREGEL_WORKER_H 1
#include <vector>
#include "Basics/Common.h"
#include "Cluster/ClusterInfo.h"
#include "VocBase/vocbase.h"
#include "Scheduler/Task.h"
#include "Cluster/ClusterInfo.h"
namespace arangodb {
namespace pregel {
class Vertex;
class InMessageCache;
class OutMessageCache;
class Worker {
public:
Worker(int executionNumber, TRI_vocbase_t *vocbase, VPackSlice &s);
Worker(int executionNumber, TRI_vocbase_t *vocbase, VPackSlice s);
~Worker();
void nextGlobalStep(VPackSlice &data);// called by coordinator
void nextGlobalStep(VPackSlice data);// called by coordinator
void receivedMessages(VPackSlice data);
private:
std::string _coordinatorId;
std::vector<Vertex> _vertices;
int64_t _globalSuperstep;
std::unordered_map<std::string, Vertex*> _vertices;
std::map<std::string, bool> _activationMap;
InMessageCache *_cache1, *_cache2;
InMessageCache *_currentCache;
OutMessageCache *_outCache;
};
}
}

View File

@ -63,6 +63,8 @@ RestHandler::status RestPregelHandler::execute() {
finishedGSS(s);
} else if (suffix[0] == "nextGSS") {
nextGSS(s);
} else if (suffix[0] == "messages") {
receivedMessages(s);
}
VPackBuilder result;
result.add(VPackValue("thanks"));
@ -76,7 +78,7 @@ RestHandler::status RestPregelHandler::execute() {
return status::DONE;
}
void RestPregelHandler::nextGSS(VPackSlice &body) {
void RestPregelHandler::nextGSS(VPackSlice body) {
VPackSlice executionNum = body.get("en");
if (executionNum.isInt()) {
Worker *w = JobMapping::instance()->worker(executionNum.getInt());
@ -88,7 +90,7 @@ void RestPregelHandler::nextGSS(VPackSlice &body) {
}
}
void RestPregelHandler::finishedGSS(VPackSlice &body) {
void RestPregelHandler::finishedGSS(VPackSlice body) {
VPackSlice executionNum = body.get("en");
if (executionNum.isInt()) {
Conductor *exe = JobMapping::instance()->conductor(executionNum.getInt());
@ -99,14 +101,14 @@ void RestPregelHandler::finishedGSS(VPackSlice &body) {
}
void RestPregelHandler::receivedMessages(VPackSlice &body) {
void RestPregelHandler::receivedMessages(VPackSlice body) {
VPackSlice executionNum = body.get("en");
if (executionNum.isInt()) {
Worker *exe = JobMapping::instance()->worker(executionNum.getInt());
if (exe) {
//exe->nextGlobalStep(body);
exe->receivedMessages(body);
} else {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_FAILED, "there is no registered worker");
}
}
}

View File

@ -31,13 +31,13 @@ namespace arangodb {
explicit RestPregelHandler(GeneralRequest*, GeneralResponse*);
public:
bool isDirect() const override { return true; }
bool isDirect() const override { return false; }
status execute() override;
private:
void nextGSS(VPackSlice &body);
void finishedGSS(VPackSlice &body);
void receivedMessages(VPackSlice &body);
void nextGSS(VPackSlice body);
void finishedGSS(VPackSlice body);
void receivedMessages(VPackSlice body);
};
}

View File

@ -69,6 +69,10 @@ namespace rest {
namespace traverser {
class BaseTraverserEngine;
}
namespace pregel {
class Worker;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief forward declarations
@ -81,13 +85,14 @@ class TransactionContext;
class Transaction {
friend class traverser::BaseTraverserEngine;
public:
double const TRX_FOLLOWER_TIMEOUT = 3.0;
class IndexHandle {
friend class Transaction;
friend class pregel::Worker;
std::shared_ptr<arangodb::Index> _index;
public:
IndexHandle() = default;

View File

@ -55,7 +55,7 @@
#include "VocBase/modes.h"
#include "Wal/LogfileManager.h"
#include "Pregel/Conductor.h"
#include "Pregel/Execution.h"
#include "Pregel/JobMapping.h"
#include <velocypack/Builder.h>
#include <velocypack/HexDump.h>
@ -1829,16 +1829,16 @@ static void JS_Pregel(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_vocbase_t* vocbase = GetContextVocBase(isolate);
LOG(WARN) << "Called as a controller";
result = pregel::Conductor::instance()->createExecutionNumber();
result = pregel::JobMapping::instance()->createExecutionNumber();
std::string const vertexCollectionName = TRI_ObjectToString(args[1]);
std::string const edgeCollectionName = TRI_ObjectToString(args[2]);
pregel::Execution* e = new pregel::Execution(result,
pregel::Conductor* e = new pregel::Conductor(result,
vocbase,
vertexCollectionName,
edgeCollectionName,
"");
pregel::Conductor::instance()->addExecution(e, result);
pregel::JobMapping::instance()->addExecution(e, result);
} else {
TRI_V8_THROW_EXCEPTION_USAGE("Only call on coordinator");