BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface software
object_database.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #pragma once
25 #include <graphene/db/object.hpp>
26 #include <graphene/db/index.hpp>
28 
29 #include <fc/log/logger.hpp>
30 
31 #include <map>
32 
33 namespace graphene { namespace db {
34 
40  {
41  public:
44 
45  void reset_indexes() { _index.clear(); _index.resize(255); }
46 
47  void open(const fc::path& data_dir );
48 
52  void flush();
53  void wipe(const fc::path& data_dir); // remove from disk
54  void close();
55 
56  template<typename T, typename F>
57  const T& create( F&& constructor )
58  {
59  auto& idx = get_mutable_index<T>();
60  return static_cast<const T&>( idx.create( [&](object& o)
61  {
62  assert( dynamic_cast<T*>(&o) );
63  constructor( static_cast<T&>(o) );
64  } ));
65  }
66 
69  template<typename IndexType>
70  const IndexType& get_index_type()const {
71  static_assert( std::is_base_of<index,IndexType>::value, "Type must be an index type" );
72  return static_cast<const IndexType&>( get_index( IndexType::object_type::space_id, IndexType::object_type::type_id ) );
73  }
74  template<typename T>
75  const index& get_index()const { return get_index(T::space_id,T::type_id); }
76  const index& get_index(uint8_t space_id, uint8_t type_id)const;
77  const index& get_index(object_id_type id)const { return get_index(id.space(),id.type()); }
79 
80  const object& get_object( object_id_type id )const;
81  const object* find_object( object_id_type id )const;
82 
86 
87  const object& insert( object&& obj ) { return get_mutable_index(obj.id).insert( std::move(obj) ); }
88  void remove( const object& obj ) { get_mutable_index(obj.id).remove( obj ); }
89  template<typename T, typename Lambda>
90  void modify( const T& obj, const Lambda& m ) {
91  get_mutable_index(obj.id).modify(obj,m);
92  }
93 
95 
96  template<typename T>
97  static const T& cast( const object& obj )
98  {
99  assert( nullptr != dynamic_cast<const T*>(&obj) );
100  return static_cast<const T&>(obj);
101  }
102  template<typename T>
103  static T& cast( object& obj )
104  {
105  assert( nullptr != dynamic_cast<T*>(&obj) );
106  return static_cast<T&>(obj);
107  }
108 
109  template<typename T>
110  const T& get( object_id_type id )const
111  {
112  const object& obj = get_object( id );
113  assert( nullptr != dynamic_cast<const T*>(&obj) );
114  return static_cast<const T&>(obj);
115  }
116  template<typename T>
117  const T* find( object_id_type id )const
118  {
119  const object* obj = find_object( id );
120  assert( !obj || nullptr != dynamic_cast<const T*>(obj) );
121  return static_cast<const T*>(obj);
122  }
123 
124  template<uint8_t SpaceID, uint8_t TypeID>
126  return find<object_downcast_t<decltype(id)>>(id);
127  }
128 
129  template<uint8_t SpaceID, uint8_t TypeID>
130  auto get( object_id<SpaceID,TypeID> id )const -> const object_downcast_t<decltype(id)>& {
131  return get<object_downcast_t<decltype(id)>>(id);
132  }
133 
134  template<typename IndexType>
135  IndexType* add_index()
136  {
137  typedef typename IndexType::object_type ObjectType;
138  if( _index[ObjectType::space_id].size() <= ObjectType::type_id )
139  _index[ObjectType::space_id].resize( 255 );
140  assert(!_index[ObjectType::space_id][ObjectType::type_id]);
141  unique_ptr<index> indexptr( new IndexType(*this) );
142  _index[ObjectType::space_id][ObjectType::type_id] = std::move(indexptr);
143  return static_cast<IndexType*>(_index[ObjectType::space_id][ObjectType::type_id].get());
144  }
145 
146  template<typename IndexType, typename SecondaryIndexType, typename... Args>
147  SecondaryIndexType* add_secondary_index( Args... args )
148  {
149  return get_mutable_index_type<IndexType>().template add_secondary_index<SecondaryIndexType, Args...>(args...);
150  }
151 
152  void pop_undo();
153 
154  fc::path get_data_dir()const { return _data_dir; }
155 
158  protected:
159  template<typename IndexType>
160  IndexType& get_mutable_index_type() {
161  static_assert( std::is_base_of<index,IndexType>::value, "Type must be an index type" );
162  return static_cast<IndexType&>( get_mutable_index( IndexType::object_type::space_id, IndexType::object_type::type_id ) );
163  }
164  template<typename T>
165  index& get_mutable_index() { return get_mutable_index(T::space_id,T::type_id); }
166  index& get_mutable_index(object_id_type id) { return get_mutable_index(id.space(),id.type()); }
167  index& get_mutable_index(uint8_t space_id, uint8_t type_id);
168 
169  private:
170 
171  friend class base_primary_index;
172  friend class undo_database;
173  void save_undo( const object& obj );
174  void save_undo_add( const object& obj );
175  void save_undo_remove( const object& obj );
176 
177  fc::path _data_dir;
178  vector< vector< unique_ptr<index> > > _index;
179  };
180 
181 } } // graphene::db
182 
183 
virtual void modify(const object &obj, const std::function< void(object &)> &)=0
SecondaryIndexType * add_secondary_index(Args...args)
const object & insert(object &&obj)
void modify(const T &obj, const Lambda &m)
const T * find(object_id_type id) const
const object * find_object(object_id_type id) const
Definition: api.cpp:56
static const T & cast(const object &obj)
auto find(object_id< SpaceID, TypeID > id) const -> const object_downcast_t< decltype(id)> *
const index & get_index() const
maintains a set of indexed objects that can be modified with multi-level rollback support ...
tracks changes to the state and allows changes to be undone
const index & get_index(object_id_type id) const
void wipe(const fc::path &data_dir)
static T & cast(object &obj)
index & get_mutable_index(object_id_type id)
virtual const object & insert(object &&obj)=0
typename object_downcast< ObjectID >::type object_downcast_t
Definition: object_id.hpp:105
virtual void remove(const object &obj)=0
void open(const fc::path &data_dir)
abstract base class for accessing objects indexed in various ways.
Definition: index.hpp:71
wraps boost::filesystem::path to provide platform independent path manipulation.
Definition: filesystem.hpp:28
const T & create(F &&constructor)
const object & get_object(object_id_type id) const
const IndexType & get_index_type() const