0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-17 23:40:57 +01:00

ircd::db: Improve column find by name from linear to logn; can still be O(1) with more work.

This commit is contained in:
Jason Volk 2017-11-15 17:29:54 -08:00
parent 0da55e93aa
commit 87c6f91530
2 changed files with 54 additions and 29 deletions

View file

@ -61,6 +61,7 @@ struct ircd::db::database
struct comparator;
struct prefix_transform;
struct column;
using description = std::vector<descriptor>;
// central collection of open databases for iteration (non-owning)
@ -74,7 +75,9 @@ struct ircd::db::database
std::shared_ptr<struct events> events;
std::shared_ptr<struct mergeop> mergeop;
std::shared_ptr<rocksdb::Cache> cache;
std::map<std::string, size_t, std::less<>> column_names;
std::vector<descriptor> descriptors;
std::vector<string_view> column_names;
std::unordered_map<string_view, size_t> column_index;
std::vector<std::shared_ptr<column>> columns;
custom_ptr<rocksdb::DB> d;
unique_const_iterator<decltype(dbs)> dbs_it;

View file

@ -408,28 +408,42 @@ try
const auto lru_cache_size{64_MiB};
return rocksdb::NewLRUCache(lru_cache_size);
}()}
,column_names{[this, &description]
,descriptors
{
// Existing columns
const auto opts(make_dbopts(std::string(this->optstr)));
std::move(description)
}
,column_names{[this]
{
// Existing columns at path. If any are left the descriptor set did not
// describe all of the columns found in the database at path.
const auto opts{make_dbopts(std::string(this->optstr))};
const auto required{db::column_names(path, opts)};
std::set<string_view> existing{begin(required), end(required)};
std::set<std::string> existing;
for(auto &column_name : db::column_names(path, opts))
existing.emplace(std::move(column_name));
decltype(this->column_names) ret;
for(const auto &descriptor : description)
// The names of the columns extracted from the descriptor set
std::vector<string_view> ret(descriptors.size());
std::transform(begin(descriptors), end(descriptors), begin(ret), [&existing]
(const auto &descriptor) -> string_view
{
existing.erase(descriptor.name);
ret.emplace(descriptor.name, -1);
}
return descriptor.name;
});
for(const auto &remain : existing)
throw error("Failed to describe existing column '%s'", remain);
throw error("Failed to describe existing column '%s' (and %zd others...)",
remain,
existing.size() - 1);
return ret;
}()}
,column_index{[this]
{
decltype(this->column_index) ret;
for(const auto &descriptor : this->descriptors)
ret.emplace(descriptor.name, -1);
return ret;
}()}
,d{[this, &description]
,d{[this]
{
bool fsck{false};
bool read_only{false};
@ -462,7 +476,7 @@ try
opts.row_cache = this->cache;
// Setup column families
for(const auto &desc : description)
for(const auto &desc : descriptors)
{
const auto c
{
@ -515,10 +529,12 @@ try
rocksdb::DB::Open(opts, path, columns, &handles, &ptr)
};
try // Assign the column index numbers given by db
{
for(const auto &handle : handles)
{
this->columns.at(handle->GetID())->handle.reset(handle);
this->column_names.at(handle->GetName()) = handle->GetID();
this->column_index.at(handle->GetName()) = handle->GetID();
}
for(size_t i(0); i < this->columns.size(); ++i)
@ -527,6 +543,12 @@ try
i,
db::id(*this->columns[i]),
db::name(*this->columns[i]));
}
catch(const std::exception &e)
{
delete ptr;
throw;
}
return custom_ptr<rocksdb::DB>
{
@ -645,8 +667,8 @@ ircd::db::database::operator()(const sopts &sopts,
ircd::db::database::column &
ircd::db::database::operator[](const string_view &name)
{
const auto it{column_names.find(name)};
if(unlikely(it == std::end(column_names)))
const auto it{column_index.find(name)};
if(unlikely(it == std::end(column_index)))
throw schema_error("'%s': column '%s' is not available or specified in schema",
this->name,
name);
@ -671,8 +693,8 @@ const ircd::db::database::column &
ircd::db::database::operator[](const string_view &name)
const
{
const auto it{column_names.find(name)};
if(unlikely(it == std::end(column_names)))
const auto it{column_index.find(name)};
if(unlikely(it == std::end(column_index)))
throw schema_error("'%s': column '%s' is not available or specified in schema",
this->name,
name);