1
0
Fork 0

Working single DBServer solution SSSP

This commit is contained in:
Simon Grätzer 2016-10-13 12:56:55 +02:00
parent a6774ae269
commit c7379f6a06
8 changed files with 65 additions and 44 deletions

View File

@ -137,8 +137,8 @@ void Conductor::finishedGlobalStep(VPackSlice &data) {
_globalSuperstep++; _globalSuperstep++;
std::string baseUrl = Utils::baseUrl(_vocbaseGuard.vocbase()->name()); std::string baseUrl = Utils::baseUrl(_vocbaseGuard.vocbase()->name());
if (_doneCount == _dbServerCount || _globalSuperstep >= 25) { if (_doneCount == _dbServerCount || _globalSuperstep == 101) {
LOG(INFO) << "Done. We did " << _globalSuperstep << " rounds"; LOG(INFO) << "Done. We did " << _globalSuperstep-1 << " rounds";
VPackBuilder b; VPackBuilder b;
b.openObject(); b.openObject();
b.add(Utils::executionNumberKey, VPackValue(_executionNumber)); b.add(Utils::executionNumberKey, VPackValue(_executionNumber));

View File

@ -48,7 +48,7 @@ void InMessageCache::clear() {
void InMessageCache::addMessages(VPackArrayIterator incomingMessages) { void InMessageCache::addMessages(VPackArrayIterator incomingMessages) {
MUTEX_LOCKER(locker, writeMutex); MUTEX_LOCKER(locker, writeMutex);
LOG(INFO) << "Adding messages to in queue\n"; LOG(INFO) << "Adding messages to in queue";
//unordered_map<string, vector<VPackSlice>> messageBucket; //unordered_map<string, vector<VPackSlice>> messageBucket;
//VPackSlice messages = data.get(Utils::messagesKey); //VPackSlice messages = data.get(Utils::messagesKey);
@ -89,7 +89,7 @@ void InMessageCache::addMessages(VPackArrayIterator incomingMessages) {
} }
VPackSlice InMessageCache::getMessages(std::string const& vertexId) { VPackSlice InMessageCache::getMessages(std::string const& vertexId) {
LOG(INFO) << "Querying messages from in queue\n"; LOG(INFO) << "Querying messages from for " << vertexId;
auto vmsg = _messages.find(vertexId); auto vmsg = _messages.find(vertexId);
if (vmsg != _messages.end()) { if (vmsg != _messages.end()) {
return vmsg->second->slice(); return vmsg->second->slice();

View File

@ -66,8 +66,8 @@ void OutMessageCache::clear() {
_map.clear(); _map.clear();
} }
void OutMessageCache::addMessage(std::string key, VPackSlice slice) { void OutMessageCache::addMessage(std::string key, VPackSlice mData) {
LOG(INFO) << "Adding messages to out queue\n"; LOG(INFO) << "Adding outgoing messages " << mData.toJson();
ShardID responsibleShard; ShardID responsibleShard;
bool usesDefaultShardingAttributes; bool usesDefaultShardingAttributes;
@ -89,15 +89,15 @@ void OutMessageCache::addMessage(std::string key, VPackSlice slice) {
// hardcoded combiner // hardcoded combiner
int64_t oldValue = b->slice().get("value").getInt(); int64_t oldValue = b->slice().get("value").getInt();
int64_t newValue = slice.get("value").getInt(); int64_t newValue = mData.get("value").getInt();
if (newValue < oldValue) { if (newValue < oldValue) {
b->clear(); b->clear();
b->add(slice); b->add(mData);
} }
} else {// first message for this vertex } else {// first message for this vertex
std::unique_ptr<VPackBuilder> b(new VPackBuilder()); std::unique_ptr<VPackBuilder> b(new VPackBuilder());
b->add(slice); b->add(mData);
_map[responsibleShard][key] = b.get(); _map[responsibleShard][key] = b.get();
b.release(); b.release();
} }

View File

@ -34,7 +34,12 @@ using namespace arangodb::pregel;
Message::Message(VPackSlice slice) { Message::Message(VPackSlice slice) {
VPackSlice s = slice.get("value"); VPackSlice s = slice.get("value");
_value = s.getSmallInt() || s.getInt() ? s.getInt() : -1; _value = s.getInt();
}
Edge::Edge(VPackSlice data) : _data(data) {
VPackSlice v = data.get("value");
_value = v.isInteger() ? v.getInt() : 1;
} }
Vertex::Vertex(VPackSlice document) : _data(document) { Vertex::Vertex(VPackSlice document) : _data(document) {
@ -51,20 +56,26 @@ Vertex::~Vertex() {
} }
void Vertex::compute(int gss, MessageIterator const &messages, OutMessageCache* const cache) { void Vertex::compute(int gss, MessageIterator const &messages, OutMessageCache* const cache) {
int current = _vertexState; int64_t current = _vertexState;
for (auto const &msg : messages) { for (auto const &msg : messages) {
if (msg._value < current) current = msg._value; if (current < 0 || msg._value < current) {
current = msg._value;
};
} }
if (current >= 0 && (gss == 0 || current != _vertexState)) { if (current >= 0 && (gss == 0 || current != _vertexState)) {
LOG(INFO) << "Recomputing value for vertex " << _data.toJson();
_vertexState = current; _vertexState = current;
for (auto const &edge : _edges) { for (auto const &edge : _edges) {
int64_t val = edge._value + current;
VPackSlice toID = edge._data.get(StaticStrings::ToString); VPackSlice toID = edge._data.get(StaticStrings::ToString);
VPackBuilder b; VPackBuilder b;
b.openObject(); b.openObject();
b.add(StaticStrings::ToString, toID); b.add(StaticStrings::ToString, toID);
b.add("value", VPackValue(edge._value + current)); b.add("value", VPackValue(val));
b.close(); b.close();
cache->addMessage(toID.copyString(), b.slice()); cache->addMessage(toID.copyString(), b.slice());
} }
} else voteHalt(); }
voteHalt();
} }

View File

@ -40,13 +40,13 @@ namespace pregel {
struct Message { struct Message {
Message(VPackSlice slice); Message(VPackSlice slice);
int _value; // demo int64_t _value; // demo
}; };
//template <typename T> //template <typename T>
class MessageIterator { class MessageIterator {
public: public:
MessageIterator() = delete; MessageIterator() : _size(0) {}
typedef MessageIterator iterator; typedef MessageIterator iterator;
typedef const MessageIterator const_iterator; typedef const MessageIterator const_iterator;
@ -109,12 +109,12 @@ namespace pregel {
}; };
struct Edge { struct Edge {
Edge(VPackSlice data) : _data(data) {} Edge(VPackSlice data);
VPackSlice _data; VPackSlice _data;
//protected: virtual void loadData() = 0; //protected: virtual void loadData() = 0;
int _value;// demo int64_t _value;// demo
}; };
class Vertex { class Vertex {
@ -132,11 +132,11 @@ namespace pregel {
protected: protected:
void voteHalt() {_activationState = VertexActivationState::STOPPED;} void voteHalt() {_activationState = VertexActivationState::STOPPED;}
int _vertexState;// demo int64_t _vertexState;// demo
VPackSlice _data; VPackSlice _data;
private: private:
VertexActivationState _activationState; VertexActivationState _activationState = VertexActivationState::ACTIVE;
}; };
} }
} }

View File

@ -54,7 +54,7 @@ using namespace arangodb::pregel;
Worker::Worker(unsigned int executionNumber, Worker::Worker(unsigned int executionNumber,
TRI_vocbase_t *vocbase, TRI_vocbase_t *vocbase,
VPackSlice s) : _vocbase(vocbase), _ctx(new WorkerContext) { VPackSlice s) : _vocbase(vocbase), _ctx(new WorkerContext(executionNumber)) {
//VPackSlice algo = s.get("algo"); //VPackSlice algo = s.get("algo");
@ -65,7 +65,6 @@ Worker::Worker(unsigned int executionNumber,
if (!(coordID.isString() && vertexShardIDs.length() == 1 && edgeShardIDs.length() == 1)) { if (!(coordID.isString() && vertexShardIDs.length() == 1 && edgeShardIDs.length() == 1)) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "Only one shard per collection supported"); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "Only one shard per collection supported");
} }
_ctx->_executionNumber = executionNumber;
_ctx->_coordinatorId = coordID.copyString(); _ctx->_coordinatorId = coordID.copyString();
_ctx->_database = vocbase->name(); _ctx->_database = vocbase->name();
_ctx->_vertexCollectionName = s.get(Utils::vertexCollectionKey).copyString();// readable name of collection _ctx->_vertexCollectionName = s.get(Utils::vertexCollectionKey).copyString();// readable name of collection
@ -147,9 +146,7 @@ Worker::Worker(unsigned int executionNumber,
} }
LOG(INFO) << s.toJson(); LOG(INFO) << s.toJson();
VPackSlice i = s.get("value");
v->_edges.emplace_back(s); v->_edges.emplace_back(s);
v->_edges.end()->_value = i.isInteger() ? i.getInt() : 1;
edgeCount++; edgeCount++;
} }
@ -190,17 +187,21 @@ void Worker::nextGlobalStep(VPackSlice data) {
"Invalid gss in %s:%d", __FILE__, __LINE__); "Invalid gss in %s:%d", __FILE__, __LINE__);
} }
unsigned int gss = (unsigned int) gssSlice.getUInt(); unsigned int gss = (unsigned int) gssSlice.getUInt();
unsigned int expected = _ctx->_globalSuperstep + 1; if (_ctx->_expectedGSS != gss) {
if (gss != 0 && expected != gss) {
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_BAD_PARAMETER, "Seems like this worker missed a gss, expected %u. Data = %s ", THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_BAD_PARAMETER, "Seems like this worker missed a gss, expected %u. Data = %s ",
expected, data.toJson().c_str()); _ctx->_expectedGSS, data.toJson().c_str());
} }
_ctx->_globalSuperstep = gss; _ctx->_globalSuperstep = gss;
_ctx->_expectedGSS = gss + 1;
_ctx->readableIncomingCache()->clear(); _ctx->readableIncomingCache()->clear();
_ctx->swapIncomingCaches();// write cache becomes the readable cache _ctx->swapIncomingCaches();// write cache becomes the readable cache
std::unique_ptr<rest::Job> job(new WorkerJob(this, _ctx)); std::unique_ptr<rest::Job> job(new WorkerJob(this, _ctx));
DispatcherFeature::DISPATCHER->addJob(job, false); int res = DispatcherFeature::DISPATCHER->addJob(job, true);
if (res != TRI_ERROR_NO_ERROR) {
LOG(ERR) << "Could not start worker job";
}
LOG(INFO) << "Worker started new gss: " << gss; LOG(INFO) << "Worker started new gss: " << gss;
} }
@ -222,7 +223,7 @@ void Worker::receivedMessages(VPackSlice data) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "Superstep out of sync"); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "Superstep out of sync");
} }
LOG(INFO) << "Worker received messages\n"; LOG(INFO) << "Worker received messages";
} }
void Worker::writeResults() { void Worker::writeResults() {
@ -247,7 +248,7 @@ void Worker::writeResults() {
b.add(StaticStrings::KeyString, pair.second->_data.get(StaticStrings::KeyString)); b.add(StaticStrings::KeyString, pair.second->_data.get(StaticStrings::KeyString));
b.add("value", VPackValue(pair.second->_vertexState)); b.add("value", VPackValue(pair.second->_vertexState));
b.close(); b.close();
LOG(INFO) << b.toString(); LOG(INFO) << b.toJson();
/*result = trx.update(_vertexCollection, b->slice(), options); /*result = trx.update(_vertexCollection, b->slice(), options);
if (!result.successful()) { if (!result.successful()) {
THROW_ARANGO_EXCEPTION_FORMAT(result.code, "while looking up graph '%s'", THROW_ARANGO_EXCEPTION_FORMAT(result.code, "while looking up graph '%s'",
@ -266,14 +267,16 @@ void Worker::writeResults() {
// ========== WorkerJob ========== // ========== WorkerJob ==========
WorkerJob::WorkerJob(Worker *worker, std::shared_ptr<WorkerContext> ctx) : Job("Pregel Job"), _worker(worker), _ctx(ctx) { WorkerJob::WorkerJob(Worker *worker,
std::shared_ptr<WorkerContext> ctx) : Job("Pregel Job"), _canceled(false), _worker(worker), _ctx(ctx) {
} }
void WorkerJob::work() { void WorkerJob::work() {
LOG(INFO) << "Worker job started";
if (_canceled) { if (_canceled) {
LOG(INFO) << "Job was canceled before work started";
return; return;
} }
LOG(INFO) << "Worker job started\n";
// TODO cache this // TODO cache this
OutMessageCache outCache(_ctx); OutMessageCache outCache(_ctx);
@ -285,24 +288,29 @@ void WorkerJob::work() {
for (auto const &it : _worker->_vertices) { for (auto const &it : _worker->_vertices) {
Vertex *v = it.second; Vertex *v = it.second;
std::string key = v->_data.get(StaticStrings::KeyString).copyString(); //std::string key = v->_data.get(StaticStrings::KeyString).copyString();
//VPackSlice messages = _ctx->readableIncomingCache()->getMessages(key);
VPackSlice messages = _ctx->readableIncomingCache()->getMessages(key); v->compute(gss, MessageIterator(), &outCache);
v->compute(gss, MessageIterator(messages), &outCache);
bool active = v->state() == VertexActivationState::ACTIVE; bool active = v->state() == VertexActivationState::ACTIVE;
if (!active) LOG(INFO) << "vertex has halted"; if (!active) LOG(INFO) << "vertex has halted";
_worker->_activationMap[it.first] = active; _worker->_activationMap[it.first] = active;
} }
} else { } else {
for (auto &it : _worker->_activationMap) { for (auto &it : _worker->_activationMap) {
VPackSlice messages = _ctx->readableIncomingCache()->getMessages(it.first);
std::string key = _ctx->vertexCollectionName() + "/" + it.first;
VPackSlice messages = _ctx->readableIncomingCache()->getMessages(key);
MessageIterator iterator(messages); MessageIterator iterator(messages);
if (iterator.size() > 0 || it.second) { if (iterator.size() > 0 || it.second) {
isDone = false; isDone = false;
LOG(INFO) << "Processing messages: " << messages.toString();
Vertex *v = _worker->_vertices[it.first]; Vertex *v = _worker->_vertices[it.first];
v->compute(gss, iterator, &outCache); v->compute(gss, iterator, &outCache);
it.second = v->state() == VertexActivationState::ACTIVE; bool active = v->state() == VertexActivationState::ACTIVE;
it.second = active;
if (!active) LOG(INFO) << "vertex has halted";
} }
} }
} }
@ -317,7 +325,7 @@ void WorkerJob::work() {
if (!isDone) { if (!isDone) {
outCache.sendMessages(); outCache.sendMessages();
} else { } else {
LOG(INFO) << "Worker job has nothing more to process\n"; LOG(INFO) << "Worker job has nothing more to process";
} }
// notify the conductor that we are done. // notify the conductor that we are done.
@ -326,7 +334,7 @@ void WorkerJob::work() {
package.add(Utils::senderKey, VPackValue(ServerState::instance()->getId())); package.add(Utils::senderKey, VPackValue(ServerState::instance()->getId()));
package.add(Utils::executionNumberKey, VPackValue(_ctx->executionNumber())); package.add(Utils::executionNumberKey, VPackValue(_ctx->executionNumber()));
package.add(Utils::globalSuperstepKey, VPackValue(gss)); package.add(Utils::globalSuperstepKey, VPackValue(gss));
if (!isDone) package.add(Utils::doneKey, VPackValue(isDone)); package.add(Utils::doneKey, VPackValue(isDone));
package.close(); package.close();
LOG(INFO) << "Sending finishedGSS to coordinator: " << _ctx->coordinatorId(); LOG(INFO) << "Sending finishedGSS to coordinator: " << _ctx->coordinatorId();
@ -348,6 +356,7 @@ void WorkerJob::work() {
} }
bool WorkerJob::cancel() { bool WorkerJob::cancel() {
LOG(INFO) << "Canceling worker job";
_canceled = true; _canceled = true;
return true; return true;
} }

View File

@ -26,7 +26,7 @@
using namespace arangodb; using namespace arangodb;
using namespace arangodb::pregel; using namespace arangodb::pregel;
WorkerContext::WorkerContext() { WorkerContext::WorkerContext(unsigned int en) : _executionNumber(en) {
_readCache = new InMessageCache(); _readCache = new InMessageCache();
_writeCache = new InMessageCache(); _writeCache = new InMessageCache();
} }

View File

@ -38,7 +38,7 @@ namespace pregel {
class WorkerContext { class WorkerContext {
friend class Worker; friend class Worker;
public: public:
WorkerContext(); WorkerContext(unsigned int exeNum);
~WorkerContext(); ~WorkerContext();
inline unsigned int executionNumber() { inline unsigned int executionNumber() {
@ -83,8 +83,9 @@ namespace pregel {
private: private:
/// @brief guard to make sure the database is not dropped while used by us /// @brief guard to make sure the database is not dropped while used by us
unsigned int _executionNumber; const unsigned int _executionNumber;
unsigned int _globalSuperstep; unsigned int _globalSuperstep = 0;
unsigned int _expectedGSS = 0;
std::string _coordinatorId; std::string _coordinatorId;
std::string _database; std::string _database;
std::string _vertexCollectionName, _vertexCollectionPlanId; std::string _vertexCollectionName, _vertexCollectionPlanId;