BitShares-Core  6.1.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:
43  virtual ~object_database() = default;
44 
45  static constexpr uint8_t _index_size = 255;
46 
48  {
49  _index.clear();
50  _index.resize(_index_size);
51  }
52 
53  void open(const fc::path& data_dir );
54 
58  void flush();
59  void wipe(const fc::path& data_dir); // remove from disk
60  void close();
61 
62  template<typename T, typename F>
63  const T& create( F&& constructor )
64  {
65  auto& idx = get_mutable_index<T>();
66  return static_cast<const T&>( idx.create( [&](object& o)
67  {
68  assert( dynamic_cast<T*>(&o) );
69  constructor( static_cast<T&>(o) );
70  } ));
71  }
72 
76  template<typename IndexType>
77  const IndexType& get_index_type()const {
78  static_assert( std::is_base_of<index,IndexType>::value, "Type must be an index type" );
79  return static_cast<const IndexType&>( get_index( IndexType::object_type::space_id,
80  IndexType::object_type::type_id ) );
81  }
82  template<typename T>
83  const index& get_index()const { return get_index(T::space_id,T::type_id); }
84  const index& get_index(uint8_t space_id, uint8_t type_id)const;
85  const index& get_index(const object_id_type& id)const { return get_index(id.space(),id.type()); }
87 
88  const object& get_object( const object_id_type& id )const;
89  const object* find_object( const object_id_type& id )const;
90 
95 
96  const object& insert( object&& obj ) { return get_mutable_index(obj.id).insert( std::move(obj) ); }
97  void remove( const object& obj ) { get_mutable_index(obj.id).remove( obj ); }
98  template<typename T, typename Lambda>
99  void modify( const T& obj, const Lambda& m ) {
100  get_mutable_index(obj.id).modify(obj,m);
101  }
102 
104 
105  template<typename T>
106  static const T& cast( const object& obj )
107  {
108  assert( nullptr != dynamic_cast<const T*>(&obj) );
109  return static_cast<const T&>(obj);
110  }
111  template<typename T>
112  static T& cast( object& obj )
113  {
114  assert( nullptr != dynamic_cast<T*>(&obj) );
115  return static_cast<T&>(obj);
116  }
117 
118  template<typename T>
119  const T& get( const object_id_type& id )const
120  {
121  const object& obj = get_object( id );
122  assert( nullptr != dynamic_cast<const T*>(&obj) );
123  return static_cast<const T&>(obj);
124  }
125  template<typename T>
126  const T* find( const object_id_type& id )const
127  {
128  const object* obj = find_object( id );
129  assert( !obj || nullptr != dynamic_cast<const T*>(obj) );
130  return static_cast<const T*>(obj);
131  }
132 
133  template<uint8_t SpaceID, uint8_t TypeID>
135  return find<object_downcast_t<decltype(id)>>(object_id_type(id));
136  }
137 
138  template<uint8_t SpaceID, uint8_t TypeID>
139  auto get( const object_id<SpaceID,TypeID>& id )const -> const object_downcast_t<decltype(id)>& {
140  return get<object_downcast_t<decltype(id)>>(object_id_type(id));
141  }
142 
143  template<typename IndexType>
144  IndexType* add_index()
145  {
146  using ObjectType = typename IndexType::object_type;
147  const auto space_id = ObjectType::space_id;
148  const auto type_id = ObjectType::type_id;
149  FC_ASSERT( space_id < _index.size(), "Space ID ${s} overflow", ("s",space_id) );
150  if( _index[space_id].size() <= type_id )
151  _index[space_id].resize( _index_size );
152  FC_ASSERT( type_id < _index[space_id].size(), "Type ID ${t} overflow", ("t",type_id) );
153  FC_ASSERT( !_index[space_id][type_id], "Index ${s}.${t} already exists", ("s",space_id)("t",type_id) );
154  _index[space_id][type_id] = std::make_unique<IndexType>(*this);
155  return static_cast<IndexType*>(_index[space_id][type_id].get());
156  }
157 
158  template<typename IndexType, typename SecondaryIndexType, typename... Args>
159  SecondaryIndexType* add_secondary_index( Args... args )
160  {
161  return get_mutable_index_type<IndexType>().template
162  add_secondary_index<SecondaryIndexType, Args...>(args...);
163  }
164 
165  void pop_undo();
166 
167  fc::path get_data_dir()const { return _data_dir; }
168 
171  protected:
172  template<typename IndexType>
173  IndexType& get_mutable_index_type() {
174  static_assert( std::is_base_of<index,IndexType>::value, "Type must be an index type" );
175  return static_cast<IndexType&>( get_mutable_index( IndexType::object_type::space_id,
176  IndexType::object_type::type_id ) );
177  }
178  template<typename T>
179  index& get_mutable_index() { return get_mutable_index(T::space_id,T::type_id); }
180  index& get_mutable_index(const object_id_type& id) { return get_mutable_index(id.space(),id.type()); }
181  index& get_mutable_index(uint8_t space_id, uint8_t type_id);
182 
183  private:
184 
185  friend class base_primary_index;
186  friend class undo_database;
187  void save_undo( const object& obj );
188  void save_undo_add( const object& obj );
189  void save_undo_remove( const object& obj );
190 
191  fc::path _data_dir;
192  std::vector< std::vector< std::unique_ptr<index> > > _index;
193  };
194 
195 } } // graphene::db
196 
197 
virtual void modify(const object &obj, const std::function< void(object &)> &)=0
const object & insert(object &&obj)
void modify(const T &obj, const Lambda &m)
SecondaryIndexType * add_secondary_index(Args... args)
const IndexType & get_index_type() const
Definition: api.cpp:48
static const T & cast(const object &obj)
index & get_mutable_index(const object_id_type &id)
static constexpr uint8_t _index_size
const T * find(const object_id_type &id) const
const object & get_object(const object_id_type &id) 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
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
const index & get_index(const object_id_type &id) const
const index & get_index() const
void wipe(const fc::path &data_dir)
static T & cast(object &obj)
virtual const object & insert(object &&obj)=0
typename object_downcast< ObjectID >::type object_downcast_t
Definition: object_id.hpp:100
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:70
auto find(const object_id< SpaceID, TypeID > &id) const -> const object_downcast_t< decltype(id)> *
virtual ~object_database()=default
const object * find_object(const object_id_type &id) const
wraps boost::filesystem::path to provide platform independent path manipulation.
Definition: filesystem.hpp:28
const T & create(F &&constructor)