Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio::chain_apis::trx_finality_status_processing_impl Struct Reference
Collaboration diagram for sysio::chain_apis::trx_finality_status_processing_impl:

Public Member Functions

 trx_finality_status_processing_impl (uint64_t max_storage, const fc::microseconds &success_duration, const fc::microseconds &failure_duration)
 
void signal_applied_transaction (const chain::transaction_trace_ptr &trace, const chain::packed_transaction_ptr &ptrx)
 
void signal_accepted_block (const chain::block_state_ptr &bsp)
 
void handle_rollback ()
 
bool status_expiry_of_trxs (const fc::time_point &now)
 
bool ensure_storage ()
 
void determine_earliest_tracked_block_id ()
 

Public Attributes

const uint64_t _max_storage
 
fc::tracked_storage< finality_status_multi_index_storage
 
uint32_t _last_proc_block_num = finality_status::no_block_num
 
chain::block_id_type _head_block_id
 
chain::block_timestamp_type _head_block_timestamp
 
chain::block_id_type _irr_block_id
 
chain::block_timestamp_type _irr_block_timestamp
 
chain::block_id_type _earliest_tracked_block_id
 
const fc::microseconds _success_duration
 
const fc::microseconds _failure_duration
 
std::deque< chain::transaction_id_type_speculative_trxs
 

Detailed Description

Definition at line 10 of file trx_finality_status_processing.cpp.

Constructor & Destructor Documentation

◆ trx_finality_status_processing_impl()

sysio::chain_apis::trx_finality_status_processing_impl::trx_finality_status_processing_impl ( uint64_t max_storage,
const fc::microseconds & success_duration,
const fc::microseconds & failure_duration )
inline

Member Function Documentation

◆ determine_earliest_tracked_block_id()

void sysio::chain_apis::trx_finality_status_processing_impl::determine_earliest_tracked_block_id ( )

Definition at line 337 of file trx_finality_status_processing.cpp.

337 {
338 const auto& indx = _storage.index().get<by_status_expiry>();
339
340 // find the lowest value successful block
341 auto success_iter = indx.lower_bound(boost::make_tuple(true, fc::time_point{}));
342 if (success_iter != indx.cend()) {
343 _earliest_tracked_block_id = success_iter->block_id;
344 }
345 }
const ContainerType & index() const
fc::tracked_storage< finality_status_multi_index > _storage
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ensure_storage()

bool sysio::chain_apis::trx_finality_status_processing_impl::ensure_storage ( )

Definition at line 221 of file trx_finality_status_processing.cpp.

