BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
object_database.cpp
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  */
25 
26 #include <fc/io/raw.hpp>
27 #include <fc/container/flat.hpp>
28 #include <fc/thread/parallel.hpp>
29 
30 namespace graphene { namespace db {
31 
33 :_undo_db(*this)
34 {
35  _index.resize(255);
36  _undo_db.enable();
37 }
38 
40 
42 {
43 }
44 
46 {
47  return get_index(id.space(),id.type()).find( id );
48 }
50 {
51  return get_index(id.space(),id.type()).get( id );
52 }
53 
54 const index& object_database::get_index(uint8_t space_id, uint8_t type_id)const
55 {
56  FC_ASSERT( _index.size() > space_id, "", ("space_id",space_id)("type_id",type_id)("index.size",_index.size()) );
57  FC_ASSERT( _index[space_id].size() > type_id, "", ("space_id",space_id)("type_id",type_id)("index[space_id].size",_index[space_id].size()) );
58  const auto& tmp = _index[space_id][type_id];
59  FC_ASSERT( tmp );
60  return *tmp;
61 }
62 index& object_database::get_mutable_index(uint8_t space_id, uint8_t type_id)
63 {
64  FC_ASSERT( _index.size() > space_id, "", ("space_id",space_id)("type_id",type_id)("index.size",_index.size()) );
65  FC_ASSERT( _index[space_id].size() > type_id , "", ("space_id",space_id)("type_id",type_id)("index[space_id].size",_index[space_id].size()) );
66  const auto& idx = _index[space_id][type_id];
67  FC_ASSERT( idx, "", ("space",space_id)("type",type_id) );
68  return *idx;
69 }
70 
72 {
73 // ilog("Save object_database in ${d}", ("d", _data_dir));
74  fc::create_directories( _data_dir / "object_database.tmp" / "lock" );
75  std::vector<fc::future<void>> tasks;
76  tasks.reserve(200);
77  for( uint32_t space = 0; space < _index.size(); ++space )
78  {
79  fc::create_directories( _data_dir / "object_database.tmp" / fc::to_string(space) );
80  const auto types = _index[space].size();
81  for( uint32_t type = 0; type < types; ++type )
82  if( _index[space][type] )
83  tasks.push_back( fc::do_parallel( [this,space,type] () {
84  _index[space][type]->save( _data_dir / "object_database.tmp" / fc::to_string(space)/fc::to_string(type) );
85  } ) );
86  }
87  for( auto& task : tasks )
88  task.wait();
89  fc::remove_all( _data_dir / "object_database.tmp" / "lock" );
90  if( fc::exists( _data_dir / "object_database" ) )
91  fc::rename( _data_dir / "object_database", _data_dir / "object_database.old" );
92  fc::rename( _data_dir / "object_database.tmp", _data_dir / "object_database" );
93  fc::remove_all( _data_dir / "object_database.old" );
94 }
95 
96 void object_database::wipe(const fc::path& data_dir)
97 {
98  close();
99  ilog("Wiping object database...");
100  fc::remove_all(data_dir / "object_database");
101  ilog("Done wiping object databse.");
102 }
103 
104 void object_database::open(const fc::path& data_dir)
105 { try {
106  _data_dir = data_dir;
107  if( fc::exists( _data_dir / "object_database" / "lock" ) )
108  {
109  wlog("Ignoring locked object_database");
110  return;
111  }
112  std::vector<fc::future<void>> tasks;
113  tasks.reserve(200);
114  ilog("Opening object database from ${d} ...", ("d", data_dir));
115  for( uint32_t space = 0; space < _index.size(); ++space )
116  for( uint32_t type = 0; type < _index[space].size(); ++type )
117  if( _index[space][type] )
118  tasks.push_back( fc::do_parallel( [this,space,type] () {
119  _index[space][type]->open( _data_dir / "object_database" / fc::to_string(space)/fc::to_string(type) );
120  } ) );
121  for( auto& task : tasks )
122  task.wait();
123  ilog( "Done opening object database." );
124 
125 } FC_CAPTURE_AND_RETHROW( (data_dir) ) }
126 
127 
129 { try {
132 
133 void object_database::save_undo( const object& obj )
134 {
135  _undo_db.on_modify( obj );
136 }
137 
138 void object_database::save_undo_add( const object& obj )
139 {
140  _undo_db.on_create( obj );
141 }
142 
143 void object_database::save_undo_remove(const object& obj)
144 {
145  _undo_db.on_remove( obj );
146 }
147 
148 } } // namespace graphene::db
bool exists(const path &p)
Definition: filesystem.cpp:209
const object * find_object(object_id_type id) const
Definition: api.cpp:56
void rename(const path &from, const path &to)
Definition: filesystem.cpp:302
void on_create(const object &obj)
auto do_parallel(Functor &&f, const char *desc FC_TASK_NAME_DEFAULT_ARG) -> fc::future< decltype(f())>
Definition: parallel.hpp:97
void create_directories(const path &p)
Definition: filesystem.cpp:210
void remove_all(const path &p)
Definition: filesystem.cpp:240
#define wlog(FORMAT,...)
Definition: logger.hpp:123
virtual const object * find(object_id_type id) const =0
const index & get_index() const
#define ilog(FORMAT,...)
Definition: logger.hpp:117
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
void on_modify(const object &obj)
void wipe(const fc::path &data_dir)
std::string to_string(double)
Definition: string.cpp:73
const object & get(object_id_type id) const
Definition: index.hpp:111
void open(const fc::path &data_dir)
abstract base class for accessing objects indexed in various ways.
Definition: index.hpp:71
void on_remove(const object &obj)
wraps boost::filesystem::path to provide platform independent path manipulation.
Definition: filesystem.hpp:28
const object & get_object(object_id_type id) const