wait_for_clean || return 1
sleep $WAIT_FOR_UPDATE
local objects_trimmed=0
+ local snaptrim_duration_total=0.0
for i in $(seq 0 $(expr $PGNUM - 1))
do
local pgid="${poolid}.${i}"
objects_trimmed=$(expr $objects_trimmed + $(ceph pg $pgid query | \
jq '.info.stats.objects_trimmed'))
+ snaptrim_duration_total=`echo $snaptrim_duration_total + $(ceph pg \
+ $pgid query | jq '.info.stats.snaptrim_duration') | bc`
done
-
test $objects_trimmed -eq $objects || return 1
+ echo "$snaptrim_duration_total > 0.0" | bc || return 1
teardown $dir || return 1
}
+function TEST_snaptrim_stats_multiple_snaps() {
+ local dir=$1
+ local poolname=test
+ local OSDS=3
+ local PGNUM=8
+ local PGPNUM=8
+ local objects=10
+ local WAIT_FOR_UPDATE=10
+
+ setup $dir || return 1
+ run_mon $dir a --osd_pool_default_size=$OSDS || return 1
+ run_mgr $dir x || return 1
+ for osd in $(seq 0 $(expr $OSDS - 1))
+ do
+ run_osd $dir $osd --osd_pool_default_pg_autoscale_mode=off || return 1
+ done
+
+ # disable scrubs
+ ceph osd set noscrub || return 1
+ ceph osd set nodeep-scrub || return 1
+
+ # Create a pool
+ create_pool $poolname $PGNUM $PGPNUM
+ wait_for_clean || return 1
+ poolid=$(ceph osd dump | grep "^pool.*[']${poolname}[']" | awk '{ print $2 }')
+
+ # write a few objects
+ local TESTDATA="testdata.0"
+ dd if=/dev/urandom of=$TESTDATA bs=4096 count=1
+ for i in `seq 1 $objects`
+ do
+ rados -p $poolname put obj${i} $TESTDATA
+ done
+ rm -f $TESTDATA
+
+ # create snapshots, clones
+ NUMSNAPS=2
+ for i in `seq 1 $NUMSNAPS`
+ do
+ rados -p $poolname mksnap snap${i}
+ TESTDATA="testdata".${i}
+ dd if=/dev/urandom of=$TESTDATA bs=4096 count=1
+ for i in `seq 1 $objects`
+ do
+ rados -p $poolname put obj${i} $TESTDATA
+ done
+ rm -f $TESTDATA
+ done
+
+ # remove the snapshots, should trigger snaptrim
+ local total_objects_trimmed=0
+ for i in `seq 1 $NUMSNAPS`
+ do
+ rados -p $poolname rmsnap snap${i}
+
+ # check for snaptrim stats
+ wait_for_clean || return 1
+ sleep $WAIT_FOR_UPDATE
+ local objects_trimmed=0
+ local snaptrim_duration_total=0.0
+ for i in $(seq 0 $(expr $PGNUM - 1))
+ do
+ local pgid="${poolid}.${i}"
+ objects_trimmed=$(expr $objects_trimmed + $(ceph pg $pgid query | \
+ jq '.info.stats.objects_trimmed'))
+ snaptrim_duration_total=`echo $snaptrim_duration_total + $(ceph pg \
+ $pgid query | jq '.info.stats.snaptrim_duration') | bc`
+ done
+ test $objects_trimmed -eq $objects || return 1
+ echo "$snaptrim_duration_total > 0.0" | bc || return 1
+ total_objects_trimmed=$(expr $total_objects_trimmed + $objects_trimmed)
+ done
+
+ test $total_objects_trimmed -eq $((objects * NUMSNAPS)) || return 1
+
+ teardown $dir || return 1
+}
main test-snaptrim-stats "$@"
# Local Variables:
});
}
+ utime_t snaptrim_begin_stamp;
+
+ void set_snaptrim_begin_stamp() {
+ snaptrim_begin_stamp = ceph_clock_now();
+ }
+
+ void set_snaptrim_duration() {
+ utime_t cur_stamp = ceph_clock_now();
+ utime_t duration = cur_stamp - snaptrim_begin_stamp;
+ recovery_state.update_stats_wo_resched(
+ [=](auto &history, auto &stats) {
+ stats.snaptrim_duration = double(duration);
+ });
+ }
+
unsigned get_target_pg_log_entries() const override;
void clear_publish_stats() override;
info.stats.stats_invalid = true;
child->info.stats.stats_invalid = true;
child->info.stats.objects_trimmed = 0;
+ child->info.stats.snaptrim_duration = 0.0;
child->info.last_epoch_started = info.last_epoch_started;
child->info.last_interval_started = info.last_interval_started;
} else {
dout(10) << __func__ << ": clean and snaps to trim, kicking" << dendl;
reset_objects_trimmed();
+ set_snaptrim_begin_stamp();
snap_trimmer_machine.process_event(KickTrim());
}
}
pg->recovery_state.share_pg_info();
}
post_event(KickTrim());
+ pg->set_snaptrim_duration();
return transit< NotTrimming >();
}
ceph_assert(!to_trim.empty());
f->dump_string("scrub_schedule", dump_scrub_schedule());
f->dump_float("scrub_duration", scrub_duration);
f->dump_int("objects_trimmed", objects_trimmed);
+ f->dump_float("snaptrim_duration", snaptrim_duration);
stats.dump(f);
f->open_array_section("up");
for (auto p = up.cbegin(); p != up.cend(); ++p)
encode(objects_scrubbed, bl);
encode(scrub_duration, bl);
encode(objects_trimmed, bl);
+ encode(snaptrim_duration, bl);
ENCODE_FINISH(bl);
}
}
if (struct_v >= 28) {
decode(objects_trimmed, bl);
+ decode(snaptrim_duration, bl);
}
}
DECODE_FINISH(bl);
a.snaptrimq_len = 1048576;
a.objects_scrubbed = 0;
a.objects_trimmed = 0;
+ a.snaptrim_duration = 0.123;
list<object_stat_collection_t*> l;
object_stat_collection_t::generate_test_instances(l);
a.stats = *l.back();
l.scrub_sched_status == r.scrub_sched_status &&
l.objects_scrubbed == r.objects_scrubbed &&
l.scrub_duration == r.scrub_duration &&
- l.objects_trimmed == r.objects_trimmed;
+ l.objects_trimmed == r.objects_trimmed &&
+ l.snaptrim_duration == r.snaptrim_duration;
}
// -- store_statfs_t --
// absurd already, so cap it to 2^32 and save 4 bytes at the same time
uint32_t snaptrimq_len;
int64_t objects_trimmed;
+ double snaptrim_duration;
pg_scrubbing_status_t scrub_sched_status;
acting_primary(-1),
snaptrimq_len(0),
objects_trimmed(0),
+ snaptrim_duration(0.0),
stats_invalid(false),
dirty_stats_invalid(false),
omap_stats_invalid(false),
}
};
-int get_objects_trimmed(json_spirit::Object& pg_dump) {
- int objs_trimmed = 0;
-
+void get_snaptrim_stats(json_spirit::Object& pg_dump,
+ int *objs_trimmed,
+ double *trim_duration) {
// pg_map
json_spirit::Object pgmap;
for (json_spirit::Object::size_type i = 0; i < pg_dump.size(); ++i) {
for(json_spirit::Object::size_type k = 0; k < pg_stat.size(); ++k) {
json_spirit::Pair& stats = pg_stat[k];
if (stats.name_ == "objects_trimmed") {
- objs_trimmed += stats.value_.get_int();
- break;
+ *objs_trimmed += stats.value_.get_int();
+ }
+ if (stats.name_ == "snaptrim_duration") {
+ *trim_duration += stats.value_.get_real();
}
}
}
-
- return objs_trimmed;
}
const int bufsize = 128;
// Dump pg stats and determine if snaptrim stats are getting set
int objects_trimmed = 0;
+ double snaptrim_duration = 0.0;
int tries = 0;
do {
char *buf, *st;
// pg dump object
json_spirit::Object& obj = v.get_obj();
- objects_trimmed = get_objects_trimmed(obj);
+ get_snaptrim_stats(obj, &objects_trimmed, &snaptrim_duration);
if (objects_trimmed < num_objs) {
tries++;
objects_trimmed = 0;
// final check for objects trimmed
ASSERT_EQ(objects_trimmed, num_objs);
+ std::cout << "Snaptrim duration: " << snaptrim_duration << std::endl;
+ ASSERT_GT(snaptrim_duration, 0.0);
// clean-up remaining objects
for (int i = 0; i < num_objs; ++i) {
// Dump pg stats and determine if snaptrim stats are getting set
int objects_trimmed = 0;
+ double snaptrim_duration = 0.0;
int tries = 0;
do {
char *buf, *st;
// pg dump object
json_spirit::Object& obj = v.get_obj();
- objects_trimmed = get_objects_trimmed(obj);
+ get_snaptrim_stats(obj, &objects_trimmed, &snaptrim_duration);
if (objects_trimmed != num_objs) {
tries++;
objects_trimmed = 0;
// final check for objects trimmed
ASSERT_EQ(objects_trimmed, num_objs);
+ std::cout << "Snaptrim duration: " << snaptrim_duration << std::endl;
+ ASSERT_GT(snaptrim_duration, 0.0);
// clean-up remaining objects
for (int i = 0; i < num_objs; ++i) {
}
};
-int get_objects_trimmed(json_spirit::Object& pg_dump) {
- int objs_trimmed = 0;
-
+void get_snaptrim_stats(json_spirit::Object& pg_dump,
+ int *objs_trimmed,
+ double *trim_duration) {
// pg_map
json_spirit::Object pgmap;
for (json_spirit::Object::size_type i = 0; i < pg_dump.size(); ++i) {
for(json_spirit::Object::size_type k = 0; k < pg_stat.size(); ++k) {
json_spirit::Pair& stats = pg_stat[k];
if (stats.name_ == "objects_trimmed") {
- objs_trimmed += stats.value_.get_int();
- break;
+ *objs_trimmed += stats.value_.get_int();
+ }
+ if (stats.name_ == "snaptrim_duration") {
+ *trim_duration += stats.value_.get_real();
}
}
}
-
- return objs_trimmed;
}
const int bufsize = 128;
// Dump pg stats and determine if snaptrim stats are getting set
int objects_trimmed = 0;
+ double snaptrim_duration = 0.0;
int tries = 0;
do {
string cmd = string("{\"prefix\": \"pg dump\",\"format\":\"json\"}");
// pg_map
json_spirit::Object& obj = v.get_obj();
- objects_trimmed = get_objects_trimmed(obj);
+ get_snaptrim_stats(obj, &objects_trimmed, &snaptrim_duration);
if (objects_trimmed < num_objs) {
tries++;
objects_trimmed = 0;
// final check for objects trimmed
ASSERT_EQ(objects_trimmed, num_objs);
+ std::cout << "Snaptrim duration: " << snaptrim_duration << std::endl;
+ ASSERT_GT(snaptrim_duration, 0.0);
// clean-up remaining objects
ioctx.snap_set_read(librados::SNAP_HEAD);
// Dump pg stats and determine if snaptrim stats are getting set
int objects_trimmed = 0;
+ double snaptrim_duration = 0.0;
int tries = 0;
do {
string cmd = string("{\"prefix\": \"pg dump\",\"format\":\"json\"}");
// pg_map
json_spirit::Object& obj = v.get_obj();
- objects_trimmed = get_objects_trimmed(obj);
+ get_snaptrim_stats(obj, &objects_trimmed, &snaptrim_duration);
if (objects_trimmed < num_objs) {
tries++;
objects_trimmed = 0;
// final check for objects trimmed
ASSERT_EQ(objects_trimmed, num_objs);
+ std::cout << "Snaptrim duration: " << snaptrim_duration << std::endl;
+ ASSERT_GT(snaptrim_duration, 0.0);
// clean-up remaining objects
ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);