221 {
222 const int64_t remaining_storage = _max_storage - _storage.memory_size();
223 if (remaining_storage > 0) {
224 return false;
225 }
226
227 auto percentage = [](uint64_t mem) {
228 const uint64_t pcnt = 90;
229 return (mem * pcnt)/100;
230 };
231 // determine how much we need to free to get back to at least the desired percentage of the storage
232 int64_t storage_to_free = _max_storage - percentage(_max_storage) - remaining_storage;
233 ilog("Finality Status exceeded max storage (${max_storage}GB) need to free up ${storage_to_free} GB",
234 ("max_storage",_max_storage/1024/1024/1024)
235 ("storage_to_free",storage_to_free/1024/1024/1024));
236 const auto& block_indx = _storage.index().get<by_block_num>();
237 const auto& status_expiry_indx = _storage.index().get<by_status_expiry>();
238 using index_iter_type = decltype(_storage.index().project<0>(block_indx.begin()));
239 chain::deque<index_iter_type> remove_trxs;
240
241 auto reduce_storage = [&storage_to_free,&remove_trxs,&storage=this->_storage](auto iter) {
242 storage_to_free -= iter->memory_size();
243 remove_trxs.push_back(storage.index().project<0>(iter));
244 };
245
246 auto block_upper_bound = finality_status::no_block_num;
247 // start at the beginning of the oldest_failure section and just keep iterating from there
248 auto oldest_failure_iter = status_expiry_indx.begin();
249 // the end of the oldest failure section
250 const auto oldest_failure_end = status_expiry_indx.lower_bound( std::make_tuple( true, fc::time_point{} ) );
252 while (storage_to_free > 0) {
253 auto oldest_block_iter = block_indx.upper_bound(block_upper_bound);
254 if (oldest_block_iter == block_indx.end()) {
255 FC_ASSERT( oldest_failure_iter != oldest_failure_end,
256 "CODE ERROR: can not free more storage, but still exceeding limit. "
257 "Total entries: ${total_entries}, storage memory to free: ${storage}, "
258 "entries slated for removal: ${remove_entries}",
259 ("total_entries", _storage.index().size())
260 ("storage", storage_to_free)
261 ("remove_entries", remove_trxs.size()));
262 for (; oldest_failure_iter != oldest_failure_end && storage_to_free > 0; ++oldest_failure_iter) {
263 reduce_storage(oldest_failure_iter);
264 }
265 FC_ASSERT( storage_to_free < 1,
266 "CODE ERROR: can not free more storage, but still exceeding limit. "
267 "Total entries: ${total_entries}, storage memory to free: ${storage}, "
268 "entries slated for removal: ${remove_entries}",
269 ("total_entries", _storage.index().size())
270 ("storage", storage_to_free)
271 ("remove_entries", remove_trxs.size()));
272 break;
273 }
274 else {
275 const auto block_num = oldest_block_iter->block_num();
276 if (earliest_block == finality_status::no_block_num) {
277 earliest_block = block_num;
278 }
279 block_upper_bound = block_num;
280 const auto block_timestamp = oldest_block_iter->block_timestamp;
281 for (; oldest_block_iter != block_indx.end() && oldest_block_iter->block_num() == block_num; ++oldest_block_iter) {
282 reduce_storage(oldest_block_iter);
283 }
284 const auto oldest_failure_upper_bound = status_expiry_indx.upper_bound( std::make_tuple( false, block_timestamp.to_time_point() ));
285 for (; oldest_failure_iter != oldest_failure_upper_bound; ++oldest_failure_iter) {
286 reduce_storage(oldest_failure_iter);
287 }
288 }
289 }
290
291 for (const auto& trx_iter : remove_trxs) {
292 _storage.erase(trx_iter);
293 }
294
295 if (earliest_block != finality_status::no_block_num) {
296 ilog( "Finality Status dropped ${trx_count} transactions, which were removed from block # ${block_num_start} to block # ${block_num_end}",
297 ("trx_count", remove_trxs.size())("block_num_start", earliest_block)("block_num_end", block_upper_bound) );
298 }
299 else {
300 ilog( "Finality Status dropped ${trx_count} transactions, all were failed transactions", ("trx_count", remove_trxs.size()) );
301 }
302
303 return true;
304 }
void erase(const Key &key)
size_t memory_size() const
fc::time_point to_time_point() const
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
#define ilog(FORMAT,...)
Definition logger.hpp:118
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_rollback()

void sysio::chain_apis::trx_finality_status_processing_impl::handle_rollback ( )

Definition at line 182 of file trx_finality_status_processing.cpp.

182 {
183 const auto& indx = _storage.index().get<by_block_num>();
184 chain::deque<decltype(_storage.index().project<0>(indx.begin()))> trxs;
185 for (auto iter = indx.lower_bound(chain::block_header::num_from_id(_head_block_id)); iter != indx.end(); ++iter) {
186 trxs.push_back(_storage.index().project<0>(iter));
187 }
188 for (const auto& trx_iter : trxs) {
189 _storage.modify( trx_iter, []( finality_status_object& obj ) {
190 obj.forked_out = true;
191 } );
192 }
193 }
void modify(typename primary_index_type::iterator itr, Lam lam)
static uint32_t num_from_id(const block_id_type &id)
tracks status related to a transaction in the blockchain
Here is the call graph for this function:
Here is the caller graph for this function:

