#include "base/callback.hh"
#include "base/cprintf.hh"
+#include "base/debug.hh"
#include "base/hostinfo.hh"
#include "base/misc.hh"
#include "base/statistics.hh"
assert(statsMap().find(this) != statsMap().end());
}
+void
+InfoAccess::setParams(const StorageParams *params)
+{
+ info()->storageParams = params;
+}
+
void
InfoAccess::setInit()
{
- info()->flags |= init;
+ info()->flags.set(init);
}
Info *
return (*i).second;
}
+StorageParams::~StorageParams()
+{
+}
+
+typedef map<std::string, Info *> NameMapType;
+NameMapType &
+nameMap()
+{
+ static NameMapType the_map;
+ return the_map;
+}
+
+int Info::id_count = 0;
+
+int debug_break_id = -1;
+
Info::Info()
- : flags(none), precision(-1), prereq(0)
+ : flags(none), precision(-1), prereq(0), storageParams(NULL)
{
- static int count = 0;
- id = count++;
+ id = id_count++;
+ if (debug_break_id >= 0 and debug_break_id == id)
+ debug_break();
}
Info::~Info()
{
}
+void
+Info::setName(const string &name)
+{
+ pair<NameMapType::iterator, bool> p =
+ nameMap().insert(make_pair(name, this));
+
+ Info *other = p.first->second;
+ bool result = p.second;
+
+ if (!result) {
+ // using other->name instead of just name to avoid a compiler
+ // warning. They should be the same.
+ panic("same statistic name used twice! name=%s\n", other->name);
+ }
+
+ this->name = name;
+}
+
bool
Info::less(Info *stat1, Info *stat2)
{
bool
Info::baseCheck() const
{
- if (!(flags & init)) {
+ if (!(flags & Stats::init)) {
#ifdef DEBUG
cprintf("this is stat number %d\n", id);
#endif
return false;
}
- if ((flags & print) && name.empty()) {
+ if ((flags & display) && name.empty()) {
panic("all printable stats must be named");
return false;
}
return true;
}
-
void
-FormulaBase::result(VResult &vec) const
+Info::enable()
{
- if (root)
- vec = root->result();
}
-Result
-FormulaBase::total() const
+void
+VectorInfo::enable()
{
- return root ? root->total() : 0.0;
+ size_type s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+ if (subdescs.size() < s)
+ subdescs.resize(s);
}
-size_type
-FormulaBase::size() const
+void
+VectorDistInfo::enable()
{
- if (!root)
- return 0;
- else
- return root->size();
+ size_type s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+ if (subdescs.size() < s)
+ subdescs.resize(s);
}
void
-FormulaBase::reset()
+Vector2dInfo::enable()
{
+ if (subnames.size() < x)
+ subnames.resize(x);
+ if (subdescs.size() < x)
+ subdescs.resize(x);
+ if (y_subnames.size() < y)
+ y_subnames.resize(y);
}
-bool
-FormulaBase::zero() const
+void
+HistStor::grow_out()
{
- VResult vec;
- result(vec);
- for (off_t i = 0; i < vec.size(); ++i)
- if (vec[i] != 0.0)
- return false;
- return true;
+ int size = cvec.size();
+ int zero = size / 2; // round down!
+ int top_half = zero + (size - zero + 1) / 2; // round up!
+ int bottom_half = (size - zero) / 2; // round down!
+
+ // grow down
+ int low_pair = zero - 1;
+ for (int i = zero - 1; i >= bottom_half; i--) {
+ cvec[i] = cvec[low_pair];
+ if (low_pair - 1 >= 0)
+ cvec[i] += cvec[low_pair - 1];
+ low_pair -= 2;
+ }
+ assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
+
+ for (int i = bottom_half - 1; i >= 0; i--)
+ cvec[i] = Counter();
+
+ // grow up
+ int high_pair = zero;
+ for (int i = zero; i < top_half; i++) {
+ cvec[i] = cvec[high_pair];
+ if (high_pair + 1 < size)
+ cvec[i] += cvec[high_pair + 1];
+ high_pair += 2;
+ }
+ assert(high_pair == size || high_pair == size + 1);
+
+ for (int i = top_half; i < size; i++)
+ cvec[i] = Counter();
+
+ max_bucket *= 2;
+ min_bucket *= 2;
+ bucket_size *= 2;
}
void
-FormulaBase::update(Info *)
+HistStor::grow_convert()
{
+ int size = cvec.size();
+ int half = (size + 1) / 2; // round up!
+ //bool even = (size & 1) == 0;
+
+ int pair = size - 1;
+ for (int i = size - 1; i >= half; --i) {
+ cvec[i] = cvec[pair];
+ if (pair - 1 >= 0)
+ cvec[i] += cvec[pair - 1];
+ pair -= 2;
+ }
+
+ for (int i = half - 1; i >= 0; i--)
+ cvec[i] = Counter();
+
+ min_bucket = -max_bucket;// - (even ? bucket_size : 0);
+ bucket_size *= 2;
}
-string
-FormulaBase::str() const
+void
+HistStor::grow_up()
{
- return root ? root->str() : "";
+ int size = cvec.size();
+ int half = (size + 1) / 2; // round up!
+
+ int pair = 0;
+ for (int i = 0; i < half; i++) {
+ cvec[i] = cvec[pair];
+ if (pair + 1 < size)
+ cvec[i] += cvec[pair + 1];
+ pair += 2;
+ }
+ assert(pair == size || pair == size + 1);
+
+ for (int i = half; i < size; i++)
+ cvec[i] = Counter();
+
+ max_bucket *= 2;
+ bucket_size *= 2;
}
Formula::Formula()
{
- setInit();
}
Formula::Formula(Temp r)
{
root = r;
+ setInit();
assert(size());
}
{
assert(!root && "Can't change formulas");
root = r;
+ setInit();
assert(size());
return *this;
}
{
if (root)
root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
- else
+ else {
root = r;
+ setInit();
+ }
+
assert(size());
return *this;
}
void
-check()
+Formula::result(VResult &vec) const
+{
+ if (root)
+ vec = root->result();
+}
+
+Result
+Formula::total() const
+{
+ return root ? root->total() : 0.0;
+}
+
+size_type
+Formula::size() const
+{
+ if (!root)
+ return 0;
+ else
+ return root->size();
+}
+
+void
+Formula::reset()
+{
+}
+
+bool
+Formula::zero() const
+{
+ VResult vec;
+ result(vec);
+ for (VResult::size_type i = 0; i < vec.size(); ++i)
+ if (vec[i] != 0.0)
+ return false;
+ return true;
+}
+
+string
+Formula::str() const
+{
+ return root ? root->str() : "";
+}
+
+void
+enable()
{
typedef list<Info *>::iterator iter_t;
Info *info = *i;
assert(info);
if (!info->check() || !info->baseCheck())
- panic("stat check failed for %s\n", info->name);
+ panic("stat check failed for '%s' %d\n", info->name, info->id);
}
off_t j = 0;
for (i = statsList().begin(); i != end; ++i) {
Info *info = *i;
- if (!(info->flags & print))
+ if (!(info->flags & display))
info->name = "__Stat" + to_string(j++);
}
statsList().sort(Info::less);
- if (i == end)
- return;
-
- iter_t last = i;
- ++i;
-
for (i = statsList().begin(); i != end; ++i) {
- if ((*i)->name == (*last)->name)
- panic("same name used twice! name=%s\n", (*i)->name);
+ Info *info = *i;
+ info->enable();
+ }
+}
- last = i;
+void
+prepare()
+{
+ list<Info *>::iterator i = statsList().begin();
+ list<Info *>::iterator end = statsList().end();
+ while (i != end) {
+ Info *info = *i;
+ info->prepare();
+ ++i;
}
}
resetQueue.add(cb);
}
-/* namespace Stats */ }
+} // namespace Stats