Commit e899fe2e authored by Georgios Bitzes's avatar Georgios Bitzes
Browse files

No more stacktrace in case --path given to quarkdb-create exists already

parent 8ad0d6fb
Pipeline #858365 passed with stages
in 38 minutes and 29 seconds
......@@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
## Unreleased
- Prevent crashing when ``LHSCAN`` is provided with a cursor missing the field
component.
- Print simple error message when the given path to quarkdb-create already exists,
instead of a stacktrace
## 0.3.7 (2019-04-24)
- Heavy use of lease commands could cause performance degradation and latency
......
......@@ -221,10 +221,10 @@ void ShardDirectory::obliterate(RaftClusterID clusterID, const std::vector<RaftS
storeResilveringHistory();
}
void ShardDirectory::initializeDirectory(const std::string &path, RaftClusterID clusterID, ShardID shardID) {
Status ShardDirectory::initializeDirectory(const std::string &path, RaftClusterID clusterID, ShardID shardID) {
std::string err;
if(directoryExists(path, err)) {
qdb_throw("Cannot initialize shard directory for '" << shardID << "', path already exists: " << path);
return Status(EEXIST, SSTR("Cannot initialize shard directory for '" << shardID << "', path already exists: " << path));
}
mkpath_or_die(path + "/", 0755);
......@@ -234,10 +234,14 @@ void ShardDirectory::initializeDirectory(const std::string &path, RaftClusterID
ResilveringHistory history;
history.append(ResilveringEvent("GENESIS", time(NULL)));
write_file_or_die(pathJoin(path, "RESILVERING-HISTORY"), history.serialize());
return Status();
}
ShardDirectory* ShardDirectory::create(const std::string &path, RaftClusterID clusterID, ShardID shardID, std::unique_ptr<StateMachine> sm) {
initializeDirectory(path, clusterID, shardID);
ShardDirectory* ShardDirectory::create(const std::string &path, RaftClusterID clusterID, ShardID shardID, std::unique_ptr<StateMachine> sm, Status &st) {
st = initializeDirectory(path, clusterID, shardID);
if(!st.ok()) {
return nullptr;
}
ShardDirectory *shardDirectory = new ShardDirectory(path);
......@@ -246,8 +250,12 @@ ShardDirectory* ShardDirectory::create(const std::string &path, RaftClusterID cl
return new ShardDirectory(path);
}
ShardDirectory* ShardDirectory::create(const std::string &path, RaftClusterID clusterID, ShardID shardID, const std::vector<RaftServer> &nodes, LogIndex startIndex, std::unique_ptr<StateMachine> sm) {
initializeDirectory(path, clusterID, shardID);
ShardDirectory* ShardDirectory::create(const std::string &path, RaftClusterID clusterID, ShardID shardID, const std::vector<RaftServer> &nodes, LogIndex startIndex, std::unique_ptr<StateMachine> sm, Status &st) {
st = initializeDirectory(path, clusterID, shardID);
if(!st.ok()) {
return nullptr;
}
ShardDirectory *shardDirectory = new ShardDirectory(path);
shardDirectory->obliterate(clusterID, nodes, startIndex, std::move(sm) );
......
......@@ -27,6 +27,7 @@
#include <memory>
#include "Common.hh"
#include "Configuration.hh"
#include "Status.hh"
#include "utils/Resilvering.hh"
namespace quarkdb {
......@@ -67,10 +68,10 @@ public:
LogIndex startIndex, std::unique_ptr<StateMachine> existingContents);
// Create a standalone shard.
static ShardDirectory* create(const std::string &path, RaftClusterID clusterID, ShardID shardID, std::unique_ptr<StateMachine> sm);
static ShardDirectory* create(const std::string &path, RaftClusterID clusterID, ShardID shardID, std::unique_ptr<StateMachine> sm, Status &st);
// Create a consensus shard.
static ShardDirectory* create(const std::string &path, RaftClusterID clusterID, ShardID shardID, const std::vector<RaftServer> &nodes, LogIndex startIndex, std::unique_ptr<StateMachine> sm);
static ShardDirectory* create(const std::string &path, RaftClusterID clusterID, ShardID shardID, const std::vector<RaftServer> &nodes, LogIndex startIndex, std::unique_ptr<StateMachine> sm, Status &st);
std::unique_ptr<ShardSnapshot> takeSnapshot(const SnapshotID &id, std::string &err);
......@@ -117,7 +118,7 @@ private:
std::string getResilveringArena(const ResilveringEventID &id);
std::string getTempSnapshot(const SnapshotID &id);
static void initializeDirectory(const std::string &path, RaftClusterID clusterID, ShardID shardID);
static Status initializeDirectory(const std::string &path, RaftClusterID clusterID, ShardID shardID);
};
......
// ----------------------------------------------------------------------
// File: Status.hh
// Author: Georgios Bitzes - CERN
// ----------------------------------------------------------------------
/************************************************************************
* quarkdb - a redis-like highly available key-value store *
* Copyright (C) 2019 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
************************************************************************/
#ifndef QUARKDB_STATUS_H
#define QUARKDB_STATUS_H
#include "utils/Macros.hh"
namespace quarkdb {
//------------------------------------------------------------------------------
// Status object for operations which may fail
//------------------------------------------------------------------------------
class Status {
public:
//----------------------------------------------------------------------------
// Default constructor - status is OK, no error message.
//----------------------------------------------------------------------------
Status() : errcode(0) {}
//----------------------------------------------------------------------------
// Constructor with an error
//----------------------------------------------------------------------------
Status(int err, std::string_view msg) : errcode(err), errorMessage(msg) {}
//----------------------------------------------------------------------------
// Is status ok?
//----------------------------------------------------------------------------
bool ok() const {
return (errcode == 0);
}
//----------------------------------------------------------------------------
// Throw FatalException if not ok
//----------------------------------------------------------------------------
void assertOk() const {
if(!ok()) {
qdb_throw("Failure (" << errcode << "): " << errorMessage);
}
}
//----------------------------------------------------------------------------
// Get errorcode
//----------------------------------------------------------------------------
int getErrc() const {
return errcode;
}
//----------------------------------------------------------------------------
// Get error message
//----------------------------------------------------------------------------
std::string getMsg() const {
return errorMessage;
}
private:
int errcode;
std::string errorMessage;
};
}
#endif
......@@ -198,7 +198,9 @@ TEST(Bulkload, CreateConsensusShardFromExistingSM) {
std::unique_ptr<ShardDirectory> shardDir;
RaftServer srv("localhost", 123);
shardDir.reset(ShardDirectory::create("/tmp/quarkdb-tests-shard-from-existing-sm/shard", "cluster-id", "shar-id", {srv}, 99, std::move(sm) ));
Status st;
shardDir.reset(ShardDirectory::create("/tmp/quarkdb-tests-shard-from-existing-sm/shard", "cluster-id", "shar-id", {srv}, 99, std::move(sm), st ));
st.assertOk();
ASSERT_EQ(sm.get(), nullptr);
ASSERT_EQ(shardDir->getStateMachine()->getPhysicalLocation(), "/tmp/quarkdb-tests-shard-from-existing-sm/shard/current/state-machine");
......
......@@ -80,7 +80,9 @@ void GlobalEnv::TearDown() {
ShardDirectory* GlobalEnv::getShardDirectory(const std::string &path, RaftClusterID clusterID, const std::vector<RaftServer> &nodes) {
ShardDirectory *ret = shardDirCache[path];
if(ret == nullptr) {
ret = ShardDirectory::create(path, clusterID, "default", nodes, 0, {} );
Status st;
ret = ShardDirectory::create(path, clusterID, "default", nodes, 0, {}, st);
st.assertOk();
shardDirCache[path] = ret;
}
......
......@@ -141,6 +141,7 @@ int main(int argc, char** argv) {
stolenStateMachine.reset(new quarkdb::StateMachine(opts[Opt::STEAL_STATE_MACHINE].arg));
}
quarkdb::Status st;
std::unique_ptr<quarkdb::ShardDirectory> shardDirectory;
if(opts[Opt::CLUSTERID]) {
std::vector<quarkdb::RaftServer> nodes;
......@@ -153,10 +154,15 @@ int main(int argc, char** argv) {
qdb_info("--nodes were not specified. This new node will be 'in limbo' until it is contacted by an existing cluster, and cannot be used to start a new cluster from scratch. Run 'quarkdb-add-observer' on the leader of the existing cluster to add it.");
}
shardDirectory.reset(quarkdb::ShardDirectory::create(opts[Opt::PATH].arg, opts[Opt::CLUSTERID].arg, "default", nodes, journalStartingIndex, std::move(stolenStateMachine)));
shardDirectory.reset(quarkdb::ShardDirectory::create(opts[Opt::PATH].arg, opts[Opt::CLUSTERID].arg, "default", nodes, journalStartingIndex, std::move(stolenStateMachine), st));
}
else {
shardDirectory.reset(quarkdb::ShardDirectory::create(opts[Opt::PATH].arg, "null", "default", std::move(stolenStateMachine)));
shardDirectory.reset(quarkdb::ShardDirectory::create(opts[Opt::PATH].arg, "null", "default", std::move(stolenStateMachine), st));
}
if(!st.ok()) {
std::cerr << "Error " << st.getErrc() << ": " << st.getMsg() << std::endl;
return 1;
}
return 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment