53 :
54 _data_file_path(bfs::absolute(dir/"shared_memory.bin")),
55 _database_name(dir.filename().string()),
56 _writable(writable)
57{
58 if(shared_file_size % _db_size_multiple_requirement) {
59 std::string what_str("Database must be mulitple of " + std::to_string(_db_size_multiple_requirement) + " bytes");
61 }
62#ifdef _WIN32
65#endif
66 if(!_writable && !bfs::exists(_data_file_path)){
67 std::string what_str("database file not found at " + _data_file_path.string());
69 }
70
71 bfs::create_directories(dir);
72
73 if(bfs::exists(_data_file_path)) {
75 std::ifstream hs(_data_file_path.generic_string(), std::ifstream::binary);
77 if(hs.fail())
79
80 db_header* dbheader = reinterpret_cast<db_header*>(header);
82 std::string what_str("\"" + _database_name + "\" database format not compatible with this version of chainbase.");
84 }
85 if(!allow_dirty && dbheader->dirty) {
86 std::string what_str("\"" + _database_name + "\" database dirty flag set");
88 }
90 std::cerr << "CHAINBASE: \"" << _database_name << "\" database was created with a chainbase from a different environment" << std::endl;
91 std::cerr << "Current compiler environment:" << std::endl;
93 std::cerr << "DB created with compiler environment:" << std::endl;
94 std::cerr << dbheader->dbenviron;
96 }
97 }
98
100 if(!bfs::exists(_data_file_path)) {
101 std::ofstream ofs(_data_file_path.generic_string(), std::ofstream::trunc);
102
103 ofs.close();
104 bfs::resize_file(_data_file_path, shared_file_size);
105 _file_mapping = bip::file_mapping(_data_file_path.generic_string().c_str(), bip::read_write);
106 _file_mapped_region = bip::mapped_region(_file_mapping, bip::read_write);
108 new (_file_mapped_region.get_address()) db_header;
109 }
110 else if(_writable) {
111 auto existing_file_size = bfs::file_size(_data_file_path);
112 size_t grow = 0;
113 if(shared_file_size > existing_file_size) {
114 grow = shared_file_size - existing_file_size;
115 bfs::resize_file(_data_file_path, shared_file_size);
116 }
117 else if(shared_file_size < existing_file_size) {
118 std::cerr << "CHAINBASE: \"" << _database_name << "\" requested size of " << shared_file_size << " is less than "
119 "existing size of " << existing_file_size << ". This database will not be shrunk and will "
120 "remain at " << existing_file_size << std::endl;
121 }
122 _file_mapping = bip::file_mapping(_data_file_path.generic_string().c_str(), bip::read_write);
123 _file_mapped_region = bip::mapped_region(_file_mapping, bip::read_write);
125 if(grow)
126 file_mapped_segment_manager->grow(grow);
127 }
128 else {
129 _file_mapping = bip::file_mapping(_data_file_path.generic_string().c_str(), bip::read_only);
130 _file_mapped_region = bip::mapped_region(_file_mapping, bip::read_only);
132 }
133
134 if(_writable) {
135
136 boost::system::error_code ec;
137 bfs::remove(bfs::absolute(dir/"shared_memory.meta"), ec);
138
139 _mapped_file_lock = bip::file_lock(_data_file_path.generic_string().c_str());
140 if(!_mapped_file_lock.try_lock())
142
143 set_mapped_file_db_dirty(true);
144 }
145
147 _segment_manager = file_mapped_segment_manager;
148 }
149 else {
150 boost::asio::io_service sig_ios;
151 boost::asio::signal_set sig_set(sig_ios, SIGINT, SIGTERM);
152#ifdef SIGPIPE
153 sig_set.add(SIGPIPE);
154#endif
155 sig_set.async_wait([](const boost::system::error_code&, int) {
157 });
158
159 try {
160 setup_non_file_mapping();
161 load_database_file(sig_ios);
162
163#ifndef _WIN32
165 if(mlock(_non_file_mapped_mapping, _non_file_mapped_mapping_size)) {
166 std::string what_str("Failed to mlock database \"" + _database_name + "\"");
168 }
169 std::cerr << "CHAINBASE: Database \"" << _database_name << "\" has been successfully locked in memory" << std::endl;
170 }
171#endif
172
173 _file_mapped_region = bip::mapped_region();
174 }
175 catch(...) {
176 if(_writable)
177 set_mapped_file_db_dirty(false);
178 throw;
179 }
180
182 }
183}
bip::managed_mapped_file::segment_manager segment_manager
std::error_code make_error_code(db_error_code e) noexcept
constexpr size_t header_size
constexpr uint64_t header_id