1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2012 New Dream Network
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.
16 #include <boost/scoped_ptr.hpp>
17 #include "common/debug.h"
18 #include "os/filestore/FileStore.h"
19 #include "common/config.h"
21 #include "FileStoreDiff.h"
23 #define dout_context g_ceph_context
24 #define dout_subsys ceph_subsys_filestore
26 #define dout_prefix *_dout << "filestore_diff "
28 FileStoreDiff::FileStoreDiff(FileStore *a, FileStore *b)
29 : a_store(a), b_store(b)
32 err = a_store->mount();
33 ceph_assert(err == 0);
35 err = b_store->mount();
36 ceph_assert(err == 0);
39 FileStoreDiff::~FileStoreDiff()
46 bool FileStoreDiff::diff_attrs(std::map<std::string,bufferptr>& b,
47 std::map<std::string,bufferptr>& a)
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 dout(0) << "diff_attrs name mismatch (verify: " << b_it->first
55 << ", store: " << a_it->first << ")" << dendl;
60 if (!b_it->second.cmp(a_it->second)) {
61 dout(0) << "diff_attrs contents mismatch on attr " << b_it->first << dendl;
69 static bool diff_omap(std::map<std::string,bufferlist>& b,
70 std::map<std::string,bufferlist>& a)
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 (b_it->first != a_it->first) {
77 dout(0) << "diff_attrs name mismatch (verify: " << b_it->first
78 << ", store: " << a_it->first << ")" << dendl;
83 if (!(b_it->second == a_it->second)) {
84 dout(0) << "diff_attrs contents mismatch on attr " << b_it->first << dendl;
92 bool FileStoreDiff::diff_objects_stat(struct stat& a, struct stat& b)
96 if (a.st_uid != b.st_uid) {
97 dout(0) << "diff_objects_stat uid mismatch (A: "
98 << a.st_uid << " != B: " << b.st_uid << ")" << dendl;
102 if (a.st_gid != b.st_gid) {
103 dout(0) << "diff_objects_stat gid mismatch (A: "
104 << a.st_gid << " != B: " << b.st_gid << ")" << dendl;
108 if (a.st_mode != b.st_mode) {
109 dout(0) << "diff_objects_stat mode mismatch (A: "
110 << a.st_mode << " != B: " << b.st_mode << ")" << dendl;
114 if (a.st_nlink != b.st_nlink) {
115 dout(0) << "diff_objects_stat nlink mismatch (A: "
116 << a.st_nlink << " != B: " << b.st_nlink << ")" << dendl;
120 if (a.st_size != b.st_size) {
121 dout(0) << "diff_objects_stat size mismatch (A: "
122 << a.st_size << " != B: " << b.st_size << ")" << dendl;
128 bool FileStoreDiff::diff_objects(FileStore *a_store, FileStore *b_store, coll_t coll)
130 dout(2) << __func__ << " coll " << coll << dendl;
135 std::vector<ghobject_t> b_objects, a_objects;
136 err = b_store->collection_list(coll, ghobject_t(), ghobject_t::get_max(),
137 INT_MAX, &b_objects, NULL);
139 dout(0) << "diff_objects list on verify coll " << coll.to_str()
140 << " returns " << err << dendl;
143 err = a_store->collection_list(coll, ghobject_t(), ghobject_t::get_max(),
144 INT_MAX, &a_objects, NULL);
146 dout(0) << "diff_objects list on store coll " << coll.to_str()
147 << " returns " << err << dendl;
151 if (b_objects.size() != a_objects.size()) {
152 dout(0) << "diff_objects num objs mismatch (A: " << a_objects.size()
153 << ", B: " << b_objects.size() << ")" << dendl;
157 std::vector<ghobject_t>::iterator b_it = b_objects.begin();
158 std::vector<ghobject_t>::iterator a_it = b_objects.begin();
159 for (; b_it != b_objects.end(); ++b_it, ++a_it) {
160 ghobject_t b_obj = *b_it, a_obj = *a_it;
161 if (b_obj.hobj.oid.name != a_obj.hobj.oid.name) {
162 dout(0) << "diff_objects name mismatch on A object "
163 << coll << "/" << a_obj << " and B object "
164 << coll << "/" << b_obj << dendl;
169 struct stat b_stat, a_stat;
170 err = b_store->stat(coll, b_obj, &b_stat);
172 dout(0) << "diff_objects error stating B object "
173 << coll.to_str() << "/" << b_obj.hobj.oid.name << dendl;
176 err = a_store->stat(coll, a_obj, &a_stat);
178 dout(0) << "diff_objects error stating A object "
179 << coll << "/" << a_obj << dendl;
183 if (diff_objects_stat(a_stat, b_stat)) {
184 dout(0) << "diff_objects stat mismatch on "
185 << coll << "/" << b_obj << dendl;
189 bufferlist a_obj_bl, b_obj_bl;
190 b_store->read(coll, b_obj, 0, b_stat.st_size, b_obj_bl);
191 a_store->read(coll, a_obj, 0, a_stat.st_size, a_obj_bl);
193 if (!a_obj_bl.contents_equal(b_obj_bl)) {
194 dout(0) << "diff_objects content mismatch on "
195 << coll << "/" << b_obj << dendl;
199 std::map<std::string, bufferptr> a_obj_attrs_map, b_obj_attrs_map;
200 err = a_store->getattrs(coll, a_obj, a_obj_attrs_map);
202 dout(0) << "diff_objects getattrs on A object " << coll << "/" << a_obj
203 << " returns " << err << dendl;
206 err = b_store->getattrs(coll, b_obj, b_obj_attrs_map);
208 dout(0) << "diff_objects getattrs on B object " << coll << "/" << b_obj
209 << "returns " << err << dendl;
213 if (diff_attrs(b_obj_attrs_map, a_obj_attrs_map)) {
214 dout(0) << "diff_objects attrs mismatch on A object "
215 << coll << "/" << a_obj << " and B object "
216 << coll << "/" << b_obj << dendl;
220 std::map<std::string, bufferlist> a_obj_omap, b_obj_omap;
221 std::set<std::string> a_omap_keys, b_omap_keys;
222 err = a_store->omap_get_keys(coll, a_obj, &a_omap_keys);
224 dout(0) << "diff_objects getomap on A object " << coll << "/" << a_obj
225 << " returns " << err << dendl;
228 err = a_store->omap_get_values(coll, a_obj, a_omap_keys, &a_obj_omap);
230 dout(0) << "diff_objects getomap on A object " << coll << "/" << a_obj
231 << " returns " << err << dendl;
234 err = b_store->omap_get_keys(coll, b_obj, &b_omap_keys);
236 dout(0) << "diff_objects getomap on A object " << coll << "/" << b_obj
237 << " returns " << err << dendl;
240 err = b_store->omap_get_values(coll, b_obj, b_omap_keys, &b_obj_omap);
242 dout(0) << "diff_objects getomap on A object " << coll << "/" << b_obj
243 << " returns " << err << dendl;
246 if (diff_omap(a_obj_omap, b_obj_omap)) {
247 dout(0) << "diff_objects omap mismatch on A object "
248 << coll << "/" << a_obj << " and B object "
249 << coll << "/" << b_obj << dendl;
257 bool FileStoreDiff::diff()
261 std::vector<coll_t> a_coll_list, b_coll_list;
262 a_store->list_collections(a_coll_list);
263 b_store->list_collections(b_coll_list);
265 std::vector<coll_t>::iterator it = b_coll_list.begin();
266 for (; it != b_coll_list.end(); ++it) {
268 if (!a_store->collection_exists(b_coll)) {
269 dout(0) << "diff B coll " << b_coll.to_str() << " DNE on A" << dendl;
273 for (std::vector<coll_t>::iterator j = a_coll_list.begin();
274 j != a_coll_list.end(); ++j) {
276 a_coll_list.erase(j);
281 if (diff_objects(a_store, b_store, b_coll))
284 for (std::vector<coll_t>::iterator it = a_coll_list.begin();
285 it != a_coll_list.end(); ++it) {
286 dout(0) << "diff A coll " << *it << " DNE on B" << dendl;