Skip to content

Commit 35297a4

Browse files
authored
remove file mapping member in order to free file handles earlier (#401)
remove file_mapping member, see #400
1 parent a1f6b73 commit 35297a4

File tree

3 files changed

+47
-45
lines changed

3 files changed

+47
-45
lines changed

keyvi/.clang-tidy

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ Checks: "*,
1616
"
1717
HeaderFilterRegex: ''
1818
FormatStyle: none
19+
CheckOptions:
20+
- key: misc-include-cleaner.IgnoreHeaders
21+
# The following files are ignored when clang-tidy analyzes header
22+
# inclusions:
23+
# - boost detail
24+
value: '
25+
boost/.*/detail/.*\.hpp;
26+
'

keyvi/include/keyvi/dictionary/fsa/automata.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,21 +91,23 @@ class Automata final {
9191
explicit Automata(const dictionary_properties_t& dictionary_properties, loading_strategy_types loading_strategy,
9292
const bool load_value_store)
9393
: dictionary_properties_(dictionary_properties) {
94-
file_mapping_ = boost::interprocess::file_mapping(dictionary_properties_->GetFileName().c_str(),
95-
boost::interprocess::read_only);
94+
boost::interprocess::file_mapping file_mapping = boost::interprocess::file_mapping(
95+
dictionary_properties_->GetFileName().c_str(), boost::interprocess::read_only);
9696

9797
const boost::interprocess::map_options_t map_options =
9898
internal::MemoryMapFlags::FSAGetMemoryMapOptions(loading_strategy);
9999

100100
TRACE("labels start offset: %d", dictionary_properties_->GetPersistenceOffset());
101-
labels_region_ = boost::interprocess::mapped_region(file_mapping_, boost::interprocess::read_only,
102-
dictionary_properties_->GetPersistenceOffset(),
103-
dictionary_properties_->GetSparseArraySize(), 0, map_options);
101+
labels_region_ = boost::interprocess::mapped_region(
102+
file_mapping, boost::interprocess::read_only,
103+
static_cast<boost::interprocess::offset_t>(dictionary_properties_->GetPersistenceOffset()),
104+
dictionary_properties_->GetSparseArraySize(), nullptr, map_options);
104105

105106
TRACE("transitions start offset: %d", dictionary_properties_->GetTransitionsOffset());
106107
transitions_region_ = boost::interprocess::mapped_region(
107-
file_mapping_, boost::interprocess::read_only, dictionary_properties_->GetTransitionsOffset(),
108-
dictionary_properties_->GetTransitionsSize(), 0, map_options);
108+
file_mapping, boost::interprocess::read_only,
109+
static_cast<boost::interprocess::offset_t>(dictionary_properties_->GetTransitionsOffset()),
110+
dictionary_properties_->GetTransitionsSize(), nullptr, map_options);
109111

110112
const auto advise = internal::MemoryMapFlags::FSAGetMemoryMapAdvices(loading_strategy);
111113

@@ -117,7 +119,7 @@ class Automata final {
117119

118120
if (load_value_store) {
119121
value_store_reader_.reset(
120-
internal::ValueStoreFactory::MakeReader(dictionary_properties_->GetValueStoreType(), &file_mapping_,
122+
internal::ValueStoreFactory::MakeReader(dictionary_properties_->GetValueStoreType(), &file_mapping,
121123
dictionary_properties_->GetValueStoreProperties(), loading_strategy));
122124
}
123125
}
@@ -415,7 +417,6 @@ class Automata final {
415417
private:
416418
dictionary_properties_t dictionary_properties_;
417419
std::unique_ptr<internal::IValueStoreReader> value_store_reader_;
418-
boost::interprocess::file_mapping file_mapping_;
419420
boost::interprocess::mapped_region labels_region_;
420421
boost::interprocess::mapped_region transitions_region_;
421422
unsigned char* labels_;

keyvi/include/keyvi/dictionary/fsa/internal/memory_map_manager.h

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
#define KEYVI_DICTIONARY_FSA_INTERNAL_MEMORY_MAP_MANAGER_H_
2727

2828
#include <algorithm>
29+
#include <cstring>
2930
#include <fstream>
3031
#include <string>
32+
#include <utility>
3133
#include <vector>
3234

3335
#include <boost/filesystem.hpp>
@@ -59,13 +61,7 @@ class MemoryMapManager final {
5961
MemoryMapManager(const size_t chunk_size, const boost::filesystem::path directory,
6062
const boost::filesystem::path filename_pattern)
6163
: chunk_size_(chunk_size), directory_(directory), filename_pattern_(filename_pattern) {}
62-
63-
~MemoryMapManager() {
64-
for (auto& m : mappings_) {
65-
delete m.mapping_;
66-
delete m.region_;
67-
}
68-
}
64+
~MemoryMapManager() = default;
6965

7066
/* Using GetAdress to read multiple bytes is unsafe as it might be a buffer overflow
7167
*
@@ -82,7 +78,8 @@ class MemoryMapManager final {
8278

8379
void* chunk_address = GetChunk(chunk_number);
8480

85-
return (reinterpret_cast<char*>(chunk_address) + chunk_offset);
81+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
82+
return static_cast<char*>(chunk_address) + chunk_offset;
8683
}
8784

8885
/* Get a buffer as copy.
@@ -97,12 +94,15 @@ class MemoryMapManager final {
9794
size_t second_chunk_size = buffer_length - first_chunk_size;
9895

9996
void* chunk_address = GetChunk(chunk_number);
100-
std::memcpy(buffer, reinterpret_cast<char*>(chunk_address) + chunk_offset, first_chunk_size);
97+
98+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
99+
std::memcpy(buffer, static_cast<char*>(chunk_address) + chunk_offset, first_chunk_size);
101100

102101
if (second_chunk_size > 0) {
103102
void* chunk_address_part2 = GetChunk(chunk_number + 1);
104-
std::memcpy(reinterpret_cast<char*>(buffer) + first_chunk_size,
105-
reinterpret_cast<const char*>(chunk_address_part2), second_chunk_size);
103+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
104+
std::memcpy(static_cast<char*>(buffer) + first_chunk_size, static_cast<const char*>(chunk_address_part2),
105+
second_chunk_size);
106106
}
107107
}
108108

@@ -129,8 +129,9 @@ class MemoryMapManager final {
129129
size_t copy_size = std::min(remaining, chunk_size_ - chunk_offset);
130130
TRACE("copy size: %ld", copy_size);
131131

132-
std::memcpy(reinterpret_cast<char*>(chunk_address) + chunk_offset,
133-
reinterpret_cast<const char*>(buffer) + buffer_offset, copy_size);
132+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
133+
std::memcpy(static_cast<char*>(chunk_address) + chunk_offset, static_cast<const char*>(buffer) + buffer_offset,
134+
copy_size);
134135

135136
remaining -= copy_size;
136137
tail_ += copy_size;
@@ -154,7 +155,8 @@ class MemoryMapManager final {
154155
void* chunk_address = GetChunk(chunk_number);
155156
size_t first_chunk_size = std::min(buffer_length, chunk_size_ - chunk_offset);
156157

157-
if (std::memcmp(reinterpret_cast<char*>(chunk_address) + chunk_offset, buffer, first_chunk_size) != 0) {
158+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
159+
if (std::memcmp(static_cast<char*>(chunk_address) + chunk_offset, buffer, first_chunk_size) != 0) {
158160
return false;
159161
}
160162

@@ -165,9 +167,10 @@ class MemoryMapManager final {
165167

166168
// handle overflow
167169
void* chunk_address_part2 = GetChunk(chunk_number + 1);
168-
return (std::memcmp(reinterpret_cast<const char*>(chunk_address_part2),
169-
reinterpret_cast<const char*>(buffer) + first_chunk_size,
170-
buffer_length - first_chunk_size) == 0);
170+
171+
return (std::memcmp(static_cast<const char*>(chunk_address_part2),
172+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
173+
static_cast<const char*>(buffer) + first_chunk_size, buffer_length - first_chunk_size) == 0);
171174
}
172175

173176
void Write(std::ostream& stream, const size_t end) const {
@@ -195,7 +198,7 @@ class MemoryMapManager final {
195198
size_t bytes_in_chunk = std::min(chunk_size_, remaining);
196199
TRACE("write chunk %d, with size: %ld, remaining: %ld", chunk, bytes_in_chunk, remaining);
197200

198-
const char* ptr = reinterpret_cast<const char*>(mappings_[chunk].region_->get_address());
201+
const char* ptr = static_cast<const char*>(mappings_[chunk].get_address());
199202
stream.write(ptr, bytes_in_chunk);
200203

201204
remaining -= bytes_in_chunk;
@@ -212,9 +215,7 @@ class MemoryMapManager final {
212215
void Persist() {
213216
persisted_ = true;
214217
for (auto& m : mappings_) {
215-
m.region_->flush();
216-
delete m.region_;
217-
delete m.mapping_;
218+
m.flush();
218219
}
219220

220221
// truncate last file according to the written buffers
@@ -236,13 +237,8 @@ class MemoryMapManager final {
236237
size_t GetNumberOfChunks() const { return number_of_chunks_; }
237238

238239
private:
239-
struct mapping {
240-
boost::interprocess::file_mapping* mapping_;
241-
boost::interprocess::mapped_region* region_;
242-
};
243-
244240
size_t chunk_size_;
245-
std::vector<mapping> mappings_;
241+
std::vector<boost::interprocess::mapped_region> mappings_;
246242
boost::filesystem::path directory_;
247243
boost::filesystem::path filename_pattern_;
248244
size_t tail_ = 0;
@@ -262,13 +258,11 @@ class MemoryMapManager final {
262258
CreateMapping();
263259
}
264260

265-
return mappings_[chunk_number].region_->get_address();
261+
return mappings_[chunk_number].get_address();
266262
}
267263

268264
void CreateMapping() {
269265
TRACE("create new mapping %d", number_of_chunks_ + 1);
270-
mapping new_mapping;
271-
272266
boost::filesystem::path filename = GetFilenameForChunk(number_of_chunks_);
273267

274268
std::ofstream chunk(filename.string().c_str(),
@@ -287,16 +281,15 @@ class MemoryMapManager final {
287281
throw memory_map_manager_exception("failed to create chunk (setting size)");
288282
}
289283

290-
new_mapping.mapping_ =
291-
new boost::interprocess::file_mapping(filename.string().c_str(), boost::interprocess::read_write);
284+
boost::interprocess::file_mapping const mapping(filename.string().c_str(), boost::interprocess::read_write);
292285

293-
new_mapping.region_ =
294-
new boost::interprocess::mapped_region(*new_mapping.mapping_, boost::interprocess::read_write);
286+
boost::interprocess::mapped_region mapped_region(
287+
boost::interprocess::mapped_region(mapping, boost::interprocess::read_write));
295288

296289
// prevent pre-fetching pages by the OS which does not make sense as values usually fit into few pages
297-
new_mapping.region_->advise(boost::interprocess::mapped_region::advice_types::advice_random);
290+
mapped_region.advise(boost::interprocess::mapped_region::advice_types::advice_random);
298291

299-
mappings_.push_back(new_mapping);
292+
mappings_.push_back(std::move(mapped_region));
300293
++number_of_chunks_;
301294
}
302295
};

0 commit comments

Comments
 (0)