/// responsibility to meet the restriction.
virtual void setNamedAddress(const char* name, void* addr) = 0;
virtual bool clearNamedAddress(const char* name) = 0;
+
+ virtual void shrinkToFit() = 0;
};
} // namespace util
virtual void setNamedAddress(const char* name, void* addr);
virtual bool clearNamedAddress(const char* name);
+ /// There's nothing this implementation can do for this.
+ virtual void shrinkToFit() {}
+
private:
// allocated_size_ can underflow, wrap around to max size_t (which
// is unsigned). But because we only do a check against 0 and not a
return (impl_->base_sgmt_->destroy<offset_ptr<void> >(name));
}
+void
+MemorySegmentMapped::shrinkToFit() {
+ // It appears an assertion failure is triggered within Boost if the size
+ // is too small. To work this around we'll make it no-op if the size is
+ // already reasonably small.
+ if (getSize() < INITIAL_SIZE) {
+ return;
+ }
+
+ impl_->base_sgmt_.reset();
+ managed_mapped_file::shrink_to_fit(impl_->filename_.c_str());
+ try {
+ // Remap the grown file; this should succeed, but it's not 100%
+ // guaranteed. If it fails we treat it as if we fail to create
+ // the new segment.
+ impl_->base_sgmt_.reset(
+ new managed_mapped_file(open_only, impl_->filename_.c_str()));
+ } catch (const boost::interprocess::interprocess_exception& ex) {
+ isc_throw(MemorySegmentError,
+ "remap after shrink failed; segment is now unusable");
+ }
+}
+
size_t
MemorySegmentMapped::getSize() const {
return (impl_->base_sgmt_->get_size());
virtual bool clearNamedAddress(const char* name);
+ virtual void shrinkToFit();
+
size_t getSize() const;
private:
~MemorySegmentMappedTest() {
segment_.reset();
- boost::interprocess::file_mapping::remove(mapped_file);
+ //boost::interprocess::file_mapping::remove(mapped_file);
}
// For initialization and for tests after the segment possibly becomes
EXPECT_TRUE(segment_->allMemoryDeallocated());
}
+TEST_F(MemorySegmentMappedTest, shrink) {
+ segment_->shrinkToFit();
+ // Normally we should be able to expect the resulting size is the smaller
+ // than the initial default size. It's not really guaranteed by the API,
+ // however, so we may have to disable this check.
+ const size_t shrinked_size = segment_->getSize();
+ EXPECT_GT(DEFAULT_INITIAL_SIZE, shrinked_size);
+
+ // Another shrink shouldn't cause disruption, and the size shouldn't change
+ segment_->shrinkToFit();
+ EXPECT_EQ(shrinked_size, segment_->getSize());
+
+ // Check the segment is still usable after shrink.
+ void* p = segment_->allocate(sizeof(uint32_t));
+ segment_->deallocate(p, sizeof(uint32_t));
+}
+
}