]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/mon/PGMap.cc
60de6b7ddae91d146682e9e252b59ba8ba40c9a2
[ceph.git] / ceph / src / test / mon / PGMap.cc
1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2014 Inktank <info@inktank.com>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License version 2, as published by the Free Software
11 * Foundation. See file COPYING.
12 */
13
14 #include "mon/PGMap.h"
15 #include "gtest/gtest.h"
16
17 #include "include/stringify.h"
18
19 TEST(pgmap, min_last_epoch_clean)
20 {
21 PGMap pg_map;
22 PGMap::Incremental inc;
23 osd_stat_t os;
24 pg_stat_t ps;
25
26 ps.last_epoch_clean = 999;
27 inc.pg_stat_updates[pg_t(9,9)] = ps;
28 inc.version = 1;
29 inc.update_stat(0, 123, os);
30 pg_map.apply_incremental(g_ceph_context, inc);
31 ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
32
33 inc = PGMap::Incremental();
34 inc.version = 2;
35 inc.update_stat(1, 222, os);
36 pg_map.apply_incremental(g_ceph_context, inc);
37 ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
38
39 inc = PGMap::Incremental();
40 inc.version = 3;
41 inc.update_stat(0, 222, os);
42 pg_map.apply_incremental(g_ceph_context, inc);
43 ASSERT_EQ(222u, pg_map.get_min_last_epoch_clean());
44
45 inc = PGMap::Incremental();
46 inc.version = 4;
47 inc.update_stat(0, 333, os);
48 inc.update_stat(1, 333, os);
49 pg_map.apply_incremental(g_ceph_context, inc);
50 ASSERT_EQ(333u, pg_map.get_min_last_epoch_clean());
51
52 ps.last_epoch_clean = 222;
53 inc = PGMap::Incremental();
54 inc.version = 5;
55 inc.pg_stat_updates[pg_t(1,1)] = ps;
56 pg_map.apply_incremental(g_ceph_context, inc);
57 ASSERT_EQ(222u, pg_map.get_min_last_epoch_clean());
58
59 ps.last_epoch_clean = 223;
60 inc = PGMap::Incremental();
61 inc.version = 6;
62 inc.pg_stat_updates[pg_t(1,1)] = ps;
63 pg_map.apply_incremental(g_ceph_context, inc);
64 ASSERT_EQ(223u, pg_map.get_min_last_epoch_clean());
65
66 ps.last_epoch_clean = 224;
67 inc = PGMap::Incremental();
68 inc.version = 7;
69 inc.pg_stat_updates[pg_t(2,2)] = ps;
70 pg_map.apply_incremental(g_ceph_context, inc);
71 ASSERT_EQ(223u, pg_map.get_min_last_epoch_clean());
72
73 ps.last_epoch_clean = 225;
74 inc = PGMap::Incremental();
75 inc.version = 8;
76 inc.pg_stat_updates[pg_t(1,1)] = ps;
77 pg_map.apply_incremental(g_ceph_context, inc);
78 ASSERT_EQ(224u, pg_map.get_min_last_epoch_clean());
79
80 }
81
82 TEST(pgmap, calc_stats)
83 {
84 bufferlist bl;
85 {
86 PGMap pg_map;
87 PGMap::Incremental inc;
88 osd_stat_t os;
89 pg_stat_t ps;
90
91 ps.last_epoch_clean = 999;
92 inc.pg_stat_updates[pg_t(9,9)] = ps;
93 inc.version = 1;
94 inc.update_stat(0, 123, os);
95 pg_map.apply_incremental(g_ceph_context, inc);
96 ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
97 pg_map.encode(bl);
98 }
99 {
100 PGMap pg_map;
101 PGMap::Incremental inc;
102 osd_stat_t os;
103 pg_stat_t ps;
104
105 ps.last_epoch_clean = 999;
106 inc.pg_stat_updates[pg_t(9,9)] = ps;
107 inc.version = 1;
108 inc.update_stat(0, 321, os);
109 pg_map.apply_incremental(g_ceph_context, inc);
110 ASSERT_EQ(321u, pg_map.get_min_last_epoch_clean());
111 bufferlist::iterator p = bl.begin();
112 ::decode(pg_map, p);
113 ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
114 }
115 }
116
117 namespace {
118 class CheckTextTable : public TextTable {
119 public:
120 CheckTextTable(bool verbose) {
121 for (int i = 0; i < 4; i++) {
122 define_column("", TextTable::LEFT, TextTable::LEFT);
123 }
124 if (verbose) {
125 for (int i = 0; i < 4; i++) {
126 define_column("", TextTable::LEFT, TextTable::LEFT);
127 }
128 }
129 }
130 const string& get(unsigned r, unsigned c) const {
131 assert(r < row.size());
132 assert(c < row[r].size());
133 return row[r][c];
134 }
135 };
136
137 // copied from PGMap.cc
138 string percentify(float a) {
139 stringstream ss;
140 if (a < 0.01)
141 ss << "0";
142 else
143 ss << std::fixed << std::setprecision(2) << a;
144 return ss.str();
145 }
146 }
147
148 // dump_object_stat_sum() is called by "ceph df" command
149 // with table, without formatter, verbose = true, not empty, avail > 0
150 TEST(pgmap, dump_object_stat_sum_0)
151 {
152 bool verbose = true;
153 CheckTextTable tbl(verbose);
154 object_stat_sum_t sum;
155 sum.num_bytes = 42 * 1024 * 1024;
156 sum.num_objects = 42;
157 sum.num_objects_degraded = 13; // there are 13 missings + not_yet_backfilled
158 sum.num_objects_dirty = 2;
159 sum.num_rd = 100;
160 sum.num_rd_kb = 123;
161 sum.num_wr = 101;
162 sum.num_wr_kb = 321;
163
164 sum.calc_copies(3); // assuming we have 3 copies for each obj
165 // nominal amount of space available for new objects in this pool
166 uint64_t avail = 2016 * 1024 * 1024;
167 pg_pool_t pool;
168 pool.quota_max_objects = 2000;
169 pool.quota_max_bytes = 2000 * 1024 * 1024;
170 pool.size = 2;
171 pool.type = pg_pool_t::TYPE_REPLICATED;
172 PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail,
173 pool.get_size(), verbose, &pool);
174 ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, 0));
175 float copies_rate =
176 (static_cast<float>(sum.num_object_copies - sum.num_objects_degraded) /
177 sum.num_object_copies);
178 float used_bytes = sum.num_bytes * copies_rate;
179 float used_percent = used_bytes / (used_bytes + avail) * 100;
180 unsigned col = 0;
181 ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, col++));
182 ASSERT_EQ(percentify(used_percent), tbl.get(0, col++));
183 ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++));
184 ASSERT_EQ(stringify(sum.num_objects), tbl.get(0, col++));
185 ASSERT_EQ(stringify(si_t(sum.num_objects_dirty)), tbl.get(0, col++));
186 ASSERT_EQ(stringify(si_t(sum.num_rd)), tbl.get(0, col++));
187 ASSERT_EQ(stringify(si_t(sum.num_wr)), tbl.get(0, col++));
188 // we can use pool.size for raw_used_rate if it is a replica pool
189 uint64_t raw_bytes_used = sum.num_bytes * pool.get_size() * copies_rate;
190 ASSERT_EQ(stringify(si_t(raw_bytes_used)), tbl.get(0, col++));
191 }
192
193 // with table, without formatter, verbose = true, empty, avail > 0
194 TEST(pgmap, dump_object_stat_sum_1)
195 {
196 bool verbose = true;
197 CheckTextTable tbl(verbose);
198 object_stat_sum_t sum; // zero by default
199 ASSERT_TRUE(sum.is_zero());
200 // nominal amount of space available for new objects in this pool
201 uint64_t avail = 2016 * 1024 * 1024;
202 pg_pool_t pool;
203 pool.quota_max_objects = 2000;
204 pool.quota_max_bytes = 2000 * 1024 * 1024;
205 pool.size = 2;
206 pool.type = pg_pool_t::TYPE_REPLICATED;
207 PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail,
208 pool.get_size(), verbose, &pool);
209 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0));
210 unsigned col = 0;
211 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
212 ASSERT_EQ(percentify(0), tbl.get(0, col++));
213 ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++));
214 ASSERT_EQ(stringify(0), tbl.get(0, col++));
215 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
216 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
217 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
218 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
219 }
220
221 // with table, without formatter, verbose = false, empty, avail = 0
222 TEST(pgmap, dump_object_stat_sum_2)
223 {
224 bool verbose = false;
225 CheckTextTable tbl(verbose);
226 object_stat_sum_t sum; // zero by default
227 ASSERT_TRUE(sum.is_zero());
228 // nominal amount of space available for new objects in this pool
229 uint64_t avail = 0;
230 pg_pool_t pool;
231 pool.quota_max_objects = 2000;
232 pool.quota_max_bytes = 2000 * 1024 * 1024;
233 pool.size = 2;
234 pool.type = pg_pool_t::TYPE_REPLICATED;
235
236 PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail,
237 pool.get_size(), verbose, &pool);
238 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0));
239 unsigned col = 0;
240 ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
241 ASSERT_EQ(percentify(0), tbl.get(0, col++));
242 ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++));
243 ASSERT_EQ(stringify(0), tbl.get(0, col++));
244 }