Issue #68 - created simple secondary index for accounts
This commit is contained in:
parent
b5b9d6d053
commit
8e9b2e8ebb
5 changed files with 165 additions and 4 deletions
|
|
@ -153,4 +153,87 @@ void account_object::options_type::validate() const
|
||||||
"May not specify fewer witnesses or committee members than the number voted for.");
|
"May not specify fewer witnesses or committee members than the number voted for.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set<object_id_type> account_member_index::get_members( const account_object& a )const
|
||||||
|
{
|
||||||
|
set<object_id_type> result;
|
||||||
|
for( auto auth : a.owner.auths )
|
||||||
|
result.insert(auth.first);
|
||||||
|
for( auto auth : a.active.auths )
|
||||||
|
result.insert(auth.first);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void account_member_index::object_inserted( const object& obj )
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<const account_object*>(&obj) ); // for debug only
|
||||||
|
const account_object& a = static_cast<const account_object&>(obj);
|
||||||
|
|
||||||
|
set<object_id_type> members = get_members(a);
|
||||||
|
for( auto item : members )
|
||||||
|
account_to_memberships[item].insert( obj.id );
|
||||||
|
}
|
||||||
|
|
||||||
|
void account_member_index::object_removed( const object& obj )
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<const account_object*>(&obj) ); // for debug only
|
||||||
|
const account_object& a = static_cast<const account_object&>(obj);
|
||||||
|
|
||||||
|
set<object_id_type> members = get_members(a);
|
||||||
|
for( auto item : members )
|
||||||
|
account_to_memberships[item].erase( obj.id );
|
||||||
|
}
|
||||||
|
|
||||||
|
void account_member_index::about_to_modify( const object& before )
|
||||||
|
{
|
||||||
|
before_members.clear();
|
||||||
|
assert( dynamic_cast<const account_object*>(&before) ); // for debug only
|
||||||
|
const account_object& a = static_cast<const account_object&>(before);
|
||||||
|
before_members = get_members(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void account_member_index::object_modified( const object& after )
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<const account_object*>(&after) ); // for debug only
|
||||||
|
const account_object& a = static_cast<const account_object&>(after);
|
||||||
|
set<object_id_type> after_members = get_members(a);
|
||||||
|
|
||||||
|
vector<object_id_type> removed; removed.reserve(before_members.size());
|
||||||
|
std::set_difference( before_members.begin(), before_members.end(),
|
||||||
|
after_members.begin(), after_members.end(),
|
||||||
|
std::inserter( removed, removed.end() ) );
|
||||||
|
|
||||||
|
for( auto itr = removed.begin(); itr != removed.end(); ++itr )
|
||||||
|
account_to_memberships[*itr].erase( after.id );
|
||||||
|
|
||||||
|
vector<object_id_type> added; added.reserve(after_members.size());
|
||||||
|
auto add_end = std::set_difference( after_members.begin(), after_members.end(),
|
||||||
|
before_members.begin(), before_members.end(),
|
||||||
|
std::inserter( added, added.end()) );
|
||||||
|
|
||||||
|
for( auto itr = added.begin(); itr != added.end(); ++itr )
|
||||||
|
account_to_memberships[*itr].insert( after.id );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void account_referrer_index::object_inserted( const object& obj )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void account_referrer_index::object_removed( const object& obj )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void account_referrer_index::about_to_modify( const object& before )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void account_referrer_index::object_modified( const object& after )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,10 @@ void database::initialize_indexes()
|
||||||
//Protocol object indexes
|
//Protocol object indexes
|
||||||
add_index< primary_index<asset_index> >();
|
add_index< primary_index<asset_index> >();
|
||||||
add_index< primary_index<force_settlement_index> >();
|
add_index< primary_index<force_settlement_index> >();
|
||||||
add_index< primary_index<account_index> >();
|
auto acnt_index = add_index< primary_index<account_index> >();
|
||||||
|
acnt_index->add_secondary_index<account_member_index>();
|
||||||
|
acnt_index->add_secondary_index<account_referrer_index>();
|
||||||
|
|
||||||
add_index< primary_index<simple_index<key_object>> >();
|
add_index< primary_index<simple_index<key_object>> >();
|
||||||
add_index< primary_index<delegate_index> >();
|
add_index< primary_index<delegate_index> >();
|
||||||
add_index< primary_index<witness_index> >();
|
add_index< primary_index<witness_index> >();
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,44 @@ class database;
|
||||||
delegate_id_type delegate_id; // optional
|
delegate_id_type delegate_id; // optional
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This secondary index will allow a reverse lookup of all accounts that a particular key or account
|
||||||
|
* is an potential signing authority.
|
||||||
|
*/
|
||||||
|
class account_member_index : public secondary_index
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void object_inserted( const object& obj ) override;
|
||||||
|
virtual void object_removed( const object& obj ) override;
|
||||||
|
virtual void about_to_modify( const object& before ) override;
|
||||||
|
virtual void object_modified( const object& after ) override;
|
||||||
|
|
||||||
|
|
||||||
|
/** given an account or key, map it to the set of accounts that reference it in an active or owner authority */
|
||||||
|
map< object_id_type, set<account_id_type> > account_to_memberships;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
set<object_id_type> get_members( const account_object& a )const;
|
||||||
|
set<object_id_type> before_members;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This secondary index will allow a reverse lookup of all accounts that have been referred by
|
||||||
|
* a particular account.
|
||||||
|
*/
|
||||||
|
class account_referrer_index : public secondary_index
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void object_inserted( const object& obj ) override;
|
||||||
|
virtual void object_removed( const object& obj ) override;
|
||||||
|
virtual void about_to_modify( const object& before ) override;
|
||||||
|
virtual void object_modified( const object& after ) override;
|
||||||
|
|
||||||
|
/** maps the referrer to the set of accounts that they have referred */
|
||||||
|
map< account_id_type, set<account_id_type> > referred_by;
|
||||||
|
};
|
||||||
|
|
||||||
struct by_asset;
|
struct by_asset;
|
||||||
struct by_account;
|
struct by_account;
|
||||||
struct by_balance;
|
struct by_balance;
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,16 @@ namespace graphene { namespace db {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class secondary_index
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~secondary_index(){};
|
||||||
|
virtual void object_inserted( const object& obj ){};
|
||||||
|
virtual void object_removed( const object& obj ){};
|
||||||
|
virtual void about_to_modify( const object& before ){};
|
||||||
|
virtual void object_modified( const object& after ){};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the common implementation
|
* Defines the common implementation
|
||||||
*/
|
*/
|
||||||
|
|
@ -143,13 +153,32 @@ namespace graphene { namespace db {
|
||||||
/** called just after obj is modified */
|
/** called just after obj is modified */
|
||||||
void on_modify( const object& obj );
|
void on_modify( const object& obj );
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void add_secondary_index()
|
||||||
|
{
|
||||||
|
_sindex.emplace_back( new T() );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& get_secondary_index()const
|
||||||
|
{
|
||||||
|
for( const auto& item : _sindex )
|
||||||
|
{
|
||||||
|
const T* result = dynamic_cast<const T*>(item.get());
|
||||||
|
if( result != nullptr ) return *result;
|
||||||
|
}
|
||||||
|
assert( !"invalid index type" );
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
vector< shared_ptr<index_observer> > _observers;
|
vector< shared_ptr<index_observer> > _observers;
|
||||||
|
vector< unique_ptr<secondary_index> > _sindex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
object_database& _db;
|
object_database& _db;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class primary_index
|
* @class primary_index
|
||||||
* @brief Wraps a derived index to intercept calls to create, modify, and remove so that
|
* @brief Wraps a derived index to intercept calls to create, modify, and remove so that
|
||||||
|
|
@ -215,12 +244,16 @@ namespace graphene { namespace db {
|
||||||
virtual const object& create(const std::function<void(object&)>& constructor )override
|
virtual const object& create(const std::function<void(object&)>& constructor )override
|
||||||
{
|
{
|
||||||
const auto& result = DerivedIndex::create( constructor );
|
const auto& result = DerivedIndex::create( constructor );
|
||||||
|
for( const auto& item : _sindex )
|
||||||
|
item->object_inserted( result );
|
||||||
on_add( result );
|
on_add( result );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void remove( const object& obj ) override
|
virtual void remove( const object& obj ) override
|
||||||
{
|
{
|
||||||
|
for( const auto& item : _sindex )
|
||||||
|
item->object_removed( obj );
|
||||||
on_remove(obj);
|
on_remove(obj);
|
||||||
DerivedIndex::remove(obj);
|
DerivedIndex::remove(obj);
|
||||||
}
|
}
|
||||||
|
|
@ -228,7 +261,11 @@ namespace graphene { namespace db {
|
||||||
virtual void modify( const object& obj, const std::function<void(object&)>& m )override
|
virtual void modify( const object& obj, const std::function<void(object&)>& m )override
|
||||||
{
|
{
|
||||||
save_undo( obj );
|
save_undo( obj );
|
||||||
|
for( const auto& item : _sindex )
|
||||||
|
item->about_to_modify( obj );
|
||||||
DerivedIndex::modify( obj, m );
|
DerivedIndex::modify( obj, m );
|
||||||
|
for( const auto& item : _sindex )
|
||||||
|
item->object_modified( obj );
|
||||||
on_modify( obj );
|
on_modify( obj );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ namespace graphene { namespace db {
|
||||||
const T& get( object_id<SpaceID,TypeID,T> id )const { return get<T>(id); }
|
const T& get( object_id<SpaceID,TypeID,T> id )const { return get<T>(id); }
|
||||||
|
|
||||||
template<typename IndexType>
|
template<typename IndexType>
|
||||||
const IndexType* add_index()
|
IndexType* add_index()
|
||||||
{
|
{
|
||||||
typedef typename IndexType::object_type ObjectType;
|
typedef typename IndexType::object_type ObjectType;
|
||||||
if( _index[ObjectType::space_id].size() <= ObjectType::type_id )
|
if( _index[ObjectType::space_id].size() <= ObjectType::type_id )
|
||||||
|
|
@ -130,7 +130,7 @@ namespace graphene { namespace db {
|
||||||
assert(!_index[ObjectType::space_id][ObjectType::type_id]);
|
assert(!_index[ObjectType::space_id][ObjectType::type_id]);
|
||||||
unique_ptr<index> indexptr( new IndexType(*this) );
|
unique_ptr<index> indexptr( new IndexType(*this) );
|
||||||
_index[ObjectType::space_id][ObjectType::type_id] = std::move(indexptr);
|
_index[ObjectType::space_id][ObjectType::type_id] = std::move(indexptr);
|
||||||
return static_cast<const IndexType*>(_index[ObjectType::space_id][ObjectType::type_id].get());
|
return static_cast<IndexType*>(_index[ObjectType::space_id][ObjectType::type_id].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_undo();
|
void pop_undo();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue