]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/objectstore/FileStoreDiff.cc
update sources to 12.2.7
[ceph.git] / ceph / src / test / objectstore / FileStoreDiff.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) 2012 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <map>
16 #include <boost/scoped_ptr.hpp>
17 #include "common/debug.h"
18 #include "os/filestore/FileStore.h"
19 #include "common/config.h"
20
21 #include "FileStoreDiff.h"
22
23 #define dout_context g_ceph_context
24 #define dout_subsys ceph_subsys_filestore
25 #undef dout_prefix
26 #define dout_prefix *_dout << "filestore_diff "
27
28 FileStoreDiff::FileStoreDiff(FileStore *a, FileStore *b)
29 : a_store(a), b_store(b)
30 {
31 int err;
32 err = a_store->mount();
33 ceph_assert(err == 0);
34
35 err = b_store->mount();
36 ceph_assert(err == 0);
37 }
38
39 FileStoreDiff::~FileStoreDiff()
40 {
41 a_store->umount();
42 b_store->umount();
43 }
44
45
46 bool FileStoreDiff::diff_attrs(std::map<std::string,bufferptr>& b,
47 std::map<std::string,bufferptr>& a)
48 {
49 bool ret = false;
50 std::map<std::string, bufferptr>::iterator b_it = b.begin();
51 std::map<std::string, bufferptr>::iterator a_it = a.begin();
52 for (; b_it != b.end(); ++b_it, ++a_it) {
53 if (b_it->first != a_it->first) {
54 cout << "diff_attrs name mismatch (verify: " << b_it->first
55 << ", store: " << a_it->first << ")" << std::endl;
56 ret = true;
57 continue;
58 }
59
60 if (!b_it->second.cmp(a_it->second)) {
61 cout << "diff_attrs contents mismatch on attr " << b_it->first << std::endl;
62 ret = true;
63 continue;
64 }
65 }
66 return ret;
67 }
68
69 static bool diff_omap(std::map<std::string,bufferlist>& b,
70 std::map<std::string,bufferlist>& a)
71 {
72 bool ret = false;
73 std::map<std::string, bufferlist>::iterator b_it = b.begin();
74 std::map<std::string, bufferlist>::iterator a_it = a.begin();
75 for (; b_it != b.end(); ++b_it, ++a_it) {
76 if (a_it == a.end()) {
77 cout << __func__ << " a reached end before b, a missing " << b_it->first
78 << std::endl;
79 ret = true;
80 break;
81 }
82 if (b_it->first != a_it->first) {
83 cout << "diff_attrs name mismatch (verify: " << b_it->first
84 << ", store: " << a_it->first << ")" << std::endl;
85 ret = true;
86 continue;
87 }
88
89 if (!(b_it->second == a_it->second)) {
90 cout << "diff_attrs contents mismatch on attr " << b_it->first << std::endl;
91 ret = true;
92 continue;
93 }
94 }
95 return ret;
96 }
97
98 bool FileStoreDiff::diff_objects_stat(struct stat& a, struct stat& b)
99 {
100 bool ret = false;
101
102 if (a.st_uid != b.st_uid) {
103 cout << "diff_objects_stat uid mismatch (A: "
104 << a.st_uid << " != B: " << b.st_uid << ")" << std::endl;
105 ret = true;
106 }
107
108 if (a.st_gid != b.st_gid) {
109 cout << "diff_objects_stat gid mismatch (A: "
110 << a.st_gid << " != B: " << b.st_gid << ")" << std::endl;
111 ret = true;
112 }
113
114 if (a.st_mode != b.st_mode) {
115 cout << "diff_objects_stat mode mismatch (A: "
116 << a.st_mode << " != B: " << b.st_mode << ")" << std::endl;
117 ret = true;
118 }
119
120 if (a.st_nlink != b.st_nlink) {
121 cout << "diff_objects_stat nlink mismatch (A: "
122 << a.st_nlink << " != B: " << b.st_nlink << ")" << std::endl;
123 ret = true;
124 }
125
126 if (a.st_size != b.st_size) {
127 cout << "diff_objects_stat size mismatch (A: "
128 << a.st_size << " != B: " << b.st_size << ")" << std::endl;
129 ret = true;
130 }
131 return ret;
132 }
133
134 bool FileStoreDiff::diff_objects(FileStore *a_store, FileStore *b_store, coll_t coll)
135 {
136 bool ret = false;
137
138 int err;
139 std::vector<ghobject_t> b_objects, a_objects;
140 err = b_store->collection_list(coll, ghobject_t(), ghobject_t::get_max(),
141 INT_MAX, &b_objects, NULL);
142 if (err < 0) {
143 cout << "diff_objects list on verify coll " << coll.to_str()
144 << " returns " << err << std::endl;
145 return true;
146 }
147 err = a_store->collection_list(coll, ghobject_t(), ghobject_t::get_max(),
148 INT_MAX, &a_objects, NULL);
149 if (err < 0) {
150 cout << "diff_objects list on store coll " << coll.to_str()
151 << " returns " << err << std::endl;
152 return true;
153 }
154
155 if (b_objects.size() != a_objects.size()) {
156 cout << "diff_objects num objs mismatch (A: " << a_objects.size()
157 << ", B: " << b_objects.size() << ")" << std::endl;
158 ret = true;
159 }
160
161 std::vector<ghobject_t>::iterator b_it = b_objects.begin();
162 std::vector<ghobject_t>::iterator a_it = b_objects.begin();
163 for (; b_it != b_objects.end(); ++b_it, ++a_it) {
164 ghobject_t b_obj = *b_it, a_obj = *a_it;
165 if (b_obj.hobj.oid.name != a_obj.hobj.oid.name) {
166 cout << "diff_objects name mismatch on A object "
167 << coll << "/" << a_obj << " and B object "
168 << coll << "/" << b_obj << std::endl;
169 ret = true;
170 continue;
171 }
172
173 struct stat b_stat, a_stat;
174 err = b_store->stat(coll, b_obj, &b_stat);
175 if (err < 0) {
176 cout << "diff_objects error stating B object "
177 << coll.to_str() << "/" << b_obj.hobj.oid.name << std::endl;
178 ret = true;
179 }
180 err = a_store->stat(coll, a_obj, &a_stat);
181 if (err < 0) {
182 cout << "diff_objects error stating A object "
183 << coll << "/" << a_obj << std::endl;
184 ret = true;
185 }
186
187 if (diff_objects_stat(a_stat, b_stat)) {
188 cout << "diff_objects stat mismatch on "
189 << coll << "/" << b_obj << std::endl;
190 ret = true;
191 }
192
193 bufferlist a_obj_bl, b_obj_bl;
194 b_store->read(coll, b_obj, 0, b_stat.st_size, b_obj_bl);
195 a_store->read(coll, a_obj, 0, a_stat.st_size, a_obj_bl);
196
197 if (!a_obj_bl.contents_equal(b_obj_bl)) {
198 cout << "diff_objects content mismatch on "
199 << coll << "/" << b_obj << std::endl;
200 ret = true;
201 }
202
203 std::map<std::string, bufferptr> a_obj_attrs_map, b_obj_attrs_map;
204 err = a_store->getattrs(coll, a_obj, a_obj_attrs_map);
205 if (err < 0) {
206 cout << "diff_objects getattrs on A object " << coll << "/" << a_obj
207 << " returns " << err << std::endl;
208 ret = true;
209 }
210 err = b_store->getattrs(coll, b_obj, b_obj_attrs_map);
211 if (err < 0) {
212 cout << "diff_objects getattrs on B object " << coll << "/" << b_obj
213 << "returns " << err << std::endl;
214 ret = true;
215 }
216
217 if (diff_attrs(b_obj_attrs_map, a_obj_attrs_map)) {
218 cout << "diff_objects attrs mismatch on A object "
219 << coll << "/" << a_obj << " and B object "
220 << coll << "/" << b_obj << std::endl;
221 ret = true;
222 }
223
224 std::map<std::string, bufferlist> a_obj_omap, b_obj_omap;
225 std::set<std::string> a_omap_keys, b_omap_keys;
226 err = a_store->omap_get_keys(coll, a_obj, &a_omap_keys);
227 if (err < 0) {
228 cout << "diff_objects getomap on A object " << coll << "/" << a_obj
229 << " returns " << err << std::endl;
230 ret = true;
231 }
232 err = a_store->omap_get_values(coll, a_obj, a_omap_keys, &a_obj_omap);
233 if (err < 0) {
234 cout << "diff_objects getomap on A object " << coll << "/" << a_obj
235 << " returns " << err << std::endl;
236 ret = true;
237 }
238 err = b_store->omap_get_keys(coll, b_obj, &b_omap_keys);
239 if (err < 0) {
240 cout << "diff_objects getomap on A object " << coll << "/" << b_obj
241 << " returns " << err << std::endl;
242 ret = true;
243 }
244 err = b_store->omap_get_values(coll, b_obj, b_omap_keys, &b_obj_omap);
245 if (err < 0) {
246 cout << "diff_objects getomap on A object " << coll << "/" << b_obj
247 << " returns " << err << std::endl;
248 ret = true;
249 }
250 if (diff_omap(a_obj_omap, b_obj_omap)) {
251 cout << "diff_objects omap mismatch on A object "
252 << coll << "/" << a_obj << " and B object "
253 << coll << "/" << b_obj << std::endl;
254 cout << "a: " << a_obj_omap << std::endl;
255 cout << "b: " << b_obj_omap << std::endl;
256 ret = true;
257 }
258 }
259
260 return ret;
261 }
262
263 bool FileStoreDiff::diff()
264 {
265 bool ret = false;
266
267 std::vector<coll_t> a_coll_list, b_coll_list;
268 a_store->list_collections(a_coll_list);
269 b_store->list_collections(b_coll_list);
270
271 std::vector<coll_t>::iterator it = b_coll_list.begin();
272 for (; it != b_coll_list.end(); ++it) {
273 coll_t b_coll = *it;
274 if (!a_store->collection_exists(b_coll)) {
275 cout << "diff B coll " << b_coll.to_str() << " DNE on A" << std::endl;
276 ret = true;
277 continue;
278 }
279 for (std::vector<coll_t>::iterator j = a_coll_list.begin();
280 j != a_coll_list.end(); ++j) {
281 if (*j == *it) {
282 a_coll_list.erase(j);
283 break;
284 }
285 }
286
287 if (diff_objects(a_store, b_store, b_coll))
288 ret = true;
289 }
290 for (std::vector<coll_t>::iterator it = a_coll_list.begin();
291 it != a_coll_list.end(); ++it) {
292 cout << "diff A coll " << *it << " DNE on B" << std::endl;
293 ret = true;
294 }
295
296 return ret;
297 }