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.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -103,7 +103,10 @@ void database::initialize_indexes()
|
|||
//Protocol object indexes
|
||||
add_index< primary_index<asset_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<delegate_index> >();
|
||||
add_index< primary_index<witness_index> >();
|
||||
|
|
|
|||
|
|
@ -256,6 +256,44 @@ class database;
|
|||
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_account;
|
||||
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
|
||||
*/
|
||||
|
|
@ -143,13 +153,32 @@ namespace graphene { namespace db {
|
|||
/** called just after obj is modified */
|
||||
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:
|
||||
vector< shared_ptr<index_observer> > _observers;
|
||||
vector< shared_ptr<index_observer> > _observers;
|
||||
vector< unique_ptr<secondary_index> > _sindex;
|
||||
|
||||
private:
|
||||
object_database& _db;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class primary_index
|
||||
* @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
|
||||
{
|
||||
const auto& result = DerivedIndex::create( constructor );
|
||||
for( const auto& item : _sindex )
|
||||
item->object_inserted( result );
|
||||
on_add( result );
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void remove( const object& obj ) override
|
||||
{
|
||||
for( const auto& item : _sindex )
|
||||
item->object_removed( obj );
|
||||
on_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
|
||||
{
|
||||
save_undo( obj );
|
||||
for( const auto& item : _sindex )
|
||||
item->about_to_modify( obj );
|
||||
DerivedIndex::modify( obj, m );
|
||||
for( const auto& item : _sindex )
|
||||
item->object_modified( 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); }
|
||||
|
||||
template<typename IndexType>
|
||||
const IndexType* add_index()
|
||||
IndexType* add_index()
|
||||
{
|
||||
typedef typename IndexType::object_type ObjectType;
|
||||
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]);
|
||||
unique_ptr<index> indexptr( new IndexType(*this) );
|
||||
_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();
|
||||
|
|
|
|||
Loading…
Reference in a new issue