◆ signal_accepted_block()

void sysio::chain_apis::trx_finality_status_processing_impl::signal_accepted_block ( const chain::block_state_ptr & bsp)

Definition at line 142 of file trx_finality_status_processing.cpp.

142 {
143 // if this block had any transactions, then we have processed everything we need to already
144 if (bsp->id == _head_block_id) {
145 return;
146 }
147
148 _head_block_id = bsp->id;
149 _head_block_timestamp = bsp->block->timestamp;
150
151 const auto head_block_num = chain::block_header::num_from_id(_head_block_id);
152 if (head_block_num <= _last_proc_block_num) {
154 }
155
157 bool status_expiry = status_expiry_of_trxs(now);
158 if (status_expiry) {
160 }
161
162 // if this approve block was preceded by speculative transactions then we produced the block, update trx state.
164 obj.block_id = block_id;
165 obj.block_timestamp = block_timestamp;
166 obj.forked_out = false;
167 };
168 for (const auto& trx_id : _speculative_trxs) {
169 auto iter = _storage.find(trx_id);
170 FC_ASSERT( iter != _storage.index().cend(),
171 "CODE ERROR: Should not have speculative transactions that have not already"
172 "been identified prior to the block being accepted. trx id: ${trx_id}",
173 ("trx_id", trx_id) );
174 _storage.modify( iter, mod );
175 }
176 _speculative_trxs.clear();
177
178 _last_proc_block_num = head_block_num;
179 }
static time_point now()
Definition time.cpp:14
primary_index_type::iterator find(const Key &key)
Here is the call graph for this function:

◆ signal_applied_transaction()

void sysio::chain_apis::trx_finality_status_processing_impl::signal_applied_transaction ( const chain::transaction_trace_ptr & trace,
const chain::packed_transaction_ptr & ptrx )

Definition at line 76 of file trx_finality_status_processing.cpp.

76 {
78 // use the head block num if we are in a block, otherwise don't provide block number for speculative blocks
79 chain::block_id_type block_id;
81 bool modified = false;
82 if (trace->producer_block_id) {
83 block_id = *trace->producer_block_id;
84 const bool block_changed = block_id != _head_block_id;
85 if (block_changed) {
86 _head_block_id = block_id;
87 _head_block_timestamp = trace->block_time;
88 }
90
91 const auto head_block_num = chain::block_header::num_from_id(_head_block_id);
92 if (block_changed && head_block_num <= _last_proc_block_num) {
94 modified = true;
95 }
96
97 _last_proc_block_num = head_block_num;
98
99 if (status_expiry_of_trxs(now)) {
100 modified = true;
101 }
102 }
103
104 if (!trace->receipt) return;
105 if (trace->receipt->status != chain::transaction_receipt_header::executed) {
106 return;
107 }
108 if (trace->scheduled) return;
109 if (chain::is_onblock(*trace)) return;
110
111 if (!trace->producer_block_id) {
112 _speculative_trxs.push_back(trace->id);
113 }
114
115 if(ensure_storage()) {
116 modified = true;
117 }
118
119 const auto& trx_id = trace->id;
120 auto iter = _storage.find(trx_id);
121 if (iter != _storage.index().cend()) {
122 _storage.modify( iter, [&block_id,&block_timestamp]( finality_status_object& obj ) {
123 obj.block_id = block_id;
125 obj.forked_out = false;
126 } );
127 }
128 else {
130 finality_status_object{.trx_id = trx_id,
131 .trx_expiry = ptrx->expiration(),
132 .received = now,
133 .block_id = block_id,
134 .block_timestamp = block_timestamp});
135 }
136
139 }
140 }
std::pair< typename primary_index_type::iterator, bool > insert(typename ContainerType::value_type obj)
block_timestamp< config::block_interval_ms, config::block_timestamp_epoch > block_timestamp_type
fc::sha256 block_id_type
Definition types.hpp:231
bool is_onblock(const transaction_trace &tt)
Definition trace.hpp:71
@ executed
succeed, no error handler executed
Definition block.hpp:14
chain::block_timestamp_type block_timestamp
Here is the call graph for this function:

