summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@broadpark.no>2021-03-04 10:58:11 +0100
committerTor Egge <Tor.Egge@broadpark.no>2021-03-04 11:06:03 +0100
commit4a33bf931364094528f30775e1b3f5e1df372fc8 (patch)
treed41ea8d328653bb5e373963a53666d3df2e62bbb /vespalib
parenta815447f4de43fd276aa20609d1727d0fe365220 (diff)
Factor out prepare_reuse_area to separate member function.
Add comments for _free_areas and _free_sizes.
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/vespa/vespalib/util/file_area_freelist.cpp30
-rw-r--r--vespalib/src/vespa/vespalib/util/file_area_freelist.h5
2 files changed, 25 insertions, 10 deletions
diff --git a/vespalib/src/vespa/vespalib/util/file_area_freelist.cpp b/vespalib/src/vespa/vespalib/util/file_area_freelist.cpp
index ac6c2263112..5edebcac1ad 100644
--- a/vespalib/src/vespa/vespalib/util/file_area_freelist.cpp
+++ b/vespalib/src/vespa/vespalib/util/file_area_freelist.cpp
@@ -26,27 +26,41 @@ FileAreaFreeList::remove_from_size_set(uint64_t offset, size_t size)
}
}
-uint64_t
-FileAreaFreeList::alloc(size_t size)
+std::pair<uint64_t, size_t>
+FileAreaFreeList::prepare_reuse_area(size_t size)
{
- auto sitr = _free_sizes.lower_bound(size);
- if (sitr == _free_sizes.end()) {
- return bad_offset; // No free areas of sufficient size
+ auto itr = _free_sizes.lower_bound(size);
+ if (itr == _free_sizes.end()) {
+ return std::make_pair(bad_offset, 0); // No free areas of sufficient size
}
- auto old_size = sitr->first;
+ auto old_size = itr->first;
assert(old_size >= size);
- auto &offsets = sitr->second;
+ auto &offsets = itr->second;
assert(!offsets.empty());
auto oitr = offsets.begin();
auto offset = *oitr;
offsets.erase(oitr);
if (offsets.empty()) {
- _free_sizes.erase(sitr);
+ _free_sizes.erase(itr);
+ }
+ // Note: Caller must update _free_areas
+ return std::make_pair(offset, old_size);
+}
+
+uint64_t
+FileAreaFreeList::alloc(size_t size)
+{
+ auto reuse_candidate = prepare_reuse_area(size);
+ auto offset = reuse_candidate.first;
+ if (offset == bad_offset) {
+ return bad_offset; // No free areas of sufficient size
}
auto fa_itr = _free_areas.find(offset);
assert(fa_itr != _free_areas.end());
fa_itr = _free_areas.erase(fa_itr);
+ auto old_size = reuse_candidate.second;
if (old_size > size) {
+ // Old area beyond what we reuse should still be a free area.
auto ins_res = _free_sizes[old_size - size].insert(offset + size);
assert(ins_res.second);
_free_areas.emplace_hint(fa_itr, offset + size, old_size - size);
diff --git a/vespalib/src/vespa/vespalib/util/file_area_freelist.h b/vespalib/src/vespa/vespalib/util/file_area_freelist.h
index 8b245084585..ad56f516d26 100644
--- a/vespalib/src/vespa/vespalib/util/file_area_freelist.h
+++ b/vespalib/src/vespa/vespalib/util/file_area_freelist.h
@@ -13,9 +13,10 @@ namespace vespalib::alloc {
* Class that tracks free areas in a file.
*/
class FileAreaFreeList {
- std::map<uint64_t, size_t> _free_areas;
- std::map<size_t, std::set<uint64_t>> _free_sizes;
+ std::map<uint64_t, size_t> _free_areas; // map from offset to size
+ std::map<size_t, std::set<uint64_t>> _free_sizes; // map from size to set of offsets
void remove_from_size_set(uint64_t offset, size_t size);
+ std::pair<uint64_t, size_t> prepare_reuse_area(size_t size);
public:
FileAreaFreeList();
~FileAreaFreeList();