Coverity (#28)
* stratum_server: resolve CID 210144 (UNINIT_CTOR)
* stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_blockchain_update_listener, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro
A temporary substition for what I hope will eventually be a full-fledged
exception-dispatcher (class-based, not macro).
* stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_protocol_handler, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT)
The potential to throw exists within guarded_critical_region_t, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger, del_connection, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: move macros to *top* of file
so they can be used *within* this file.
* daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT)
The potential to throw exists within log_space, and any paths involving
the logger (including CATCH_ENTRY_*).
* daemon: return cstdlib proper types in main
* simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT)
CID: 210082
CID: 210086
CID: 210096
CID: 210147
CID: 210149
CID: 210150
The potential to throw exists throughout various paths in main.
* simplewallet: return cstdlib proper types in main
* simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, and any paths
involving the logger (including CATCH_ENTRY_*).
* conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT)
CID: 210038
CID: 210047
CID: 210108
CID: 210122
CID: 210157
The potential to throw exists throughout various paths in main.
* conn_tool: return cstdlib proper types in main
* miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT)
The potential to throw exists within deinit, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT)
The potential to throw exists within boost microsec_clock::localtime(),
and any paths involving the logger (including CATCH_ENTRY_*).
* db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT)
The potential to throw exists within close(), including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT)
The potential to throw exists within several paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210064
CID: 210093
CID: 210136
CID: 210139
The potential to throw exists within m_func(), including any paths
involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210072
CID: 210094
CID: 210116
CID: 210141
The potential to throw exists within m_cache.clear(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT)
The potential to throw exists within shutdown(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT)
The potential to throw exists within unlock(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: http_base: resolve CID 210176 (UNINIT_CTOR)
* p2p: net_node: resolve CID 210173 (UNINIT_CTOR)
* epee: net_helper: resolve CID 210138 (UNINIT_CTOR)
* p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR)
* currency_basic: resolve CID 210117 (UNINIT_CTOR)
* epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR)
CID: 210040
CID: 210090
CID: 210105
* simplewallet: resolve CID 210103 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR)
* json_archive: resolve CID 210087 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR)
* miniupnp_helper: resolve CID 210037 (UNINIT_CTOR)
* crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN)
* wallet2: resolve CID 210041 (CHECKED_RETURN)
* epee: misc_log_ex: resolve CID 210127 (DEADCODE)
* epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE)
CID: 210167
CID: 210170
CID: 210180
* p2p: net_node: resolve CID 210065 (PASS_BY_VALUE)
* epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE)
* epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE)
* epee: misc_log_ex: add NESTED_*_ENTRY macros
* simplewallet: use NESTED_*_ENTRY in message_writer dtor
* stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor
* stratum_protocol_handler: use NESTED_*_ENTRY in dtor
* lmdb_db_backend: use NESTED_*_ENTRY in dtor
* epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210088
CID: 210106
CID: 210164
CID: 210179
The potential to throw exists within various paths, including any
paths involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: use NESTED_*_ENTRY in dtor
* miniupnp_helper: use NESTED_*_ENTRY in dtor
* epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor
* epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors
* epee: net_helper: use NESTED_*_ENTRY in dtor
* epee: profile_tools: use NESTED_*_ENTRY in dtors
* epee: misc_language: use NESTED_*_ENTRY in dtor
* epee: syncobj: use NESTED_*_ENTRY in dtor
* zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
|
|
|
// Copyright (c) 2014-2019 Zano Project
|
2018-12-27 18:50:45 +03:00
|
|
|
// Copyright (c) 2014-2018 The Louisdor Project
|
|
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
|
|
#include "db_backend_lmdb.h"
|
|
|
|
|
#include "misc_language.h"
|
|
|
|
|
#include "string_coding.h"
|
|
|
|
|
#include "profile_tools.h"
|
2019-08-10 05:31:47 +03:00
|
|
|
#include "util.h"
|
2018-12-27 18:50:45 +03:00
|
|
|
|
|
|
|
|
#define BUF_SIZE 1024
|
2019-08-13 19:59:44 +03:00
|
|
|
#define DB_RESIZE_MIN_FREE_SIZE (100 * 1024 * 1024) // DB map size will grow if that much space left on DB
|
|
|
|
|
#define DB_RESIZE_MIN_MAX_SIZE (50 * 1024 * 1024) // Minimum DB map size (starting size)
|
|
|
|
|
#define DB_RESIZE_INCREMENT_SIZE (100 * 1024 * 1024) // Grow step size
|
|
|
|
|
#define DB_RESIZE_COMMITS_TO_CHECK 50
|
2018-12-27 18:50:45 +03:00
|
|
|
|
|
|
|
|
#define CHECK_AND_ASSERT_MESS_LMDB_DB(rc, ret, mess) CHECK_AND_ASSERT_MES(res == MDB_SUCCESS, ret, "[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess);
|
2019-06-06 23:08:21 +03:00
|
|
|
#define CHECK_AND_ASSERT_THROW_MESS_LMDB_DB(rc, mess) CHECK_AND_ASSERT_THROW_MES(res == MDB_SUCCESS, "[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess);
|
|
|
|
|
#define ASSERT_MES_AND_THROW_LMDB(rc, mess) ASSERT_MES_AND_THROW("[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess);
|
2018-12-27 18:50:45 +03:00
|
|
|
|
|
|
|
|
#undef LOG_DEFAULT_CHANNEL
|
|
|
|
|
#define LOG_DEFAULT_CHANNEL "lmdb"
|
|
|
|
|
// 'lmdb' channel is disabled by default
|
|
|
|
|
|
|
|
|
|
namespace tools
|
|
|
|
|
{
|
|
|
|
|
namespace db
|
|
|
|
|
{
|
2019-08-13 19:59:44 +03:00
|
|
|
lmdb_db_backend::lmdb_db_backend()
|
|
|
|
|
: m_penv(AUTO_VAL_INIT(m_penv))
|
|
|
|
|
, m_commits_count(0)
|
2018-12-27 18:50:45 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
2019-08-13 19:59:44 +03:00
|
|
|
|
2018-12-27 18:50:45 +03:00
|
|
|
lmdb_db_backend::~lmdb_db_backend()
|
|
|
|
|
{
|
Coverity (#28)
* stratum_server: resolve CID 210144 (UNINIT_CTOR)
* stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_blockchain_update_listener, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro
A temporary substition for what I hope will eventually be a full-fledged
exception-dispatcher (class-based, not macro).
* stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_protocol_handler, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT)
The potential to throw exists within guarded_critical_region_t, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger, del_connection, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: move macros to *top* of file
so they can be used *within* this file.
* daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT)
The potential to throw exists within log_space, and any paths involving
the logger (including CATCH_ENTRY_*).
* daemon: return cstdlib proper types in main
* simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT)
CID: 210082
CID: 210086
CID: 210096
CID: 210147
CID: 210149
CID: 210150
The potential to throw exists throughout various paths in main.
* simplewallet: return cstdlib proper types in main
* simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, and any paths
involving the logger (including CATCH_ENTRY_*).
* conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT)
CID: 210038
CID: 210047
CID: 210108
CID: 210122
CID: 210157
The potential to throw exists throughout various paths in main.
* conn_tool: return cstdlib proper types in main
* miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT)
The potential to throw exists within deinit, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT)
The potential to throw exists within boost microsec_clock::localtime(),
and any paths involving the logger (including CATCH_ENTRY_*).
* db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT)
The potential to throw exists within close(), including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT)
The potential to throw exists within several paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210064
CID: 210093
CID: 210136
CID: 210139
The potential to throw exists within m_func(), including any paths
involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210072
CID: 210094
CID: 210116
CID: 210141
The potential to throw exists within m_cache.clear(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT)
The potential to throw exists within shutdown(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT)
The potential to throw exists within unlock(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: http_base: resolve CID 210176 (UNINIT_CTOR)
* p2p: net_node: resolve CID 210173 (UNINIT_CTOR)
* epee: net_helper: resolve CID 210138 (UNINIT_CTOR)
* p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR)
* currency_basic: resolve CID 210117 (UNINIT_CTOR)
* epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR)
CID: 210040
CID: 210090
CID: 210105
* simplewallet: resolve CID 210103 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR)
* json_archive: resolve CID 210087 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR)
* miniupnp_helper: resolve CID 210037 (UNINIT_CTOR)
* crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN)
* wallet2: resolve CID 210041 (CHECKED_RETURN)
* epee: misc_log_ex: resolve CID 210127 (DEADCODE)
* epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE)
CID: 210167
CID: 210170
CID: 210180
* p2p: net_node: resolve CID 210065 (PASS_BY_VALUE)
* epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE)
* epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE)
* epee: misc_log_ex: add NESTED_*_ENTRY macros
* simplewallet: use NESTED_*_ENTRY in message_writer dtor
* stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor
* stratum_protocol_handler: use NESTED_*_ENTRY in dtor
* lmdb_db_backend: use NESTED_*_ENTRY in dtor
* epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210088
CID: 210106
CID: 210164
CID: 210179
The potential to throw exists within various paths, including any
paths involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: use NESTED_*_ENTRY in dtor
* miniupnp_helper: use NESTED_*_ENTRY in dtor
* epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor
* epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors
* epee: net_helper: use NESTED_*_ENTRY in dtor
* epee: profile_tools: use NESTED_*_ENTRY in dtors
* epee: misc_language: use NESTED_*_ENTRY in dtor
* epee: syncobj: use NESTED_*_ENTRY in dtor
* zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
|
|
|
NESTED_TRY_ENTRY();
|
|
|
|
|
|
|
|
|
|
close();
|
|
|
|
|
|
|
|
|
|
NESTED_CATCH_ENTRY(__func__);
|
2018-12-27 18:50:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::open(const std::string& path_, uint64_t cache_sz)
|
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
res = mdb_env_create(&m_penv);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_create");
|
|
|
|
|
|
2019-08-15 18:48:20 +03:00
|
|
|
MDB_dbi max_dbs = 15;
|
|
|
|
|
res = mdb_env_set_maxdbs(m_penv, max_dbs);
|
2018-12-27 18:50:45 +03:00
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_maxdbs");
|
|
|
|
|
|
|
|
|
|
m_path = path_;
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
m_path = epee::string_encoding::convert_ansii_to_utf8(m_path);
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-08-10 05:31:47 +03:00
|
|
|
CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_path), false, "create_directories_if_necessary failed: " << m_path);
|
|
|
|
|
|
2019-08-15 18:48:20 +03:00
|
|
|
unsigned int lmdb_flags = MDB_NORDAHEAD /*| MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC*/;
|
|
|
|
|
mdb_mode_t lmdb_mode = 0644;
|
|
|
|
|
|
|
|
|
|
res = mdb_env_open(m_penv, m_path.c_str(), lmdb_flags, lmdb_mode);
|
|
|
|
|
if (res != MDB_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
// DB created with prev LMDB 0.9.18 cannot be opened due to huge map size set in env
|
|
|
|
|
// try to remove DB folder completely and re-open
|
|
|
|
|
boost::filesystem::remove_all(m_path);
|
|
|
|
|
CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_path), false, "create_directories_if_necessary failed: " << m_path);
|
|
|
|
|
res = mdb_env_create(&m_penv);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_create");
|
|
|
|
|
res = mdb_env_set_maxdbs(m_penv, max_dbs);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_maxdbs");
|
|
|
|
|
res = mdb_env_open(m_penv, m_path.c_str(), lmdb_flags, lmdb_mode);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_open, m_path=" << m_path);
|
|
|
|
|
}
|
2019-08-13 19:59:44 +03:00
|
|
|
|
|
|
|
|
resize_if_needed();
|
2018-12-27 18:50:45 +03:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::open_container(const std::string& name, container_handle& h)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
MDB_dbi dbi = AUTO_VAL_INIT(dbi);
|
|
|
|
|
begin_transaction();
|
|
|
|
|
int res = mdb_dbi_open(get_current_tx(), name.c_str(), MDB_CREATE, &dbi);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_dbi_open with container name: " << name);
|
|
|
|
|
commit_transaction();
|
|
|
|
|
h = static_cast<container_handle>(dbi);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::close()
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<boost::recursive_mutex> lock(m_cs);
|
|
|
|
|
for (auto& tx_thread : m_txs)
|
|
|
|
|
{
|
|
|
|
|
for (auto txe : tx_thread.second)
|
|
|
|
|
{
|
|
|
|
|
int res = mdb_txn_commit(txe.ptx);
|
|
|
|
|
if (res != MDB_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR("[DB ERROR]: On close tranactions: " << mdb_strerror(res));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_txs.clear();
|
|
|
|
|
}
|
|
|
|
|
if (m_penv)
|
|
|
|
|
{
|
|
|
|
|
mdb_env_close(m_penv);
|
|
|
|
|
m_penv = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::begin_transaction(bool read_only)
|
|
|
|
|
{
|
|
|
|
|
if (!read_only)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_CYAN("[DB " << m_path << "] WRITE LOCKED", LOG_LEVEL_3);
|
|
|
|
|
CRITICAL_SECTION_LOCK(m_write_exclusive_lock);
|
2019-08-13 19:59:44 +03:00
|
|
|
|
|
|
|
|
if (m_commits_count.fetch_add(1, std::memory_order_relaxed) % DB_RESIZE_COMMITS_TO_CHECK == DB_RESIZE_COMMITS_TO_CHECK - 1)
|
|
|
|
|
{
|
|
|
|
|
if (!resize_if_needed())
|
|
|
|
|
m_commits_count.store(DB_RESIZE_COMMITS_TO_CHECK - 1, std::memory_order_relaxed); // if failed, try again on next commit
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-27 18:50:45 +03:00
|
|
|
}
|
|
|
|
|
PROFILE_FUNC("lmdb_db_backend::begin_transaction");
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<boost::recursive_mutex> lock(m_cs);
|
|
|
|
|
CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed");
|
|
|
|
|
transactions_list& rtxlist = m_txs[std::this_thread::get_id()];
|
|
|
|
|
MDB_txn* pparent_tx = nullptr;
|
|
|
|
|
MDB_txn* p_new_tx = nullptr;
|
2019-06-06 14:34:05 +03:00
|
|
|
bool parent_read_only = false;
|
2018-12-27 18:50:45 +03:00
|
|
|
if (rtxlist.size())
|
2019-06-06 14:34:05 +03:00
|
|
|
{
|
2018-12-27 18:50:45 +03:00
|
|
|
pparent_tx = rtxlist.back().ptx;
|
2019-06-06 14:34:05 +03:00
|
|
|
parent_read_only = rtxlist.back().read_only;
|
|
|
|
|
}
|
2018-12-27 18:50:45 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pparent_tx && read_only)
|
|
|
|
|
{
|
|
|
|
|
++rtxlist.back().count;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
unsigned int flags = 0;
|
|
|
|
|
if (read_only)
|
|
|
|
|
flags += MDB_RDONLY;
|
|
|
|
|
|
2019-06-06 14:34:05 +03:00
|
|
|
//don't use parent tx in write transactions if parent tx was read-only (restriction in lmdb)
|
|
|
|
|
//see "Nested transactions: Max 1 child, write txns only, no writemap"
|
|
|
|
|
if (pparent_tx && parent_read_only)
|
|
|
|
|
pparent_tx = nullptr;
|
|
|
|
|
|
2018-12-27 18:50:45 +03:00
|
|
|
CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed");
|
|
|
|
|
res = mdb_txn_begin(m_penv, pparent_tx, flags, &p_new_tx);
|
2019-06-06 23:08:21 +03:00
|
|
|
if(res != MDB_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
//Important: if mdb_txn_begin is failed need to unlock previously locked mutex
|
|
|
|
|
CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock);
|
|
|
|
|
//throw exception to avoid regular code execution
|
|
|
|
|
ASSERT_MES_AND_THROW_LMDB(res, "Unable to mdb_txn_begin");
|
|
|
|
|
}
|
2018-12-27 18:50:45 +03:00
|
|
|
|
|
|
|
|
rtxlist.push_back(tx_entry());
|
|
|
|
|
rtxlist.back().count = read_only ? 1 : 0;
|
|
|
|
|
rtxlist.back().ptx = p_new_tx;
|
|
|
|
|
rtxlist.back().read_only = read_only;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_L4("[DB] Transaction started");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MDB_txn* lmdb_db_backend::get_current_tx()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<boost::recursive_mutex> lock(m_cs);
|
|
|
|
|
auto& rtxlist = m_txs[std::this_thread::get_id()];
|
|
|
|
|
CHECK_AND_ASSERT_MES(rtxlist.size(), nullptr, "Unable to find active tx for thread " << std::this_thread::get_id());
|
|
|
|
|
return rtxlist.back().ptx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::pop_tx_entry(tx_entry& txe)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<boost::recursive_mutex> lock(m_cs);
|
|
|
|
|
auto it = m_txs.find(std::this_thread::get_id());
|
|
|
|
|
CHECK_AND_ASSERT_MES(it != m_txs.end(), false, "[DB] Unable to find id cor current thread");
|
|
|
|
|
CHECK_AND_ASSERT_MES(it->second.size(), false, "[DB] No active tx for current thread");
|
|
|
|
|
|
|
|
|
|
txe = it->second.back();
|
|
|
|
|
|
|
|
|
|
if (it->second.back().read_only && it->second.back().count == 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR("Internal db tx state error: read_only and count readers == 0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((it->second.back().read_only && it->second.back().count < 2) || (!it->second.back().read_only && it->second.back().count < 1))
|
|
|
|
|
{
|
|
|
|
|
it->second.pop_back();
|
|
|
|
|
if (!it->second.size())
|
|
|
|
|
m_txs.erase(it);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
--it->second.back().count;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::commit_transaction()
|
|
|
|
|
{
|
|
|
|
|
PROFILE_FUNC("lmdb_db_backend::commit_transaction");
|
|
|
|
|
{
|
|
|
|
|
tx_entry txe = AUTO_VAL_INIT(txe);
|
|
|
|
|
bool r = pop_tx_entry(txe);
|
|
|
|
|
CHECK_AND_ASSERT_MES(r, false, "Unable to pop_tx_entry");
|
|
|
|
|
|
|
|
|
|
if (txe.count == 0 || (txe.read_only && txe.count == 1))
|
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
res = mdb_txn_commit(txe.ptx);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_txn_commit (error " << res << ")");
|
|
|
|
|
if (!txe.read_only && !txe.count)
|
|
|
|
|
{
|
|
|
|
|
CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock);
|
|
|
|
|
LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED", LOG_LEVEL_3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LOG_PRINT_L4("[DB] Transaction committed");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lmdb_db_backend::abort_transaction()
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
tx_entry txe = AUTO_VAL_INIT(txe);
|
|
|
|
|
bool r = pop_tx_entry(txe);
|
|
|
|
|
CHECK_AND_ASSERT_MES(r, void(), "Unable to pop_tx_entry");
|
|
|
|
|
if (txe.count == 0 || (txe.read_only && txe.count == 1))
|
|
|
|
|
{
|
|
|
|
|
mdb_txn_abort(txe.ptx);
|
2019-01-16 18:59:55 +03:00
|
|
|
if (!txe.read_only && !txe.count)
|
2018-12-27 18:50:45 +03:00
|
|
|
{
|
|
|
|
|
CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock);
|
|
|
|
|
LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED(ABORTED)", LOG_LEVEL_3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
LOG_PRINT_L4("[DB] Transaction aborted");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::erase(container_handle h, const char* k, size_t ks)
|
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
MDB_val key = AUTO_VAL_INIT(key);
|
|
|
|
|
key.mv_data = (void*)k;
|
|
|
|
|
key.mv_size = ks;
|
|
|
|
|
|
|
|
|
|
res = mdb_del(get_current_tx(), static_cast<MDB_dbi>(h), &key, nullptr);
|
|
|
|
|
if (res == MDB_NOTFOUND)
|
|
|
|
|
return false;
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_del");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::have_tx()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<boost::recursive_mutex> lock(m_cs);
|
|
|
|
|
auto it = m_txs.find(std::this_thread::get_id());
|
|
|
|
|
if (it == m_txs.end())
|
|
|
|
|
return false;
|
|
|
|
|
return it->second.size() ? true : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::get(container_handle h, const char* k, size_t ks, std::string& res_buff)
|
|
|
|
|
{
|
|
|
|
|
PROFILE_FUNC("lmdb_db_backend::get");
|
|
|
|
|
int res = 0;
|
|
|
|
|
MDB_val key = AUTO_VAL_INIT(key);
|
|
|
|
|
MDB_val data = AUTO_VAL_INIT(data);
|
|
|
|
|
key.mv_data = (void*)k;
|
|
|
|
|
key.mv_size = ks;
|
|
|
|
|
bool need_to_commit = false;
|
|
|
|
|
if (!have_tx())
|
|
|
|
|
{
|
|
|
|
|
need_to_commit = true;
|
|
|
|
|
begin_transaction(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = mdb_get(get_current_tx(), static_cast<MDB_dbi>(h), &key, &data);
|
|
|
|
|
|
|
|
|
|
if (need_to_commit)
|
|
|
|
|
commit_transaction();
|
|
|
|
|
|
|
|
|
|
if (res == MDB_NOTFOUND)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_get, h: " << h << ", ks: " << ks);
|
|
|
|
|
res_buff.assign((const char*)data.mv_data, data.mv_size);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::clear(container_handle h)
|
|
|
|
|
{
|
|
|
|
|
int res = mdb_drop(get_current_tx(), static_cast<MDB_dbi>(h), 0);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_drop");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t lmdb_db_backend::size(container_handle h)
|
|
|
|
|
{
|
|
|
|
|
PROFILE_FUNC("lmdb_db_backend::size");
|
|
|
|
|
MDB_stat container_stat = AUTO_VAL_INIT(container_stat);
|
|
|
|
|
bool need_to_commit = false;
|
|
|
|
|
if (!have_tx())
|
|
|
|
|
{
|
|
|
|
|
need_to_commit = true;
|
|
|
|
|
begin_transaction(true);
|
|
|
|
|
}
|
|
|
|
|
int res = mdb_stat(get_current_tx(), static_cast<MDB_dbi>(h), &container_stat);
|
|
|
|
|
if (need_to_commit)
|
|
|
|
|
commit_transaction();
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_stat");
|
|
|
|
|
return container_stat.ms_entries;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::set(container_handle h, const char* k, size_t ks, const char* v, size_t vs)
|
|
|
|
|
{
|
|
|
|
|
PROFILE_FUNC("lmdb_db_backend::set");
|
|
|
|
|
int res = 0;
|
|
|
|
|
MDB_val key = AUTO_VAL_INIT(key);
|
|
|
|
|
MDB_val data = AUTO_VAL_INIT(data);
|
|
|
|
|
key.mv_data = (void*)k;
|
|
|
|
|
key.mv_size = ks;
|
|
|
|
|
data.mv_data = (void*)v;
|
|
|
|
|
data.mv_size = vs;
|
|
|
|
|
|
|
|
|
|
res = mdb_put(get_current_tx(), static_cast<MDB_dbi>(h), &key, &data, 0);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_put");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2019-08-13 19:59:44 +03:00
|
|
|
|
2018-12-27 18:50:45 +03:00
|
|
|
bool lmdb_db_backend::enumerate(container_handle h, i_db_callback* pcb)
|
|
|
|
|
{
|
|
|
|
|
CHECK_AND_ASSERT_MES(pcb, false, "null capback ptr passed to enumerate");
|
|
|
|
|
MDB_val key = AUTO_VAL_INIT(key);
|
|
|
|
|
MDB_val data = AUTO_VAL_INIT(data);
|
|
|
|
|
|
|
|
|
|
bool need_to_commit = false;
|
|
|
|
|
if (!have_tx())
|
|
|
|
|
{
|
|
|
|
|
need_to_commit = true;
|
|
|
|
|
begin_transaction(true);
|
|
|
|
|
}
|
|
|
|
|
MDB_cursor* cursor_ptr = nullptr;
|
|
|
|
|
int res = mdb_cursor_open(get_current_tx(), static_cast<MDB_dbi>(h), &cursor_ptr);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_cursor_open");
|
|
|
|
|
CHECK_AND_ASSERT_MES(cursor_ptr, false, "cursor_ptr is null after mdb_cursor_open");
|
|
|
|
|
|
|
|
|
|
uint64_t count = 0;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
int res = mdb_cursor_get(cursor_ptr, &key, &data, MDB_NEXT);
|
|
|
|
|
if (res == MDB_NOTFOUND)
|
|
|
|
|
break;
|
|
|
|
|
if (!pcb->on_enum_item(count, key.mv_data, key.mv_size, data.mv_data, data.mv_size))
|
|
|
|
|
break;
|
|
|
|
|
count++;
|
|
|
|
|
} while (cursor_ptr);
|
|
|
|
|
|
|
|
|
|
mdb_cursor_close(cursor_ptr);
|
|
|
|
|
if (need_to_commit)
|
|
|
|
|
commit_transaction();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lmdb_db_backend::get_stat_info(tools::db::stat_info& si)
|
|
|
|
|
{
|
|
|
|
|
si = AUTO_VAL_INIT_T(tools::db::stat_info);
|
|
|
|
|
|
|
|
|
|
MDB_envinfo ei = AUTO_VAL_INIT(ei);
|
|
|
|
|
mdb_env_info(m_penv, &ei);
|
|
|
|
|
si.map_size = ei.me_mapsize;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<boost::recursive_mutex> lock(m_cs);
|
|
|
|
|
for (auto& e : m_txs)
|
|
|
|
|
{
|
|
|
|
|
for (auto& pr : e.second)
|
|
|
|
|
{
|
|
|
|
|
++si.tx_count;
|
|
|
|
|
if(!pr.read_only)
|
|
|
|
|
++si.write_tx_count;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2019-08-13 19:59:44 +03:00
|
|
|
|
|
|
|
|
bool lmdb_db_backend::resize_if_needed()
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_CYAN("[DB " << m_path << "] WRITE LOCKED in resize_if_needed()", LOG_LEVEL_3);
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_write_exclusive_lock);
|
|
|
|
|
|
|
|
|
|
if (have_tx())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED("[DB " << m_path << "] : resize_if_needed(): Have txs on stack, unable to resize!", LOG_LEVEL_0);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MDB_stat st = AUTO_VAL_INIT(st);
|
|
|
|
|
mdb_env_stat(m_penv, &st);
|
|
|
|
|
MDB_envinfo ei = AUTO_VAL_INIT(ei);
|
|
|
|
|
mdb_env_info(m_penv, &ei);
|
|
|
|
|
|
|
|
|
|
uint64_t dirty_size = ei.me_last_pgno * st.ms_psize;
|
|
|
|
|
int64_t size_diff = ei.me_mapsize - dirty_size;
|
|
|
|
|
if (size_diff >= DB_RESIZE_MIN_FREE_SIZE && ei.me_mapsize >= DB_RESIZE_MIN_MAX_SIZE)
|
|
|
|
|
return true; // resize is not needed
|
|
|
|
|
|
|
|
|
|
double gigabyte = 1024 * 1024 * 1024;
|
|
|
|
|
const uint64_t increment_size_pg_aligned = DB_RESIZE_INCREMENT_SIZE - (DB_RESIZE_INCREMENT_SIZE % st.ms_psize);
|
|
|
|
|
|
|
|
|
|
// need to resize DB
|
|
|
|
|
uint64_t new_size = ei.me_mapsize - (ei.me_mapsize % increment_size_pg_aligned) + increment_size_pg_aligned;
|
|
|
|
|
|
|
|
|
|
int res = mdb_env_set_mapsize(m_penv, new_size);
|
|
|
|
|
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_mapsize");
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_CYAN("[DB " << m_path << "] has grown: " << std::fixed << std::setprecision(2) << ei.me_mapsize / gigabyte << " GiB -> " << std::fixed << std::setprecision(2) << new_size / gigabyte << " GiB", LOG_LEVEL_0);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-27 18:50:45 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef LOG_DEFAULT_CHANNEL
|
Coverity (#28)
* stratum_server: resolve CID 210144 (UNINIT_CTOR)
* stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_blockchain_update_listener, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro
A temporary substition for what I hope will eventually be a full-fledged
exception-dispatcher (class-based, not macro).
* stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_protocol_handler, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT)
The potential to throw exists within guarded_critical_region_t, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger, del_connection, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: move macros to *top* of file
so they can be used *within* this file.
* daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT)
The potential to throw exists within log_space, and any paths involving
the logger (including CATCH_ENTRY_*).
* daemon: return cstdlib proper types in main
* simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT)
CID: 210082
CID: 210086
CID: 210096
CID: 210147
CID: 210149
CID: 210150
The potential to throw exists throughout various paths in main.
* simplewallet: return cstdlib proper types in main
* simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, and any paths
involving the logger (including CATCH_ENTRY_*).
* conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT)
CID: 210038
CID: 210047
CID: 210108
CID: 210122
CID: 210157
The potential to throw exists throughout various paths in main.
* conn_tool: return cstdlib proper types in main
* miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT)
The potential to throw exists within deinit, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT)
The potential to throw exists within boost microsec_clock::localtime(),
and any paths involving the logger (including CATCH_ENTRY_*).
* db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT)
The potential to throw exists within close(), including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT)
The potential to throw exists within several paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210064
CID: 210093
CID: 210136
CID: 210139
The potential to throw exists within m_func(), including any paths
involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210072
CID: 210094
CID: 210116
CID: 210141
The potential to throw exists within m_cache.clear(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT)
The potential to throw exists within shutdown(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT)
The potential to throw exists within unlock(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: http_base: resolve CID 210176 (UNINIT_CTOR)
* p2p: net_node: resolve CID 210173 (UNINIT_CTOR)
* epee: net_helper: resolve CID 210138 (UNINIT_CTOR)
* p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR)
* currency_basic: resolve CID 210117 (UNINIT_CTOR)
* epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR)
CID: 210040
CID: 210090
CID: 210105
* simplewallet: resolve CID 210103 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR)
* json_archive: resolve CID 210087 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR)
* miniupnp_helper: resolve CID 210037 (UNINIT_CTOR)
* crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN)
* wallet2: resolve CID 210041 (CHECKED_RETURN)
* epee: misc_log_ex: resolve CID 210127 (DEADCODE)
* epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE)
CID: 210167
CID: 210170
CID: 210180
* p2p: net_node: resolve CID 210065 (PASS_BY_VALUE)
* epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE)
* epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE)
* epee: misc_log_ex: add NESTED_*_ENTRY macros
* simplewallet: use NESTED_*_ENTRY in message_writer dtor
* stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor
* stratum_protocol_handler: use NESTED_*_ENTRY in dtor
* lmdb_db_backend: use NESTED_*_ENTRY in dtor
* epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210088
CID: 210106
CID: 210164
CID: 210179
The potential to throw exists within various paths, including any
paths involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: use NESTED_*_ENTRY in dtor
* miniupnp_helper: use NESTED_*_ENTRY in dtor
* epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor
* epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors
* epee: net_helper: use NESTED_*_ENTRY in dtor
* epee: profile_tools: use NESTED_*_ENTRY in dtors
* epee: misc_language: use NESTED_*_ENTRY in dtor
* epee: syncobj: use NESTED_*_ENTRY in dtor
* zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
|
|
|
#define LOG_DEFAULT_CHANNEL NULL
|