std::exception_ptr added to TxSearch

pull/93/merge
moneroexamples 6 years ago
parent 0de07b5611
commit 6e069cad80

@ -41,11 +41,17 @@ CurrentBlockchainStatus::monitor_blockchain()
if (stop_blockchain_monitor_loop)
break;
update_current_blockchain_height();
update_current_blockchain_height();
read_mempool();
OMINFO << "Current blockchain height: " << current_height
<< ", no of mempool txs: " << mempool_txs.size();
clean_search_thread_map();
check_search_threads_for_exceptions();
std::this_thread::sleep_for(
std::chrono::seconds(
bc_setup.refresh_block_status_every_seconds));
@ -950,13 +956,40 @@ CurrentBlockchainStatus::clean_search_thread_map()
if (search_thread_exist(st.first)
&& st.second.get_functor().still_searching() == false)
{
OMERROR << st.first << " still searching: "
<< st.second.get_functor().still_searching();
OMINFO << "Ereasing a search thread";
searching_threads.erase(st.first);
}
}
}
bool
CurrentBlockchainStatus::check_search_threads_for_exceptions()
{
bool found_any_exception {false};
std::lock_guard<std::mutex> lck (searching_threads_map_mtx);
for (auto& st: searching_threads)
{
if (search_thread_exist(st.first)
&& st.second.get_functor().still_searching() == false)
{
try
{
auto eptr = st.second.get_functor().get_exception_ptr();
found_any_exception = true;
std::rethrow_exception(eptr);
}
catch (const std::exception& e)
{
OMERROR << "Error in search thread: " << e.what();
}
}
}
return found_any_exception;
}
tuple<string, string, string>
CurrentBlockchainStatus::construct_output_rct_field(

@ -219,6 +219,9 @@ public:
virtual void
clean_search_thread_map();
virtual bool
check_search_threads_for_exceptions();
/*
* The frontend requires rct field to work
* the filed consisitct of rct_pk, mask, and amount.

@ -17,13 +17,13 @@ ThreadRAII::~ThreadRAII()
{
if (action == DtorAction::join)
{
std::cout << "\nThreadRAII::~ThreadRAII() t.join()\n";
//std::cout << "\nThreadRAII::~ThreadRAII() t.join()\n";
t.join();
}
else
{
t.detach();
std::cout << "\nThreadRAII::~ThreadRAII() t.detach()\n";
//std::cout << "\nThreadRAII::~ThreadRAII() t.detach()\n";
}
}
}

@ -44,9 +44,6 @@ public:
T& get_functor() {return *f;}
// ThreadRAII2(ThreadRAII2&&) = default;
// ThreadRAII2& operator=(ThreadRAII2&&) = default;
protected:
std::unique_ptr<T> f;
};

@ -15,7 +15,8 @@
namespace xmreg
{
TxSearch::TxSearch(XmrAccount& _acc, std::shared_ptr<CurrentBlockchainStatus> _current_bc_status)
TxSearch::TxSearch(XmrAccount& _acc,
std::shared_ptr<CurrentBlockchainStatus> _current_bc_status)
: current_bc_status {_current_bc_status}
{
acc = make_shared<XmrAccount>(_acc);
@ -25,16 +26,18 @@ TxSearch::TxSearch(XmrAccount& _acc, std::shared_ptr<CurrentBlockchainStatus> _c
network_type net_type = current_bc_status->get_bc_setup().net_type;
if (!xmreg::parse_str_address(acc->address, address, net_type))
{
OMERROR << "Cant parse string address: " << acc->address;
throw TxSearchException("Cant parse string address: " + acc->address);
OMERROR << "Cant parse address: " + acc->address;
throw TxSearchException("Cant parse address: " + acc->address);
}
if (!xmreg::parse_str_secret_key(acc->viewkey, viewkey))
{
OMERROR << "Cant parse the private key: " << acc->viewkey;
throw TxSearchException("Cant parse private key: " + acc->viewkey);
OMERROR << "Cant parse private view key: " + acc->address;
throw TxSearchException("Cant parse private view key: "
+ acc->viewkey);
}
populate_known_outputs();
@ -56,7 +59,8 @@ TxSearch::operator()()
last_ping_timestamp = current_timestamp;
uint64_t blocks_lookahead = current_bc_status->get_bc_setup().blocks_search_lookahead;
uint64_t blocks_lookahead
= current_bc_status->get_bc_setup().blocks_search_lookahead;
// we put everything in massive catch, as there are plenty ways in which
// an exceptions can be thrown here. Mostly from mysql.
@ -83,7 +87,8 @@ TxSearch::operator()()
std::this_thread::sleep_for(
std::chrono::seconds(
current_bc_status->get_bc_setup().refresh_block_status_every_seconds)
current_bc_status->get_bc_setup()
.refresh_block_status_every_seconds)
);
loop_timestamp = get_current_timestamp();
@ -102,8 +107,10 @@ TxSearch::operator()()
// were dropped due to reorganization.
//CurrentBlockchainStatus::update_current_blockchain_height();
// if any txs that we already indexed got orphaned as a consequence of this
// MySqlAccounts::select_txs_for_account_spendability_check should
// if any txs that we already indexed got orphaned as a
// consequence of this
// MySqlAccounts::select_txs_for_account_spendability_check
// should
// update database accordingly when get_address_txs is executed.
continue;
@ -140,7 +147,8 @@ TxSearch::operator()()
// because we dont have spendkey. But what we can do is, we can look for
// candidate key images. And this can be achieved by checking if any mixin
// in associated with the given key image, is our output. If it is our output,
// then we assume its our key image (i.e. we spend this output). Off course this is only
// then we assume its our key image (i.e. we spend this output).
// Off course this is only
// assumption as our outputs can be used in key images of others for their
// mixin purposes. Thus, we sent to the front end the list of key images
// that we think are yours, and the frontend, because it has spend key,
@ -160,9 +168,9 @@ TxSearch::operator()()
// Class that is responsible for identification of our outputs
// and inputs in a given tx.
OutputInputIdentification oi_identification {&address, &viewkey, &tx,
tx_hash, is_coinbase,
current_bc_status};
OutputInputIdentification oi_identification {
&address, &viewkey, &tx,tx_hash,
is_coinbase, current_bc_status};
// flag indicating whether the txs in the given block are spendable.
// this is true when block number is more than 10 blocks from current
@ -237,16 +245,20 @@ TxSearch::operator()()
XmrTransaction tx_data;
tx_data.id = mysqlpp::null;
tx_data.hash = oi_identification.get_tx_hash_str();
tx_data.prefix_hash = oi_identification.get_tx_prefix_hash_str();
tx_data.tx_pub_key = oi_identification.get_tx_pub_key_str();
tx_data.hash = oi_identification
.get_tx_hash_str();
tx_data.prefix_hash = oi_identification
.get_tx_prefix_hash_str();
tx_data.tx_pub_key = oi_identification
.get_tx_pub_key_str();
tx_data.account_id = acc->id.data;
tx_data.blockchain_tx_id = blockchain_tx_id;
tx_data.total_received = oi_identification.total_received;
tx_data.total_sent = 0; // at this stage we don't have any
// info about spendings
tx_data.total_sent = 0; // at this stage we don't have
// anyinfo about spendings
// this is current block + unlock time
// this is current block
// + unlock time
// for regular tx, the unlock time is
// default of 10 blocks.
// for coinbase tx it is 60 blocks
@ -271,7 +283,8 @@ TxSearch::operator()()
tx_hash, amount_specific_indices))
{
OMERROR << "cant get_amount_specific_indices!";
throw TxSearchException("cant get_amount_specific_indices!");
throw TxSearchException(
"cant get_amount_specific_indices!");
}
if (tx_mysql_id == 0)
@ -307,15 +320,18 @@ TxSearch::operator()()
{
// add the outputs found into known_outputs_keys map
std::lock_guard<std::mutex> lck (getting_known_outputs_keys);
known_outputs_keys.insert({out_info.pub_key, out_info.amount});
std::lock_guard<std::mutex> lck (
getting_known_outputs_keys);
known_outputs_keys.insert(
{out_info.pub_key, out_info.amount});
}
} // for (auto& out_info: oi_identification.identified_outputs)
// insert all outputs found into mysql's outputs table
uint64_t no_rows_inserted = xmr_accounts->insert(outputs_found);
uint64_t no_rows_inserted
= xmr_accounts->insert(outputs_found);
if (no_rows_inserted == 0)
{
@ -542,26 +558,11 @@ TxSearch::operator()()
} // while(continue_search)
}
catch(TxSearchException const& e)
{
OMERROR << "TxSearchException in TxSearch: " << e.what()
<< " for " << acc->address;
}
catch(mysqlpp::Exception const& e)
{
OMERROR << "mysqlpp::Exception in TxSearch: " << e.what()
<< " for " << acc->address;
}
catch(std::exception const& e)
{
OMERROR << "std::exception in TxSearch: "
<< e.what() << " for " << acc->address;
}
}
catch(...)
{
OMERROR << "Unknown exception in TxSearch for "
<< acc->address;
OMERROR << "Exception in TxSearch for " << acc->address;
set_exception_ptr();
}
// it will stop anyway, but just call it so we get info message pritened out

@ -44,6 +44,11 @@ private:
bool continue_search {true};
// to store last exception thrown in the search thread
// using this, a main thread can get info what went wrong here
std::exception_ptr eptr;
mutex getting_eptr;
mutex getting_known_outputs_keys;
uint64_t last_ping_timestamp;
@ -78,7 +83,8 @@ public:
// make default constructor. useful in testing
TxSearch() = default;
TxSearch(XmrAccount& _acc, std::shared_ptr<CurrentBlockchainStatus> _current_bc_status);
TxSearch(XmrAccount& _acc,
std::shared_ptr<CurrentBlockchainStatus> _current_bc_status);
virtual void
operator()();
@ -107,6 +113,20 @@ public:
virtual known_outputs_t
get_known_outputs_keys();
virtual void
set_exception_ptr()
{
std::lock_guard<std::mutex> lck (getting_eptr);
eptr = std::current_exception();
stop();
}
virtual std::exception_ptr
get_exception_ptr()
{
std::lock_guard<std::mutex> lck (getting_eptr);
return eptr;
}
/**
* Search for our txs in the mempool

@ -205,9 +205,18 @@ YourMoneroRequests::get_address_txs(
// a placeholder for exciting or new account data
xmreg::XmrAccount acc;
// if not logged, i.e., no search thread exist, then start one.
if (login_and_start_search_thread(xmr_address, view_key, acc, j_response))
// for this to continue, search thread must have already been
// created and still exisits.
if (current_bc_status->search_thread_exist(xmr_address))
{
// populate acc and check view_key
if (!login_and_start_search_thread(xmr_address, view_key, acc, j_response))
{
// some error with loggin in or search thread start
session_close(session, j_response.dump());
return;
}
// before fetching txs, check if provided view key
// is correct. this is simply to ensure that
// we cant fetch an account's txs using only address.
@ -301,9 +310,12 @@ YourMoneroRequests::get_address_txs(
} // if (xmr_accounts->select_txs_for_ac
} // if (login_and_start_search_thread(xmr
} // if (current_bc_status->search_thread_exist(xmr_address))
else
{
{
j_response = json {{"status", "error"},
{"reason", "Search thread does not exist."}};
// some error with loggin in or search thread start
session_close(session, j_response.dump());
return;
@ -413,9 +425,17 @@ YourMoneroRequests::get_address_info(
// a placeholder for exciting or new account data
xmreg::XmrAccount acc;
// select this account if its existing one
if (login_and_start_search_thread(xmr_address, view_key, acc, j_response))
// for this to continue, search thread must have already been
// created and still exisits.
if (current_bc_status->search_thread_exist(xmr_address))
{
// populate acc and check view_key
if (!login_and_start_search_thread(xmr_address, view_key, acc, j_response))
{
// some error with loggin in or search thread start
session_close(session, j_response.dump());
return;
}
uint64_t total_received {0};
@ -506,9 +526,12 @@ YourMoneroRequests::get_address_info(
} // if (xmr_accounts->select_txs_for_account_spendability_check(acc.id, txs))
} // if (login_and_start_search_thread(xmr_address, view_key, acc, j_response))
} // if (current_bc_status->search_thread_exist(xmr_address))
else
{
j_response = json {{"status", "error"},
{"reason", "Search thread does not exist."}};
// some error with loggin in or search thread start
session_close(session, j_response.dump());
return;
@ -588,8 +611,19 @@ YourMoneroRequests::get_unspent_outs(
xmreg::XmrAccount acc;
// select this account if its existing one
if (login_and_start_search_thread(xmr_address, view_key, acc, j_response))
// for this to continue, search thread must have already been
// created and still exisits.
if (current_bc_status->search_thread_exist(xmr_address))
{
// populate acc and check view_key
if (!login_and_start_search_thread(xmr_address, view_key, acc, j_response))
{
// some error with loggin in or search thread start
session_close(session, j_response.dump());
return;
}
uint64_t total_outputs_amount {0};
// uint64_t current_blockchain_height
@ -711,9 +745,12 @@ YourMoneroRequests::get_unspent_outs(
->get_dynamic_per_kb_fee_estimate();
} // if (login_and_start_search_thread(xmr_address, view_key, acc, j_response))
} // if (current_bc_status->search_thread_exist(xmr_address))
else
{
j_response = json {{"status", "error"},
{"reason", "Search thread does not exist."}};
// some error with loggin in or search thread start
session_close(session, j_response.dump());
return;
@ -1803,8 +1840,23 @@ YourMoneroRequests::login_and_start_search_thread(
if (!current_bc_status->search_thread_exist(acc.address))
{
auto tx_search
= std::make_unique<TxSearch>(acc, current_bc_status);
std::unique_ptr<TxSearch> tx_search;
try
{
tx_search
= std::make_unique<TxSearch>(acc,
current_bc_status);
}
catch (std::exception const& e)
{
OMERROR << "TxSearch construction faild.";
j_response = json {{"status", "error"},
{"reason", "Failed to construct "
"TxSearch object"}};
return false;
}
if (current_bc_status->start_tx_search_thread(
acc, std::move(tx_search)))

@ -83,7 +83,7 @@ parse_str_address(const string& address_str,
if (!get_account_address_from_str(address_info, net_type, address_str))
{
cerr << "Error getting address: " << address_str << '\n';
//cerr << "Error getting address: " << address_str << '\n';
return false;
}

Loading…
Cancel
Save