◆ status_expiry_of_trxs()

bool sysio::chain_apis::trx_finality_status_processing_impl::status_expiry_of_trxs ( const fc::time_point & now)

Definition at line 195 of file trx_finality_status_processing.cpp.

195 {
196 const auto& indx = _storage.index().get<by_status_expiry>();
197 chain::deque<decltype(_storage.index().project<0>(indx.begin()))> remove_trxs;
198
199 // find the successful (in any block) transactions that are past the failure expiry times
200 auto success_iter = indx.lower_bound(boost::make_tuple(true, fc::time_point{}));
201
202 const fc::time_point success_expiry = now - _success_duration;
203 const auto success_end = indx.upper_bound(boost::make_tuple(true, success_expiry));
204 for (; success_iter != success_end; ++success_iter) {
205 remove_trxs.push_back(_storage.index().project<0>(success_iter));
206 }
207
208 const fc::time_point fail_expiry = now - _failure_duration;
209 const auto fail_end = indx.upper_bound(boost::make_tuple(false, fail_expiry));
210 // find the failure (not in a block) transactions that are past the failure expiry time
211 for (auto fail_iter = indx.begin(); fail_iter != fail_end; ++fail_iter) {
212 remove_trxs.push_back(_storage.index().project<0>(fail_iter));
213 }
214
215 for (const auto& trx_iter : remove_trxs) {
216 _storage.erase(trx_iter);
217 }
218 return !remove_trxs.empty();
219 }
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ _earliest_tracked_block_id

chain::block_id_type sysio::chain_apis::trx_finality_status_processing_impl::_earliest_tracked_block_id

Definition at line 37 of file trx_finality_status_processing.cpp.

◆ _failure_duration

const fc::microseconds sysio::chain_apis::trx_finality_status_processing_impl::_failure_duration

Definition at line 39 of file trx_finality_status_processing.cpp.

◆ _head_block_id

chain::block_id_type sysio::chain_apis::trx_finality_status_processing_impl::_head_block_id

Definition at line 33 of file trx_finality_status_processing.cpp.

◆ _head_block_timestamp

chain::block_timestamp_type sysio::chain_apis::trx_finality_status_processing_impl::_head_block_timestamp

Definition at line 34 of file trx_finality_status_processing.cpp.

◆ _irr_block_id

chain::block_id_type sysio::chain_apis::trx_finality_status_processing_impl::_irr_block_id

Definition at line 35 of file trx_finality_status_processing.cpp.

◆ _irr_block_timestamp

chain::block_timestamp_type sysio::chain_apis::trx_finality_status_processing_impl::_irr_block_timestamp

Definition at line 36 of file trx_finality_status_processing.cpp.

◆ _last_proc_block_num

uint32_t sysio::chain_apis::trx_finality_status_processing_impl::_last_proc_block_num = finality_status::no_block_num

Definition at line 32 of file trx_finality_status_processing.cpp.

◆ _max_storage

const uint64_t sysio::chain_apis::trx_finality_status_processing_impl::_max_storage

Definition at line 30 of file trx_finality_status_processing.cpp.

◆ _speculative_trxs

std::deque<chain::transaction_id_type> sysio::chain_apis::trx_finality_status_processing_impl::_speculative_trxs

Definition at line 40 of file trx_finality_status_processing.cpp.

◆ _storage

fc::tracked_storage<finality_status_multi_index> sysio::chain_apis::trx_finality_status_processing_impl::_storage

Definition at line 31 of file trx_finality_status_processing.cpp.

◆ _success_duration

const fc::microseconds sysio::chain_apis::trx_finality_status_processing_impl::_success_duration

Definition at line 38 of file trx_finality_status_processing.cpp.


The documentation for this struct was generated from the following file: