0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-09-27 11:18:51 +02:00

ircd::db: Simplify/Consolidate error hierarchy.

This commit is contained in:
Jason Volk 2018-12-24 13:32:22 -08:00
parent aa166d0c5d
commit 2876398c04
4 changed files with 224 additions and 69 deletions

View file

@ -38,6 +38,7 @@ namespace rocksdb
struct SstFileWriter;
struct TableProperties;
struct LogFile;
struct Status;
}
//

View file

@ -15,6 +15,7 @@
namespace ircd::db
{
struct init;
struct error;
struct gopts;
struct sopts;
struct cell;
@ -24,26 +25,6 @@ namespace ircd::db
struct database;
struct options;
// Errors for the database subsystem. The exceptions that use _HIDENAME
// are built from RocksDB errors which already have an info string with
// an included name.
//
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, not_found)
IRCD_EXCEPTION(error, schema_error)
IRCD_EXCEPTION_HIDENAME(error, corruption)
IRCD_EXCEPTION_HIDENAME(error, not_supported)
IRCD_EXCEPTION_HIDENAME(error, invalid_argument)
IRCD_EXCEPTION_HIDENAME(error, io_error)
IRCD_EXCEPTION_HIDENAME(error, merge_in_progress)
IRCD_EXCEPTION_HIDENAME(error, incomplete)
IRCD_EXCEPTION_HIDENAME(error, shutdown_in_progress)
IRCD_EXCEPTION_HIDENAME(error, timed_out)
IRCD_EXCEPTION_HIDENAME(error, aborted)
IRCD_EXCEPTION_HIDENAME(error, busy)
IRCD_EXCEPTION_HIDENAME(error, expired)
IRCD_EXCEPTION_HIDENAME(error, try_again)
// db subsystem has its own logging facility
extern struct log::log log;
@ -71,6 +52,7 @@ namespace ircd::db
#include "database/snapshot.h"
#include "database/sst.h"
#include "database/wal.h"
#include "error.h"
#include "cache.h"
#include "opts.h"
#include "column.h"

91
include/ircd/db/error.h Normal file
View file

@ -0,0 +1,91 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_DB_ERROR_H
namespace ircd::db
{
struct error;
}
/// Database error. For most catchers of this error outside of the db:: system,
/// the formatted what() message will be sufficient. The codes are not useful
/// outside of db::. A common error `not_found` has its own subtype to be
/// caught independently;
///
struct ircd::db::error
:ircd::error
{
struct not_found;
protected:
static const rocksdb::Status _no_code_;
public:
uint8_t code {0};
uint8_t subcode {0};
uint8_t severity {0};
error(generate_skip_t,
const rocksdb::Status &);
explicit
error(const rocksdb::Status &);
IRCD_OVERLOAD(internal)
error(internal_t,
const rocksdb::Status &s,
const string_view &fmt,
const va_rtti &ap);
template<class... args>
error(const rocksdb::Status &s,
const string_view &fmt,
args&&... a)
:error
{
internal, s, fmt, va_rtti{std::forward<args>(a)...}
}{}
template<class... args>
error(const string_view &fmt,
args&&... a)
:error
{
internal, _no_code_, fmt, va_rtti{std::forward<args>(a)...}
}{}
};
namespace ircd::db
{
using not_found = error::not_found;
}
/// Common error `not_found` has its own subtype to be caught independently;
/// it may contain a more limited what() (or none at all) as an optimization.
///
struct ircd::db::error::not_found
:error
{
protected:
static const rocksdb::Status _not_found_;
public:
template<class... args>
not_found(const string_view &fmt,
args&&... a)
:error
{
_not_found_, fmt, std::forward<args>(a)...
}{}
not_found();
};

View file

