mirror of https://gitee.com/bigwinds/arangodb
Working single DBServer solution SSSP
This commit is contained in:
parent
a6774ae269
commit
c7379f6a06
|
@ -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));
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue