mirror of https://gitee.com/bigwinds/arangodb
Finished implementation
This commit is contained in:
parent
2c8cd5c2b6
commit
a95ef5ed53
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -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
|
|
@ -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;
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue