forked from cheng/wallet
user friendly error handling of zooko names
Fixed it while dead drunk could not walk in a straight line had difficulty typing coded rather slowly, but still wrote smart code. Realized that the error handling has to have exception structures in scope, but not the constructors in scope You can forward the constructors, but if you forward the structs, exceptions will crash. Your exception constructor inputs can use structs that are out of scope at the exception handler
This commit is contained in:
parent
badd99b74b
commit
61db535769
18
src/ILog.h
18
src/ILog.h
@ -10,17 +10,25 @@ void ILogDebug(const char*);
|
||||
void queue_error_message(const char*); //Used for error conditions within a destructor because you cannot throw within a destructor
|
||||
void queue_fatal_error(const char*); //Used for fatal error conditions within a destructor in place of FatalException because you cannot throw within a destructor
|
||||
|
||||
struct sqlite3;
|
||||
|
||||
class MyException: public std::exception {
|
||||
private:
|
||||
std::string err;
|
||||
int err_number;
|
||||
public:
|
||||
virtual ~MyException() override = default;
|
||||
MyException() = delete;
|
||||
explicit MyException(const std::string &m) noexcept :err(m){}
|
||||
explicit MyException(const char* sz) noexcept :err(sz) {}
|
||||
explicit MyException(const std::string &m) noexcept :err(m.c_str()),err_number(-1){}
|
||||
explicit MyException(const char* sz) noexcept :err(sz),err_number(-1) {}
|
||||
explicit MyException(const char* sz, int i) noexcept :err(sz), err_number(i) {}
|
||||
explicit MyException(int, sqlite3*) noexcept;
|
||||
virtual const char* what() const override {
|
||||
return err.c_str();
|
||||
}
|
||||
virtual const int what_num() const {
|
||||
return err_number;
|
||||
}
|
||||
};
|
||||
|
||||
class FatalException : public MyException {
|
||||
@ -35,12 +43,6 @@ public:
|
||||
HashReuseException() noexcept;
|
||||
};
|
||||
|
||||
class SQLexception : public MyException {
|
||||
public:
|
||||
using MyException::MyException;
|
||||
SQLexception() noexcept;
|
||||
};
|
||||
|
||||
class NonUtf8DataInDatabase : public MyException {
|
||||
public:
|
||||
using MyException::MyException;
|
||||
|
@ -24,7 +24,7 @@ void sqlite3_init() {
|
||||
if (sqlite3_initialize() != SQLITE_OK) {
|
||||
errorCode = 7;
|
||||
szError = "Fatal Error: Sqlite library did not init.";
|
||||
// Cannot log the error, because logging not set up yet, so logging itself causes an exception
|
||||
// Cannot log the error, because logging not set up yet, so logging itself causes an exception
|
||||
throw FatalException(szError.c_str());
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ static int callback(void* NotUsed, int argc, char** argv, char** azColName) {
|
||||
std::string str;
|
||||
str.reserve(256);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
str =str + "\t\"" + azColName[i]+ R"|("=)|" + (argv[i]!=nullptr ? argv[i] : "NULL");
|
||||
str = str + "\t\"" + azColName[i] + R"|("=)|" + (argv[i] != nullptr ? argv[i] : "NULL");
|
||||
}
|
||||
ILogMessage(str.c_str());
|
||||
return 0;
|
||||
@ -52,7 +52,7 @@ public:
|
||||
pdb = nullptr;
|
||||
#endif
|
||||
int rc =sqlite3_open_v2(dbName, &pdb, flags, nullptr);
|
||||
if (rc != SQLITE_OK) throw SQLexception(error_message(rc, pdb));
|
||||
if (rc != SQLITE_OK) throw MyException(rc, pdb);
|
||||
assert(pdb != nullptr);
|
||||
// pdb can never be nullptr, since the sqlite3_open_v2 command always initializes
|
||||
// it even if open fails
|
||||
@ -62,7 +62,7 @@ public:
|
||||
char* zErrMsg = nullptr;
|
||||
int rc = sqlite3_exec(pdb, szsql, callback, nullptr, &zErrMsg);
|
||||
if (rc != SQLITE_OK) {
|
||||
SQLexception e(std::string("SQL Exec Error: ") + zErrMsg);
|
||||
auto e = MyException(zErrMsg, rc);
|
||||
sqlite3_free(zErrMsg);
|
||||
throw e;
|
||||
}
|
||||
@ -90,6 +90,11 @@ ISqlite3* Sqlite3_open(const char * db_name) {
|
||||
return new ISqlite3Impl(db_name, SQLITE_OPEN_READWRITE);
|
||||
}
|
||||
|
||||
MyException::MyException(int i, sqlite3* pdb) noexcept:
|
||||
err_number(i),
|
||||
err(error_message(i, pdb))
|
||||
{}
|
||||
|
||||
// Factory method to create database.
|
||||
ISqlite3 * Sqlite3_create(const char* db_name) {
|
||||
return new ISqlite3Impl(db_name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
@ -101,10 +106,10 @@ class IcompiledImpl_sql :
|
||||
friend class ISqlite3Impl;
|
||||
private:
|
||||
sqlite3_stmt *pStmt;
|
||||
ISqlite3Impl *pdbImplOwn;
|
||||
ISqlite3Impl*pdbImplOwn;
|
||||
auto e(int rc) {
|
||||
assert(rc != SQLITE_OK);
|
||||
return SQLexception(error_message(rc, pdbImplOwn->pdb));
|
||||
return MyException(rc, pdbImplOwn->pdb);
|
||||
}
|
||||
public:
|
||||
IcompiledImpl_sql() = delete;
|
||||
@ -192,7 +197,7 @@ public:
|
||||
// from n blocks to n+1 blocks when a single transaction updates the root and anciliary data.
|
||||
// We will build the blockchain hash table in postfix format, with patricia tree nodes that
|
||||
// have skiplink format stored only in memory and rebuilt each startup so that it grows append only,
|
||||
throw SQLexception("Abnormal busy database");
|
||||
throw MyException("Abnormal busy database", 2^14+2);
|
||||
break;
|
||||
case SQLITE_MISUSE:
|
||||
//ret = MISUSE;
|
||||
|
@ -114,8 +114,9 @@ namespace ro {
|
||||
result step() {
|
||||
return (*this)->Isqlite3_step();
|
||||
}
|
||||
|
||||
void final_step() {
|
||||
if (step() != result::DONE) throw SQLexception("SQL: Unexpected rows remaining");
|
||||
if (step() != result::DONE) throw MyException("SQL: Unexpected rows remaining", 16384);
|
||||
}
|
||||
void reset() {
|
||||
(*this)->Isqlite3_reset();
|
||||
@ -199,6 +200,15 @@ public:
|
||||
csql_into_names.do_one(psz);
|
||||
csql_namekey_into_keys.do_one(pt);
|
||||
}
|
||||
catch (const MyException& e) {
|
||||
csql_rollback.do_one();
|
||||
if (e.what_num() == 19) {
|
||||
throw MyException("Name already in database");
|
||||
}
|
||||
else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
csql_rollback.do_one();
|
||||
throw;
|
||||
|
@ -129,8 +129,6 @@ FatalException::FatalException() noexcept :
|
||||
MyException(R"|(unspecified fatal exception)|") {};
|
||||
HashReuseException::HashReuseException() noexcept :
|
||||
MyException(R"|(finalized the same hash constructor twice or more)|") {};
|
||||
SQLexception::SQLexception() noexcept :
|
||||
MyException(R"|(SQL Exception)|") {};
|
||||
BadDataException::BadDataException() noexcept :
|
||||
MyException(R"|(Bad data exception)|") {};
|
||||
NonUtf8DataInDatabase::NonUtf8DataInDatabase() noexcept :
|
||||
|
Loading…
Reference in New Issue
Block a user