DECODE_FINISH(_bl);
}
+void ObjectCleanRegions::trim()
+{
+ while(clean_offsets.num_intervals() > max_num_intervals) {
+ typename interval_set<uint64_t>::iterator shortest_interval = clean_offsets.begin();
+ if (shortest_interval == clean_offsets.end())
+ break;
+ for (typename interval_set<uint64_t>::iterator it = clean_offsets.begin();
+ it != clean_offsets.end();
+ ++it) {
+ if (it.get_len() < shortest_interval.get_len())
+ shortest_interval = it;
+ }
+ clean_offsets.erase(shortest_interval);
+ }
+}
+
+void ObjectCleanRegions::merge(const ObjectCleanRegions &other)
+{
+ clean_offsets.intersection_of(other.clean_offsets);
+ clean_omap = clean_omap && other.clean_omap;
+ trim();
+}
+
+void ObjectCleanRegions::mark_data_region_dirty(uint64_t offset, uint64_t len)
+{
+ interval_set<uint64_t> clean_region;
+ clean_region.insert(0, (uint64_t)-1);
+ clean_region.erase(offset, len);
+ clean_offsets.intersection_of(clean_region);
+ trim();
+}
+
+void ObjectCleanRegions::mark_omap_dirty()
+{
+ clean_omap = false;
+}
+
+void ObjectCleanRegions::mark_object_new()
+{
+ new_object = true;
+}
+
+void ObjectCleanRegions::mark_fully_dirty()
+{
+ mark_data_region_dirty(0, (uint64_t)-1);
+ mark_omap_dirty();
+ mark_object_new();
+}
+
+interval_set<uint64_t> ObjectCleanRegions::get_dirty_regions() const
+{
+ interval_set<uint64_t> dirty_region;
+ dirty_region.insert(0, (uint64_t)-1);
+ dirty_region.subtract(clean_offsets);
+ return dirty_region;
+}
+
+bool ObjectCleanRegions::omap_is_dirty() const
+{
+ return !clean_omap;
+}
+
+bool ObjectCleanRegions::object_is_exist() const
+{
+ return !new_object;
+}
+
+void ObjectCleanRegions::encode(bufferlist &bl) const
+{
+ ENCODE_START(1, 1, bl);
+ using ceph::encode;
+ encode(clean_offsets, bl);
+ encode(clean_omap, bl);
+ encode(new_object, bl);
+ ENCODE_FINISH(bl);
+}
+
+void ObjectCleanRegions::decode(bufferlist::const_iterator &bl)
+{
+ DECODE_START(1, bl);
+ using ceph::decode;
+ decode(clean_offsets, bl);
+ decode(clean_omap, bl);
+ decode(new_object, bl);
+ DECODE_FINISH(bl);
+}
+
+void ObjectCleanRegions::dump(Formatter *f) const
+{
+ f->open_object_section("object_clean_regions");
+ f->dump_stream("clean_offsets") << clean_offsets;
+ f->dump_bool("clean_omap", clean_omap);
+ f->dump_bool("object_new", new_object);
+ f->close_section();
+}
+
+void ObjectCleanRegions::generate_test_instances(list<ObjectCleanRegions*>& o)
+{
+ o.push_back(new ObjectCleanRegions());
+ o.push_back(new ObjectCleanRegions());
+ o.back()->mark_data_region_dirty(4096, 40960);
+ o.back()->mark_omap_dirty();
+ o.back()->mark_object_new();
+}
+
+ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr)
+{
+ return out << "clean_offsets: " << ocr.clean_offsets
+ << ", clean_omap: " << ocr.clean_omap
+ << ", object_new: " << ocr.new_object;
+}
+
// -- pg_log_entry_t --
string pg_log_entry_t::get_key_name() const
/// priority when more full
#define OSD_DELETE_PRIORITY_FULL 255
+/// max intervals for clean_offsets in ObjectCleanRegions
+#define OSD_CLEAN_OFFSETS_MAX_INTERVALS 10
static std::map<int, int> max_prio_map = {
{OSD_BACKFILL_PRIORITY_BASE, OSD_BACKFILL_DEGRADED_PRIORITY_BASE - 1},
{OSD_BACKFILL_DEGRADED_PRIORITY_BASE, OSD_RECOVERY_PRIORITY_BASE - 1},
};
WRITE_CLASS_ENCODER(ObjectModDesc)
+class ObjectCleanRegions {
+private:
+ interval_set<uint64_t> clean_offsets;
+ bool clean_omap;
+ bool new_object;
+ int32_t max_num_intervals;
+
+ /**
+ * trim the number of intervals if clean_offsets.num_intervals()
+ * exceeds the given upbound max_num_intervals
+ * etc. max_num_intervals=2, clean_offsets:{[5~10], [20~5]}
+ * then new interval [30~10] will evict out the shortest one [20~5]
+ * finally, clean_offsets becomes {[5~10], [30~10]}
+ */
+ void trim();
+ friend ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr);
+public:
+ ObjectCleanRegions(int32_t max = OSD_CLEAN_OFFSETS_MAX_INTERVALS) : new_object(false), max_num_intervals(max) {
+ clean_offsets.insert(0, (uint64_t)-1);
+ clean_omap = true;
+ }
+ ObjectCleanRegions(uint64_t offset, uint64_t len, bool co, int32_t max = OSD_CLEAN_OFFSETS_MAX_INTERVALS)
+ : clean_omap(co), new_object(false), max_num_intervals(max) {
+ clean_offsets.insert(offset, len);
+ }
+ bool operator==(const ObjectCleanRegions &orc) const {
+ return clean_offsets == orc.clean_offsets && clean_omap == orc.clean_omap && max_num_intervals == orc.max_num_intervals;
+ }
+
+ void merge(const ObjectCleanRegions &other);
+ void mark_data_region_dirty(uint64_t offset, uint64_t len);
+ void mark_omap_dirty();
+ void mark_object_new();
+ void mark_fully_dirty();
+ interval_set<uint64_t> get_dirty_regions() const;
+ bool omap_is_dirty() const;
+ bool object_is_exist() const;
+
+ void encode(bufferlist &bl) const;
+ void decode(bufferlist::const_iterator &bl);
+ void dump(Formatter *f) const;
+ static void generate_test_instances(list<ObjectCleanRegions*>& o);
+};
+WRITE_CLASS_ENCODER(ObjectCleanRegions)
+ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr);
/**
* pg_log_entry_t - single entry/event in pg log