@ -1371,14 +1371,9 @@ try
d->GetLatestSequenceNumber()
};
}
catch(const corruption &e)
catch(const error &e)
{
throw corruption
{
"Corruption for '%s' (%s). Try restarting with the -pitrecdb command line option",
this->name,
e.what()
};
throw;
}
catch(const std::exception &e)
{
@ -1535,7 +1530,7 @@ ircd::db::database::operator[](const string_view &name)
{
const auto it{column_names.find(name)};
if(unlikely(it == std::end(column_names)))
throw schema_error
throw not_found
{
"'%s': column '%s' is not available or specified in schema",
this->name,
@ -1555,7 +1550,7 @@ try
}
catch(const std::out_of_range &e)
{
throw schema_error
throw not_found
{
"'%s': column id[%u] is not available or specified in schema",
this->name,
@ -1569,7 +1564,7 @@ const
{
const auto it{column_names.find(name)};
if(unlikely(it == std::end(column_names)))
throw schema_error
throw not_found
{
"'%s': column '%s' is not available or specified in schema",
this->name,
@ -1589,7 +1584,7 @@ const try
}
catch(const std::out_of_range &e)
{
throw schema_error
throw not_found
{
"'%s': column id[%u] is not available or specified in schema",
this->name,
@ -9167,7 +9162,7 @@ ircd::db::row::operator[](const string_view &column)
{
const auto it(find(column));
if(unlikely(it == end()))
throw schema_error
throw not_found
{
"column '%s' not specified in the descriptor schema", column
};
@ -9181,7 +9176,7 @@ const
{
const auto it(find(column));
if(unlikely(it == end()))
throw schema_error
throw not_found
{
"column '%s' not specified in the descriptor schema", column
};
@ -10994,11 +10989,133 @@ ircd::db::ticker(const rocksdb::Cache &cache,
zero;
}
///////////////////////////////////////////////////////////////////////////////
//
// error.h
//
//
// error::not_found
//
decltype(ircd::db::error::not_found::_not_found_)
ircd::db::error::not_found::_not_found_
{
rocksdb::Status::NotFound()
};
//
// error::not_found::not_found
//
ircd::db::error::not_found::not_found()
:error
{
generate_skip, _not_found_
}
{
strlcpy(buf, "NotFound");
}
//
// error
//
decltype(ircd::db::error::_no_code_)
ircd::db::error::_no_code_
{
rocksdb::Status::OK()
};
//
// error::error
//
ircd::db::error::error(internal_t,
const rocksdb::Status &s,
const string_view &fmt,
const va_rtti &ap)
:error
{
s
}
{
const string_view &msg{buf};
const mutable_buffer remain
{
buf + size(msg), sizeof(buf) - size(msg)
};
fmt::vsprintf
{
remain, fmt, ap
};
}
ircd::db::error::error(const rocksdb::Status &s)
:error
{
generate_skip, s
}
{
fmt::sprintf
{
buf, "%s (%u:%u): %s (%u)",
s.getState(),
this->code,
this->subcode,
reflect(s.severity()),
this->severity,
};
}
ircd::db::error::error(generate_skip_t,
const rocksdb::Status &s)
:ircd::error
{
generate_skip
}
,code
{
s.code()
}
,subcode
{
s.subcode()
}
,severity
{
s.severity()
}
{
}
///////////////////////////////////////////////////////////////////////////////
//
// Misc
//
//
// throw_on_error
//
ircd::db::throw_on_error::throw_on_error(const rocksdb::Status &status)
{
using rocksdb::Status;
switch(status.code())
{
case Status::kOk:
return;
case Status::kNotFound:
throw not_found{};
default:
throw error{status};
}
}
std::vector<std::string>
ircd::db::column_names(const std::string &path,
const std::string &options)
@ -11324,42 +11441,6 @@ ircd::db::error_to_status::error_to_status(const std::error_code &e)
{
}
//
// throw_on_error
//
ircd::db::throw_on_error::throw_on_error(const rocksdb::Status &s)
{
using rocksdb::Status;
const string_view &message
{
s.getState()
};
switch(s.code())
{
case Status::kOk: return;
case Status::kNotFound: throw not_found{"%s", message};
case Status::kCorruption: throw corruption{"%s", message};
case Status::kNotSupported: throw not_supported{"%s", message};
case Status::kInvalidArgument: throw invalid_argument{"%s", message};
case Status::kIOError: throw io_error{"%s", message};
case Status::kMergeInProgress: throw merge_in_progress{"%s", message};
case Status::kIncomplete: throw incomplete{"%s", message};
case Status::kShutdownInProgress: throw shutdown_in_progress{"%s", message};
case Status::kTimedOut: throw timed_out{"%s", message};
case Status::kAborted: throw aborted{"%s", message};
case Status::kBusy: throw busy{"%s", message};
case Status::kExpired: throw expired{"%s", message};
case Status::kTryAgain: throw try_again{"%s", message};
default: throw error
{
"code[%d] %s", s.code(), message
};
}
}
//
//
//