221 {
223 if (remaining_storage > 0) {
224 return false;
225 }
226
227 auto percentage = [](
uint64_t mem) {
229 return (mem * pcnt)/100;
230 };
231
233 ilog(
"Finality Status exceeded max storage (${max_storage}GB) need to free up ${storage_to_free} GB",
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
247
248 auto oldest_failure_iter = status_expiry_indx.begin();
249
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}",
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 }
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}",
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();
277 earliest_block = block_num;
278 }
279 block_upper_bound = block_num;
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 }
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) {
293 }
294
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
block_timestamp(uint32_t s=0)
fc::time_point to_time_point() const
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
constexpr uint32_t no_block_num
unsigned __int64 uint64_t