]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/objectstore/FileStoreDiff.cc
buildsys: change download over to reef release
[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 using namespace std;
29
30 FileStoreDiff::FileStoreDiff(FileStore *a, FileStore *b)
31 : a_store(a), b_store(b)
32 {
33 int err;
34 err = a_store->mount();
35 ceph_assert(err == 0);
36
37 err = b_store->mount();
38 ceph_assert(err == 0);
39 }
40
41 FileStoreDiff::~FileStoreDiff()
42 {
43 a_store->umount();
44 b_store->umount();
45 }
46
47
48 bool FileStoreDiff::diff_attrs(std::map<std::string,bufferptr,std::less<>>& b,
49 std::map<std::string,bufferptr,std::less<>>& a)
50 {
51 bool ret = false;
52 auto b_it = b.begin();
53 auto a_it = a.begin();
54 for (; b_it != b.end(); ++b_it, ++a_it) {
55 if (b_it->first != a_it->first) {
56 cout << "diff_attrs name mismatch (verify: " << b_it->first
57 << ", store: " << a_it->first << ")" << std::endl;
58 ret = true;
59 continue;
60 }
61
62 if (!b_it->second.cmp(a_it->second)) {
63 cout << "diff_attrs contents mismatch on attr " << b_it->first << std::endl;
64 ret = true;
65 continue;
66 }
67 }
68 return ret;
69 }
70
71 static bool diff_omap(std::map<std::string,bufferlist>& b,
72 std::map<std::string,bufferlist>& a)
73 {
74 bool ret = false;
75 std::map<std::string, bufferlist>::iterator b_it = b.begin();
76 std::map<std::string, bufferlist>::iterator a_it = a.begin();
77 for (; b_it != b.end(); ++b_it, ++a_it) {
78 if (a_it == a.end()) {
79 cout << __func__ << " a reached end before b, a missing " << b_it->first
80 << std::endl;
81 ret = true;
82 break;
83 }
84 if (b_it->first != a_it->first) {
85 cout << "diff_attrs name mismatch (verify: " << b_it->first
86 << ", store: " << a_it->first << ")" << std::endl;
87 ret = true;
88 continue;
89 }
90
91 if (!(b_it->second == a_it->second)) {
92 cout << "diff_attrs contents mismatch on attr " << b_it->first << std::endl;
93 ret = true;
94 continue;
95 }
96 }
97 return ret;
98 }
99
100 bool FileStoreDiff::diff_objects_stat(struct stat& a, struct stat& b)
101 {
102 bool ret = false;
103
104 if (a.st_uid != b.st_uid) {
105 cout << "diff_objects_stat uid mismatch (A: "
106 << a.st_uid << " != B: " << b.st_uid << ")" << std::endl;
107 ret = true;
108 }
109
110 if (a.st_gid != b.st_gid) {
111 cout << "diff_objects_stat gid mismatch (A: "
112 << a.st_gid << " != B: " << b.st_gid << ")" << std::endl;
113 ret = true;
114 }
115
116 if (a.st_mode != b.st_mode) {
117 cout << "diff_objects_stat mode mismatch (A: "
118 << a.st_mode << " != B: " << b.st_mode << ")" << std::endl;
119 ret = true;
120 }
121
122 if (a.st_nlink != b.st_nlink) {
123 cout << "diff_objects_stat nlink mismatch (A: "
124 << a.st_nlink << " != B: " << b.st_nlink << ")" << std::endl;
125 ret = true;
126 }
127
128 if (a.st_size != b.st_size) {
129 cout << "diff_objects_stat size mismatch (A: "
130 << a.st_size << " != B: " << b.st_size << ")" << std::endl;
131 ret = true;
132 }
133 return ret;
134 }
135
136 bool FileStoreDiff::diff_objects(FileStore *a_store, FileStore *b_store, coll_t coll)
137 {
138 bool ret = false;
139
140 int err;
141 std::vector<ghobject_t> b_objects, a_objects;
142 err = b_store->collection_list(coll, ghobject_t(), ghobject_t::get_max(),
143 INT_MAX, &b_objects, NULL);
144 if (err < 0) {
145 cout << "diff_objects list on verify coll " << coll.to_str()
146 << " returns " << err << std::endl;
147 return true;
148 }
149 err = a_store->collection_list(coll, ghobject_t(), ghobject_t::get_max(),
150 INT_MAX, &a_objects, NULL);
151 if (err < 0) {
152 cout << "diff_objects list on store coll " << coll.to_str()
153 << " returns " << err << std::endl;
154 return true;
155 }
156
157 if (b_objects.size() != a_objects.size()) {
158 cout << "diff_objects " << coll << " num objs mismatch (A: " << a_objects.size()
159 << ", B: " << b_objects.size() << ")" << std::endl;
160 ret = true;
161 cout << "a: " << a_objects << std::endl;
162 cout << "b: " << b_objects << std::endl;
163 }
164
165 auto a_ch = a_store->open_collection(coll);
166 auto b_ch = b_store->open_collection(coll);
167 std::vector<ghobject_t>::iterator b_it = b_objects.begin();
168 std::vector<ghobject_t>::iterator a_it = b_objects.begin();
169 for (; b_it != b_objects.end(); ++b_it, ++a_it) {
170 ghobject_t b_obj = *b_it, a_obj = *a_it;
171 if (b_obj.hobj.oid.name != a_obj.hobj.oid.name) {
172 cout << "diff_objects name mismatch on A object "
173 << coll << "/" << a_obj << " and B object "
174 << coll << "/" << b_obj << std::endl;
175 ret = true;
176 continue;
177 }
178
179 struct stat b_stat, a_stat;
180 err = b_store->stat(b_ch, b_obj, &b_stat);
181 if (err < 0) {
182 cout << "diff_objects error stating B object "
183 << coll.to_str() << "/" << b_obj.hobj.oid.name << std::endl;
184 ret = true;
185 }
186 err = a_store->stat(a_ch, a_obj, &a_stat);
187 if (err < 0) {
188 cout << "diff_objects error stating A object "
189 << coll << "/" << a_obj << std::endl;
190 ret = true;
191 }
192
193 if (diff_objects_stat(a_stat, b_stat)) {
194 cout << "diff_objects stat mismatch on "
195 << coll << "/" << b_obj << std::endl;
196 ret = true;
197 }
198
199 bufferlist a_obj_bl, b_obj_bl;
200 b_store->read(b_ch, b_obj, 0, b_stat.st_size, b_obj_bl);
201 a_store->read(a_ch, a_obj, 0, a_stat.st_size, a_obj_bl);
202
203 if (!a_obj_bl.contents_equal(b_obj_bl)) {
204 cout << "diff_objects content mismatch on "
205 << coll << "/" << b_obj << std::endl;
206 ret = true;
207 }
208
209 std::map<std::string, bufferptr, std::less<>> a_obj_attrs_map, b_obj_attrs_map;
210 err = a_store->getattrs(a_ch, a_obj, a_obj_attrs_map);
211 if (err < 0) {
212 cout << "diff_objects getattrs on A object " << coll << "/" << a_obj
213 << " returns " << err << std::endl;
214 ret = true;
215 }
216 err = b_store->getattrs(b_ch, b_obj, b_obj_attrs_map);
217 if (err < 0) {
218 cout << "diff_objects getattrs on B object " << coll << "/" << b_obj
219 << "returns " << err << std::endl;
220 ret = true;
221 }
222
223 if (diff_attrs(b_obj_attrs_map, a_obj_attrs_map)) {
224 cout << "diff_objects attrs mismatch on A object "
225 << coll << "/" << a_obj << " and B object "
226 << coll << "/" << b_obj << std::endl;
227 ret = true;
228 }
229
230 std::map<std::string, bufferlist> a_obj_omap, b_obj_omap;
231 std::set<std::string> a_omap_keys, b_omap_keys;
232 err = a_store->omap_get_keys(a_ch, a_obj, &a_omap_keys);
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 = a_store->omap_get_values(a_ch, a_obj, a_omap_keys, &a_obj_omap);
239 if (err < 0) {
240 cout << "diff_objects getomap on A object " << coll << "/" << a_obj
241 << " returns " << err << std::endl;
242 ret = true;
243 }
244 err = b_store->omap_get_keys(b_ch, b_obj, &b_omap_keys);
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 err = b_store->omap_get_values(b_ch, b_obj, b_omap_keys, &b_obj_omap);
251 if (err < 0) {
252 cout << "diff_objects getomap on A object " << coll << "/" << b_obj
253 << " returns " << err << std::endl;
254 ret = true;
255 }
256 if (diff_omap(a_obj_omap, b_obj_omap)) {
257 cout << "diff_objects omap mismatch on A object "
258 << coll << "/" << a_obj << " and B object "
259 << coll << "/" << b_obj << std::endl;
260 cout << "a: " << a_obj_omap << std::endl;
261 cout << "b: " << b_obj_omap << std::endl;
262 ret = true;
263 }
264 }
265
266 return ret;
267 }
268
269 bool FileStoreDiff::diff()
270 {
271 bool ret = false;
272
273 std::vector<coll_t> a_coll_list, b_coll_list;
274 a_store->list_collections(a_coll_list);
275 b_store->list_collections(b_coll_list);
276
277 std::vector<coll_t>::iterator it = b_coll_list.begin();
278 for (; it != b_coll_list.end(); ++it) {
279 coll_t b_coll = *it;
280 if (!a_store->collection_exists(b_coll)) {
281 cout << "diff B coll " << b_coll.to_str() << " DNE on A" << std::endl;
282 ret = true;
283 continue;
284 }
285 for (std::vector<coll_t>::iterator j = a_coll_list.begin();
286 j != a_coll_list.end(); ++j) {
287 if (*j == *it) {
288 a_coll_list.erase(j);
289 break;
290 }
291 }
292
293 if (diff_objects(a_store, b_store, b_coll))
294 ret = true;
295 }
296 for (std::vector<coll_t>::iterator it = a_coll_list.begin();
297 it != a_coll_list.end(); ++it) {
298 cout << "diff A coll " << *it << " DNE on B" << std::endl;
299 ret = true;
300 }
301
302 return ret;
303 }