Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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       dout(0) << "diff_attrs name mismatch (verify: " << b_it->first
55           << ", store: " << a_it->first << ")" << dendl;
56       ret = true;
57       continue;
58     }
59
60     if (!b_it->second.cmp(a_it->second)) {
61       dout(0) << "diff_attrs contents mismatch on attr " << b_it->first << dendl;
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 (b_it->first != a_it->first) {
77       dout(0) << "diff_attrs name mismatch (verify: " << b_it->first
78           << ", store: " << a_it->first << ")" << dendl;
79       ret = true;
80       continue;
81     }
82
83     if (!(b_it->second == a_it->second)) {
84       dout(0) << "diff_attrs contents mismatch on attr " << b_it->first << dendl;
85       ret = true;
86       continue;
87     }
88   }
89   return ret;
90 }
91
92 bool FileStoreDiff::diff_objects_stat(struct stat& a, struct stat& b)
93 {
94   bool ret = false;
95
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;
99     ret = true;
100   }
101
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;
105     ret = true;
106   }
107
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;
111     ret = true;
112   }
113
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;
117     ret = true;
118   }
119
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;
123     ret = true;
124   }
125   return ret;
126 }
127
128 bool FileStoreDiff::diff_objects(FileStore *a_store, FileStore *b_store, coll_t coll)
129 {
130   dout(2) << __func__ << " coll "  << coll << dendl;
131
132   bool ret = false;
133
134   int err;
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);
138   if (err < 0) {
139     dout(0) << "diff_objects list on verify coll " << coll.to_str()
140             << " returns " << err << dendl;
141     return true;
142   }
143   err = a_store->collection_list(coll, ghobject_t(), ghobject_t::get_max(),
144                                  INT_MAX, &a_objects, NULL);
145   if (err < 0) {
146     dout(0) << "diff_objects list on store coll " << coll.to_str()
147               << " returns " << err << dendl;
148     return true;
149   }
150
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;
154     ret = true;
155   }
156
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;
165       ret = true;
166       continue;
167     }
168
169     struct stat b_stat, a_stat;
170     err = b_store->stat(coll, b_obj, &b_stat);
171     if (err < 0) {
172       dout(0) << "diff_objects error stating B object "
173               << coll.to_str() << "/" << b_obj.hobj.oid.name << dendl;
174       ret = true;
175     }
176     err = a_store->stat(coll, a_obj, &a_stat);
177     if (err < 0) {
178       dout(0) << "diff_objects error stating A object "
179           << coll << "/" << a_obj << dendl;
180       ret = true;
181     }
182
183     if (diff_objects_stat(a_stat, b_stat)) {
184       dout(0) << "diff_objects stat mismatch on "
185           << coll << "/" << b_obj << dendl;
186       ret = true;
187     }
188
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);
192
193     if (!a_obj_bl.contents_equal(b_obj_bl)) {
194       dout(0) << "diff_objects content mismatch on "
195           << coll << "/" << b_obj << dendl;
196       ret = true;
197     }
198
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);
201     if (err < 0) {
202       dout(0) << "diff_objects getattrs on A object " << coll << "/" << a_obj
203               << " returns " << err << dendl;
204       ret = true;
205     }
206     err = b_store->getattrs(coll, b_obj, b_obj_attrs_map);
207     if (err < 0) {
208       dout(0) << "diff_objects getattrs on B object " << coll << "/" << b_obj
209               << "returns " << err << dendl;
210       ret = true;
211     }
212
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;
217       ret = true;
218     }
219
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);
223     if (err < 0) {
224       dout(0) << "diff_objects getomap on A object " << coll << "/" << a_obj
225               << " returns " << err << dendl;
226       ret = true;
227     }
228     err = a_store->omap_get_values(coll, a_obj, a_omap_keys, &a_obj_omap);
229     if (err < 0) {
230       dout(0) << "diff_objects getomap on A object " << coll << "/" << a_obj
231               << " returns " << err << dendl;
232       ret = true;
233     }
234     err = b_store->omap_get_keys(coll, b_obj, &b_omap_keys);
235     if (err < 0) {
236       dout(0) << "diff_objects getomap on A object " << coll << "/" << b_obj
237               << " returns " << err << dendl;
238       ret = true;
239     }
240     err = b_store->omap_get_values(coll, b_obj, b_omap_keys, &b_obj_omap);
241     if (err < 0) {
242       dout(0) << "diff_objects getomap on A object " << coll << "/" << b_obj
243               << " returns " << err << dendl;
244       ret = true;
245     }
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;
250       ret = true;
251     }
252   }
253
254   return ret;
255 }
256
257 bool FileStoreDiff::diff()
258 {
259   bool ret = false;
260
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);
264
265   std::vector<coll_t>::iterator it = b_coll_list.begin();
266   for (; it != b_coll_list.end(); ++it) {
267     coll_t b_coll = *it;
268     if (!a_store->collection_exists(b_coll)) {
269       dout(0) << "diff B coll " << b_coll.to_str() << " DNE on A" << dendl;
270       ret = true;
271       continue;
272     }
273     for (std::vector<coll_t>::iterator j = a_coll_list.begin();
274          j != a_coll_list.end(); ++j) {
275       if (*j == *it) {
276         a_coll_list.erase(j);
277         break;
278       }
279     }
280
281     if (diff_objects(a_store, b_store, b_coll))
282       ret = true;
283   }
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;
287     ret = true;
288   }
289
290   return ret;
291 }