Scorum
base_plugin_impl.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <limits>
4 #include <chainbase/generic_index.hpp>
7 
8 #define LIFE_TIME_PERIOD std::numeric_limits<uint32_t>::max()
9 
10 namespace scorum {
11 namespace common_statistics {
12 
13 using namespace scorum::protocol;
14 using namespace scorum::chain;
15 
16 struct by_bucket;
17 
18 template <typename Bucket, typename Plugin> class common_statistics_plugin_impl
19 {
20  typedef typename chainbase::get_index_type<Bucket>::type bucket_index;
21 
22 public:
24 
25  Plugin& _self;
26  flat_set<uint32_t> _tracked_buckets = { 60, 3600, 21600, 86400, 604800, 2592000, LIFE_TIME_PERIOD };
27  flat_set<typename Bucket::id_type> _current_buckets;
28  uint32_t _maximum_history_per_bucket_size = 100;
29 
30 public:
32  : _self(plugin)
33  {
34  }
36  {
37  }
38 
39  virtual void process_bucket_creation(const Bucket& bucket)
40  {
41  }
42  virtual void process_block(const Bucket& bucket, const signed_block& b)
43  {
44  }
45  virtual void process_pre_operation(const Bucket& bucket, const operation_notification& o)
46  {
47  }
48  virtual void process_post_operation(const Bucket& bucket, const operation_notification& o)
49  {
50  }
51 
52  void initialize()
53  {
54  auto& db = _self.database();
55 
56  db.applied_block.connect([&](const signed_block& b) { this->on_block(b); });
57  db.pre_apply_operation.connect([&](const operation_notification& o) { this->pre_operation(o); });
58  db.post_apply_operation.connect([&](const operation_notification& o) { this->post_operation(o); });
59 
60  db.template add_plugin_index<bucket_index>();
61  }
62 
64  {
65  auto& db = _self.database();
66 
67  for (auto bucket_id : _current_buckets)
68  {
69  const auto& bucket = db.get(bucket_id);
70 
71  process_pre_operation(bucket, o);
72  }
73  }
74 
76  {
77  try
78  {
79  auto& db = _self.database();
80 
81  for (auto bucket_id : _current_buckets)
82  {
83  const auto& bucket = db.get(bucket_id);
84 
85  process_post_operation(bucket, o);
86  }
87  }
88  FC_CAPTURE_AND_RETHROW()
89  }
90 
91  void on_block(const signed_block& block)
92  {
93  auto& db = _self.database();
94 
95  _current_buckets.clear();
96 
97  const auto& bucket_idx = db.template get_index<bucket_index, common_statistics::by_bucket>();
98 
99  for (const auto& bucket : _tracked_buckets)
100  {
101  auto open = fc::time_point_sec((db.head_block_time().sec_since_epoch() / bucket) * bucket);
102 
103  auto itr = bucket_idx.find(boost::make_tuple(bucket, open));
104  if (itr != bucket_idx.end())
105  {
106  _current_buckets.insert(itr->id);
107  }
108  else
109  {
110  const auto& new_bucket_obj = db.template create<Bucket>([&](Bucket& bo) {
111  bo.open = open;
112  bo.seconds = bucket;
113  });
114 
115  process_bucket_creation(new_bucket_obj);
116 
117  _current_buckets.insert(new_bucket_obj.id);
118 
119  // adjust history
120  if (_maximum_history_per_bucket_size > 0)
121  {
122  try
123  {
124  auto cutoff = fc::time_point_sec();
125  if (safe<uint64_t>(bucket) * safe<uint64_t>(_maximum_history_per_bucket_size)
126  < safe<uint64_t>(LIFE_TIME_PERIOD))
127  {
128  cutoff = fc::time_point_sec(
129  (safe<uint32_t>(db.head_block_time().sec_since_epoch())
130  - safe<uint32_t>(bucket) * safe<uint32_t>(_maximum_history_per_bucket_size))
131  .value);
132  }
133 
134  itr = bucket_idx.lower_bound(boost::make_tuple(bucket, fc::time_point_sec()));
135 
136  while (itr->seconds == bucket && itr->open < cutoff)
137  {
138  auto old_itr = itr;
139  ++itr;
140  db.remove(*old_itr);
141  }
142  }
143  catch (fc::overflow_exception& e)
144  {
145  }
146  catch (fc::underflow_exception& e)
147  {
148  }
149  }
150  }
151 
152  process_block(*itr, block);
153  }
154  }
155 };
156 
157 } // namespace common_statistics
158 } // namespace scorum
#define LIFE_TIME_PERIOD
virtual void process_post_operation(const Bucket &bucket, const operation_notification &o)
flat_set< typename Bucket::id_type > _current_buckets
virtual void process_block(const Bucket &bucket, const signed_block &b)
void pre_operation(const operation_notification &o)
void post_operation(const operation_notification &o)
virtual void process_pre_operation(const Bucket &bucket, const operation_notification &o)
virtual void process_bucket_creation(const Bucket &bucket)
shared_multi_index_container< bucket_object, indexed_by< ordered_unique< tag< by_id >, member< bucket_object, bucket_id_type, &bucket_object::id > >, ordered_unique< tag< common_statistics::by_bucket >, composite_key< bucket_object, member< common_statistics::base_bucket_object, uint32_t, &common_statistics::base_bucket_object::seconds >, member< common_statistics::base_bucket_object, fc::time_point_sec, &common_statistics::base_bucket_object::open > > > > > bucket_index
Definition: objects.hpp:59
Definition: asset.cpp:15