Skip to content

Commit

Permalink
Replace std::runtime_error with limestone_exception
Browse files Browse the repository at this point in the history
  • Loading branch information
umegane committed Sep 18, 2024
1 parent caf6f42 commit 4578abe
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 139 deletions.
31 changes: 11 additions & 20 deletions src/limestone/datastore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <glog/logging.h>
#include <limestone/logging.h>
#include "logging_helper.h"
#include "limestone_exception_helper.h"

#include <limestone/api/datastore.h>
#include "internal.h"
Expand All @@ -47,8 +48,7 @@ datastore::datastore(configuration const& conf) : location_(conf.data_locations_
if (!result_check || error) {
const bool result_mkdir = boost::filesystem::create_directory(location_, error);
if (!result_mkdir || error) {
LOG_LP(ERROR) << "fail to create directory: result_mkdir: " << result_mkdir << ", error_code: " << error << ", path: " << location_;
throw std::runtime_error("fail to create the log_location directory");
LOG_AND_THROW_IO_EXCEPTION("fail to create directory: result_mkdir: " + location_.string(), error);
}
internal::setup_initial_logdir(location_);
add_file(manifest_path);
Expand Down Expand Up @@ -77,12 +77,10 @@ datastore::datastore(configuration const& conf) : location_(conf.data_locations_
if (!result || error) {
FILE* strm = fopen(epoch_file_path_.c_str(), "a"); // NOLINT(*-owning-memory)
if (!strm) {
LOG_LP(ERROR) << "does not have write permission for the log_location directory, path: " << location_;
throw std::runtime_error("does not have write permission for the log_location directory");
LOG_AND_THROW_IO_EXCEPTION("does not have write permission for the log_location directory, path: " + location_.string(), errno);
}
if (fclose(strm) != 0) { // NOLINT(*-owning-memory)
LOG_LP(ERROR) << "fclose failed, errno = " << errno;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("fclose failed", errno);
}
add_file(epoch_file_path_);
}
Expand Down Expand Up @@ -114,13 +112,11 @@ void datastore::ready() {
boost::filesystem::directory_iterator it(location_, error);
boost::filesystem::directory_iterator end;
if (error) {
LOG_LP(ERROR) << "Failed to initialize directory iterator: error_code: " << error.message() << ", path: " << location_;
throw std::runtime_error("Failed to initialize directory iterator");
LOG_AND_THROW_IO_EXCEPTION("Failed to initialize directory iterator, path: " + location_.string(), error);
}
for (; it != end; it.increment(error)) {
if (error) {
LOG_LP(ERROR) << "Failed to access directory entry: error_code: " << error.message() << ", path: " << location_;
throw std::runtime_error("Failed to iterate over the directory entries");
LOG_AND_THROW_IO_EXCEPTION("Failed to access directory entry: , path: " + location_.string(), error);
}
if (boost::filesystem::is_regular_file(it->path())) {
std::string filename = it->path().filename().string();
Expand Down Expand Up @@ -200,21 +196,17 @@ void datastore::update_min_epoch_id(bool from_switch_epoch) { // NOLINT(readabi

FILE* strm = fopen(epoch_file_path_.c_str(), "a"); // NOLINT(*-owning-memory)
if (!strm) {
LOG_LP(ERROR) << "fopen failed, errno = " << errno;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("fopen failed", errno);
}
log_entry::durable_epoch(strm, static_cast<epoch_id_type>(epoch_id_recorded_.load()));
if (fflush(strm) != 0) {
LOG_LP(ERROR) << "fflush failed, errno = " << errno;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("fflush failed", errno);
}
if (fsync(fileno(strm)) != 0) {
LOG_LP(ERROR) << "fsync failed, errno = " << errno;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("fsync failed", errno);
}
if (fclose(strm) != 0) { // NOLINT(*-owning-memory)
LOG_LP(ERROR) << "fclose failed, errno = " << errno;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("fclose failed", errno);
}
break;
}
Expand Down Expand Up @@ -400,8 +392,7 @@ void datastore::rotate_epoch_file() {
boost::filesystem::ofstream strm{};
strm.open(epoch_file_path_, std::ios_base::out | std::ios_base::app | std::ios_base::binary);
if(!strm || !strm.is_open() || strm.bad() || strm.fail()){
LOG_LP(ERROR) << "does not have write permission for the log_location directory, path: " << location_;
throw std::runtime_error("does not have write permission for the log_location directory");
THROW_LIMESTONE_IO_EXCEPTION("does not have write permission for the log_location directory, path: " + location_.string(), errno);
}
strm.close();
}
Expand Down
66 changes: 34 additions & 32 deletions src/limestone/datastore_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <limestone/api/datastore.h>

#include "limestone_exception_helper.h"
#include "compaction_catalog.h"
#include "internal.h"
#include "log_entry.h"
Expand All @@ -43,31 +44,26 @@ void setup_initial_logdir(const boost::filesystem::path& logdir) {
boost::filesystem::path config = logdir / std::string(manifest_file_name);
FILE* strm = fopen(config.c_str(), "w"); // NOLINT(*-owning-memory)
if (!strm) {
std::string err_msg = "Failed to open file for writing: " + config.string() + ". errno = " + std::to_string(errno);
LOG_LP(ERROR) << err_msg;
throw std::runtime_error(err_msg);
std::string err_msg = "Failed to open file for writing: " + config.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, errno);
}
std::string manifest_str = manifest_v2.dump(4);
auto ret = fwrite(manifest_str.c_str(), manifest_str.length(), 1, strm);
if (ret != 1) {
std::string err_msg = "Failed to write to file: " + config.string() + ". errno = " + std::to_string(errno);
LOG_LP(ERROR) << err_msg;
throw std::runtime_error(err_msg);
std::string err_msg = "Failed to write to file: " + config.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, errno);
}
if (fflush(strm) != 0) {
std::string err_msg = "Failed to flush file buffer: " + config.string() + ". errno = " + std::to_string(errno);
LOG_LP(ERROR) << err_msg;
throw std::runtime_error(err_msg);
std::string err_msg = "Failed to flush file buffer: " + config.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, errno);
}
if (fsync(fileno(strm)) != 0) {
std::string err_msg = "Failed to sync file to disk: " + config.string() + ". errno = " + std::to_string(errno);
LOG_LP(ERROR) << err_msg;
throw std::runtime_error(err_msg);
std::string err_msg = "Failed to sync file to disk: " + config.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, errno);
}
if (fclose(strm) != 0) { // NOLINT(*-owning-memory)
std::string err_msg = "Failed to close file: " + config.string() + ". errno = " + std::to_string(errno);
LOG_LP(ERROR) << err_msg;
throw std::runtime_error(err_msg);
std::string err_msg = "Failed to close file: " + config.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, errno);
}
// Create compaction catalog file
compaction_catalog catalog(logdir);
Expand Down Expand Up @@ -105,65 +101,71 @@ int is_supported_version(const boost::filesystem::path& manifest_path, std::stri
}
}

bool exists_path(const boost::filesystem::path& path) {
boost::system::error_code ec;
bool ret = boost::filesystem::exists(path, ec);
if (!ret && ec != boost::system::errc::no_such_file_or_directory) {
std::string err_msg = "Failed to check if file exists: " + path.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, ec);
}
return ret;
}


