2019-03-12 23:00:14 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
|
2020-06-17 07:33:13 +02:00
|
|
|
decltype(ircd::stats::NAME_MAX_LEN)
|
|
|
|
ircd::stats::NAME_MAX_LEN
|
|
|
|
{
|
|
|
|
127
|
|
|
|
};
|
|
|
|
|
2019-03-12 23:00:14 +01:00
|
|
|
decltype(ircd::stats::items)
|
|
|
|
ircd::stats::items
|
|
|
|
{};
|
|
|
|
|
2019-05-06 04:01:29 +02:00
|
|
|
std::ostream &
|
2020-06-17 07:33:13 +02:00
|
|
|
ircd::stats::operator<<(std::ostream &s,
|
|
|
|
const item<void> &item_)
|
2020-06-18 05:28:05 +02:00
|
|
|
{
|
|
|
|
thread_local char tmp[256];
|
|
|
|
s << string(tmp, item_);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::stats::string(const mutable_buffer &buf,
|
|
|
|
const item<void> &item_)
|
2019-05-06 04:01:29 +02:00
|
|
|
{
|
2020-06-17 07:33:13 +02:00
|
|
|
if(item_.type == typeid(uint64_t *))
|
|
|
|
{
|
|
|
|
const auto &item
|
|
|
|
{
|
|
|
|
dynamic_cast<const stats::item<uint64_t *> &>(item_)
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(item.val);
|
2020-06-18 05:28:05 +02:00
|
|
|
return fmt::sprintf
|
|
|
|
{
|
|
|
|
buf, "%lu", *item.val
|
|
|
|
};
|
2020-06-17 07:33:13 +02:00
|
|
|
}
|
|
|
|
else if(item_.type == typeid(uint32_t *))
|
|
|
|
{
|
|
|
|
const auto &item
|
|
|
|
{
|
|
|
|
dynamic_cast<const stats::item<uint32_t *> &>(item_)
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(item.val);
|
2020-06-18 05:28:05 +02:00
|
|
|
return fmt::sprintf
|
|
|
|
{
|
|
|
|
buf, "%u", *item.val
|
|
|
|
};
|
2020-06-17 07:33:13 +02:00
|
|
|
}
|
|
|
|
else if(item_.type == typeid(uint16_t *))
|
|
|
|
{
|
|
|
|
const auto &item
|
|
|
|
{
|
|
|
|
dynamic_cast<const stats::item<uint16_t *> &>(item_)
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(item.val);
|
2020-06-18 05:28:05 +02:00
|
|
|
return fmt::sprintf
|
|
|
|
{
|
|
|
|
buf, "%u", *item.val
|
|
|
|
};
|
2020-06-17 07:33:13 +02:00
|
|
|
}
|
2020-06-18 05:28:05 +02:00
|
|
|
else throw error
|
|
|
|
{
|
|
|
|
"Unsupported value type '%s'",
|
|
|
|
item_.type.name(),
|
|
|
|
};
|
2019-05-06 04:01:29 +02:00
|
|
|
}
|
|
|
|
|
2019-03-12 23:00:14 +01:00
|
|
|
//
|
|
|
|
// item
|
|
|
|
//
|
|
|
|
|
2019-05-06 04:01:29 +02:00
|
|
|
//
|
|
|
|
// item::item
|
|
|
|
//
|
|
|
|
|
2020-06-17 07:33:13 +02:00
|
|
|
ircd::stats::item<void>::item(const std::type_index &type,
|
|
|
|
const json::members &opts)
|
|
|
|
:type
|
2019-03-12 23:00:14 +01:00
|
|
|
{
|
2020-06-17 07:33:13 +02:00
|
|
|
type
|
2019-03-12 23:00:14 +01:00
|
|
|
}
|
|
|
|
,feature
|
|
|
|
{
|
2020-06-17 07:33:13 +02:00
|
|
|
opts
|
2019-03-12 23:00:14 +01:00
|
|
|
}
|
2020-12-18 12:25:16 +01:00
|
|
|
,name
|
|
|
|
{
|
|
|
|
this->operator[]("name")
|
|
|
|
}
|
2019-03-12 23:00:14 +01:00
|
|
|
{
|
2020-12-18 03:24:45 +01:00
|
|
|
if(unlikely(!name))
|
|
|
|
throw invalid
|
2020-06-17 07:33:13 +02:00
|
|
|
{
|
|
|
|
"Stats item must have a 'name' string feature"
|
|
|
|
};
|
|
|
|
|
2020-12-18 03:24:45 +01:00
|
|
|
if(unlikely(name.size() > NAME_MAX_LEN))
|
|
|
|
throw invalid
|
2019-03-12 23:00:14 +01:00
|
|
|
{
|
|
|
|
"Stats item '%s' name length:%zu exceeds max:%zu",
|
|
|
|
name,
|
|
|
|
name.size(),
|
|
|
|
NAME_MAX_LEN
|
|
|
|
};
|
|
|
|
|
2020-12-18 12:25:16 +01:00
|
|
|
static const auto less
|
|
|
|
{
|
|
|
|
[](const auto &a, const auto &b)
|
|
|
|
{
|
|
|
|
return a->name < b->name;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const auto exists
|
|
|
|
{
|
|
|
|
std::binary_search(begin(items), end(items), this, less)
|
|
|
|
};
|
|
|
|
|
|
|
|
if(unlikely(exists))
|
2020-12-18 03:24:45 +01:00
|
|
|
throw invalid
|
2019-03-12 23:00:14 +01:00
|
|
|
{
|
2020-12-18 03:24:45 +01:00
|
|
|
"Stats item named '%s' already exists",
|
|
|
|
name
|
2019-03-12 23:00:14 +01:00
|
|
|
};
|
2020-12-18 12:25:16 +01:00
|
|
|
|
|
|
|
if(items.empty())
|
|
|
|
items.reserve(4096);
|
|
|
|
|
|
|
|
items.emplace_back(this);
|
|
|
|
std::sort(begin(items), end(items), less);
|
2019-03-12 23:00:14 +01:00
|
|
|
}
|
|
|
|
|
2020-06-17 07:33:13 +02:00
|
|
|
ircd::stats::item<void>::~item()
|
2019-03-12 23:00:14 +01:00
|
|
|
noexcept
|
|
|
|
{
|
2020-12-18 12:25:16 +01:00
|
|
|
if(!name)
|
|
|
|
return;
|
2020-06-17 07:33:13 +02:00
|
|
|
|
2020-12-18 12:25:16 +01:00
|
|
|
const auto eit
|
2019-03-12 23:00:14 +01:00
|
|
|
{
|
2020-12-18 12:25:16 +01:00
|
|
|
std::remove_if(begin(items), end(items), [this]
|
|
|
|
(const auto &item)
|
2020-06-17 07:33:13 +02:00
|
|
|
{
|
2020-12-18 12:25:16 +01:00
|
|
|
return item->name == this->name;
|
|
|
|
})
|
|
|
|
};
|
2020-06-17 07:33:13 +02:00
|
|
|
|
2020-12-18 12:25:16 +01:00
|
|
|
items.erase(eit, end(items));
|
2019-03-12 23:00:14 +01:00
|
|
|
}
|
2020-06-17 07:33:13 +02:00
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::stats::item<void>::operator[](const string_view &key)
|
|
|
|
const noexcept
|
|
|
|
{
|
|
|
|
const json::object feature
|
|
|
|
{
|
|
|
|
this->feature
|
|
|
|
};
|
|
|
|
|
|
|
|
return feature[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// pointer-to-value items
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// item<uint64_t *>
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::stats::item<uint64_t *>::item(uint64_t *const &val,
|
|
|
|
const json::members &feature)
|
|
|
|
:item<void>
|
|
|
|
{
|
|
|
|
typeid(uint64_t *), feature
|
|
|
|
}
|
|
|
|
,val
|
|
|
|
{
|
|
|
|
val
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// item<uint32_t *>
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::stats::item<uint32_t *>::item(uint32_t *const &val,
|
|
|
|
const json::members &feature)
|
|
|
|
:item<void>
|
|
|
|
{
|
|
|
|
typeid(uint32_t *), feature
|
|
|
|
}
|
|
|
|
,val
|
|
|
|
{
|
|
|
|
val
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// item<uint16_t *>
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::stats::item<uint16_t *>::item(uint16_t *const &val,
|
|
|
|
const json::members &feature)
|
|
|
|
:item<void>
|
|
|
|
{
|
|
|
|
typeid(uint16_t *), feature
|
|
|
|
}
|
|
|
|
,val
|
|
|
|
{
|
|
|
|
val
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// value-carrying items
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// item<uint64_t>
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::stats::item<uint64_t>::item(const json::members &feature)
|
|
|
|
:item<uint64_t *>
|
|
|
|
{
|
|
|
|
std::addressof(this->val), feature
|
|
|
|
}
|
|
|
|
,val
|
|
|
|
{
|
|
|
|
0UL
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// item<uint32_t>
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::stats::item<uint32_t>::item(const json::members &feature)
|
|
|
|
:item<uint32_t *>
|
|
|
|
{
|
|
|
|
std::addressof(this->val), feature
|
|
|
|
}
|
|
|
|
,val
|
|
|
|
{
|
|
|
|
0U
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// item<uint16_t>
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::stats::item<uint16_t>::item(const json::members &feature)
|
|
|
|
:item<uint16_t *>
|
|
|
|
{
|
|
|
|
std::addressof(this->val), feature
|
|
|
|
}
|
|
|
|
,val
|
|
|
|
{
|
|
|
|
0U
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|