void check_and_migrate_logdir_format(const boost::filesystem::path& logdir) {
boost::filesystem::path manifest_path = logdir / std::string(manifest_file_name);
boost::filesystem::path manifest_backup_path = logdir / std::string(manifest_file_backup_name);
boost::system::error_code ec;

if (!boost::filesystem::exists(manifest_path) && boost::filesystem::exists(manifest_backup_path)) {
if (!exists_path(manifest_path) && exists_path(manifest_backup_path)) {
VLOG_LP(log_info) << "Manifest file is missing, but a backup file exists at " << manifest_backup_path.string()
<< ". Using the backup file as the manifest by renaming it to " << manifest_path.string();
boost::filesystem::rename(manifest_backup_path, manifest_path, ec);
if (ec) {
std::string err_msg =
"Failed to rename manifest backup from " + manifest_backup_path.string() + " to " + manifest_path.string() + ". Error: " + ec.message();
LOG(ERROR) << err_msg;
throw std::runtime_error(err_msg);
"Failed to rename manifest backup from " + manifest_backup_path.string() + " to " + manifest_path.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, ec);
}
}

if (boost::filesystem::exists(manifest_path) && boost::filesystem::exists(manifest_backup_path)) {
if (exists_path(manifest_path) && exists_path(manifest_backup_path)) {
VLOG_LP(log_info) << "both manifest and backup manifest file exists, removing backup manifest file";
boost::filesystem::remove(manifest_backup_path, ec);
if (ec) {
std::string err_msg = "Failed to remove backup manifest file: " + manifest_backup_path.string() + ". Error: " + ec.message();
LOG(ERROR) << err_msg;
throw std::runtime_error(err_msg);
std::string err_msg = "Failed to remove backup manifest file: " + manifest_backup_path.string();
LOG_AND_THROW_IO_EXCEPTION(err_msg, ec);
}
}

if (!boost::filesystem::exists(manifest_path)) {
if (!exists_path(manifest_path)) {
VLOG_LP(log_info) << "no manifest file in logdir, maybe v0";
LOG(ERROR) << version_error_prefix << " (version mismatch: version 0, server supports version 1)";
throw std::runtime_error("logdir version mismatch");
THROW_LIMESTONE_EXCEPTION(std::string(version_error_prefix) + " (version mismatch: version 0, server supports version 1)");
}
std::string errmsg;
int vc = is_supported_version(manifest_path, errmsg);
if (vc == 0) {
LOG(ERROR) << version_error_prefix << " (" << errmsg << ")";
throw std::runtime_error("logdir version mismatch");
THROW_LIMESTONE_EXCEPTION("logdir version mismatch");
}
if (vc < 0) {
VLOG_LP(log_info) << errmsg;
LOG(ERROR) << "/:limestone dbdir is corrupted, can not use.";
throw std::runtime_error("logdir corrupted");
THROW_LIMESTONE_EXCEPTION("logdir corrupted");
}
if (vc == 1) {
// migrate to version 2
VLOG_LP(log_info) << "migrating from version 1 to version 2";
boost::filesystem::rename(manifest_path, manifest_backup_path, ec);
if (ec) {
std::string err_msg = "Failed to rename manifest file: " + manifest_path.string() + " to " + manifest_backup_path.string() + ". Error: " + ec.message();
LOG(ERROR) << err_msg;
throw std::runtime_error(err_msg);
LOG_AND_THROW_IO_EXCEPTION(err_msg, ec);
}
setup_initial_logdir(logdir);
VLOG_LP(log_info) << "migration done";
boost::filesystem::remove(manifest_backup_path, ec);
if (ec) {
std::string err_msg = "Failed to remove backup manifest file: " + manifest_backup_path.string() + ". Error: " + ec.message();
LOG(ERROR) << err_msg;
throw std::runtime_error(err_msg);
LOG_AND_THROW_IO_EXCEPTION(err_msg, ec);
}
}
}
Expand Down
23 changes: 9 additions & 14 deletions src/limestone/datastore_snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "logging_helper.h"

#include <limestone/api/datastore.h>
#include "limestone_exception_helper.h"
#include "dblog_scan.h"
#include "internal.h"
#include "log_entry.h"
Expand Down Expand Up @@ -175,12 +176,12 @@ static std::pair<epoch_id_type, sorting_context> create_sorted_from_wals(
try {
epoch_id_type max_appeared_epoch = logscan.scan_pwal_files_throws(ld_epoch, add_entry);
return {max_appeared_epoch, std::move(sctx)};
} catch (std::runtime_error& e) {
} catch (limestone_exception& e) {
VLOG_LP(log_info) << "failed to scan pwal files: " << e.what();
LOG(ERROR) << "/:limestone recover process failed. (cause: corruption detected in transaction log data directory), "
<< "see https://github.com/project-tsurugi/tsurugidb/blob/master/docs/troubleshooting-guide.md";
LOG(ERROR) << "/:limestone dblogdir (transaction log directory): " << from_dir;
throw std::runtime_error("dblogdir is corrupted");
throw limestone_exception("dblogdir is corrupted");
}
}

Expand Down Expand Up @@ -267,17 +268,15 @@ void create_compact_pwal(
if (!result_check || error) {
const bool result_mkdir = boost::filesystem::create_directory(to_dir, error);
if (!result_mkdir || error) {
LOG_LP(ERROR) << "fail to create directory " << to_dir;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("fail to create directory " + to_dir.string(), error);
}
}

boost::filesystem::path snapshot_file = to_dir / boost::filesystem::path("pwal_0000.compacted");
VLOG_LP(log_info) << "generating compacted pwal file: " << snapshot_file;
FILE* ostrm = fopen(snapshot_file.c_str(), "w"); // NOLINT(*-owning-memory)
if (!ostrm) {
LOG_LP(ERROR) << "cannot create snapshot file (" << snapshot_file << ")";
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("cannot create snapshot file (" + snapshot_file.string() + ")", errno);
}
setvbuf(ostrm, nullptr, _IOFBF, 128L * 1024L); // NOLINT, NB. glibc may ignore size when _IOFBF and buffer=NULL
bool rewind = true; // TODO: change by flag
Expand All @@ -296,8 +295,7 @@ void create_compact_pwal(
sortdb_foreach(sctx, write_snapshot_entry);
//log_entry::end_session(ostrm, epoch);
if (fclose(ostrm) != 0) { // NOLINT(*-owning-memory)
LOG_LP(ERROR) << "cannot close snapshot file (" << snapshot_file << "), errno = " << errno;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("cannot close snapshot file (" + snapshot_file.string() + ")", errno);
}
}

Expand All @@ -318,24 +316,21 @@ void datastore::create_snapshot(const std::set<std::string>& file_names) {
if (!result_check || error) {
const bool result_mkdir = boost::filesystem::create_directory(sub_dir, error);
if (!result_mkdir || error) {
LOG_LP(ERROR) << "fail to create directory";
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("fail to create directory", error);
}
}

boost::filesystem::path snapshot_file = sub_dir / boost::filesystem::path(std::string(snapshot::file_name_));
VLOG_LP(log_info) << "generating snapshot file: " << snapshot_file;
FILE* ostrm = fopen(snapshot_file.c_str(), "w"); // NOLINT(*-owning-memory)
if (!ostrm) {
LOG_LP(ERROR) << "cannot create snapshot file (" << snapshot_file << ")";
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("cannot create snapshot file", errno);
}
setvbuf(ostrm, nullptr, _IOFBF, 128L * 1024L); // NOLINT, NB. glibc may ignore size when _IOFBF and buffer=NULL
auto write_snapshot_entry = [&ostrm](std::string_view key, std::string_view value){log_entry::write(ostrm, key, value);};
sortdb_foreach(sctx, write_snapshot_entry);
if (fclose(ostrm) != 0) { // NOLINT(*-owning-memory)
LOG_LP(ERROR) << "cannot close snapshot file (" << snapshot_file << "), errno = " << errno;
throw std::runtime_error("I/O error");
LOG_AND_THROW_IO_EXCEPTION("cannot close snapshot file (" + snapshot_file.string() + ")", errno);
}
}

Expand Down
22 changes: 10 additions & 12 deletions src/limestone/dblog_scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <glog/logging.h>
#include <limestone/logging.h>
#include "logging_helper.h"
#include "limestone_exception_helper.h"

#include <limestone/api/datastore.h>
#include "internal.h"
Expand All @@ -40,13 +41,11 @@ std::optional<epoch_id_type> last_durable_epoch(const boost::filesystem::path& f
// ASSERT: file exists
istrm.open(file, std::ios_base::in | std::ios_base::binary);
if (!istrm) { // permission?
LOG_LP(ERROR) << "cannot read epoch file: " << file;
throw std::runtime_error("cannot read epoch file");
THROW_LIMESTONE_IO_EXCEPTION("cannot read epoch file: " + file.string(), errno);
}
while (e.read(istrm)) {
if (e.type() != log_entry::entry_type::marker_durable) {
LOG_LP(ERROR) << "this epoch file is broken: unexpected log_entry type: " << static_cast<int>(e.type());
throw std::runtime_error("unexpected log_entry type for epoch file");
LOG_AND_THROW_EXCEPTION("this epoch file is broken: unexpected log_entry type: " + std::to_string(static_cast<int>(e.type())));
}
if (!rv.has_value() || e.epoch_id() > rv) {
rv = e.epoch_id();
Expand All @@ -63,8 +62,7 @@ epoch_id_type dblog_scan::last_durable_epoch_in_dir() {
if (!boost::filesystem::exists(main_epoch_file)) {
// datastore operations (ctor and rotate) ensure that the main epoch file exists.
// so it may directory called from outside of datastore
LOG_LP(ERROR) << "epoch file does not exist: " << main_epoch_file;
throw std::runtime_error("epoch file does not exist");
LOG_AND_THROW_EXCEPTION("epoch file does not exist: " + main_epoch_file.string());
}
std::optional<epoch_id_type> ld_epoch = last_durable_epoch(main_epoch_file);
if (ld_epoch.has_value()) {
Expand All @@ -90,8 +88,8 @@ epoch_id_type dblog_scan::last_durable_epoch_in_dir() {
}

static bool log_error_and_throw(log_entry::read_error& e) {
LOG_LP(ERROR) << "this pwal file is broken: " << e.message();
throw std::runtime_error("pwal file read error");
LOG_AND_THROW_EXCEPTION("this pwal file is broken: " + e.message());
return false;
}

void dblog_scan::detach_wal_files(bool skip_empty_files) {
Expand Down Expand Up @@ -144,7 +142,7 @@ epoch_id_type dblog_scan::scan_pwal_files( // NOLINT(readability-function-cogni
if (!is_detached_wal(p)) {
VLOG(30) << "MARKED BUT TAIL IS BROKEN (NOT DETACHED): " << p;
if (fail_fast_) {
throw std::runtime_error("the end of non-detached file is broken");
THROW_LIMESTONE_EXCEPTION("the end of non-detached file is broken");
}
} else {
VLOG(30) << "MARKED BUT TAIL IS BROKEN (DETACHED): " << p;
Expand All @@ -155,7 +153,7 @@ epoch_id_type dblog_scan::scan_pwal_files( // NOLINT(readability-function-cogni
VLOG(30) << "TAIL IS BROKEN: " << p;
if (!is_detached_wal(p)) {
if (fail_fast_) {
throw std::runtime_error("the end of non-detached file is broken");
THROW_LIMESTONE_EXCEPTION("the end of non-detached file is broken");
}
}
break;
Expand All @@ -166,7 +164,7 @@ epoch_id_type dblog_scan::scan_pwal_files( // NOLINT(readability-function-cogni
case parse_error::failed:
VLOG(30) << "ERROR: " << p;
if (fail_fast_) {
throw std::runtime_error(ec.message());
THROW_LIMESTONE_EXCEPTION(ec.message());
}
break;
case parse_error::broken_after_tobe_cut: assert(false);
Expand Down Expand Up @@ -204,7 +202,7 @@ epoch_id_type dblog_scan::scan_pwal_files( // NOLINT(readability-function-cogni

try {
process_file(p);
} catch (std::runtime_error& ex) {
} catch (limestone_exception& ex) {
VLOG(log_info) << "/:limestone catch runtime_error(" << ex.what() << ")";
{
std::lock_guard<std::mutex> lock(list_mtx);
Expand Down
Loading

0 comments on commit 4578abe

Please sign in to comment.