Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / tools / rados / PoolDump.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) 2015 Red Hat
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  */
14
15 #include "include/rados/librados.hpp"
16 #include "common/errno.h"
17
18 #include "PoolDump.h"
19
20 using namespace librados;
21
22 #define dout_context g_ceph_context
23 #define dout_subsys ceph_subsys_rados
24
25 /**
26  * Export RADOS objects from a live cluster
27  * to a serialized format via a file descriptor.
28  *
29  * @returns 0 on success, else error code
30  */
31 int PoolDump::dump(IoCtx *io_ctx)
32 {
33   assert(io_ctx != NULL);
34
35   int r = 0;
36   write_super();
37
38   r = write_simple(TYPE_POOL_BEGIN, file_fd);
39   if (r != 0) {
40     return r;
41   }
42
43   io_ctx->set_namespace(all_nspaces);
44   librados::NObjectIterator i = io_ctx->nobjects_begin();
45
46   librados::NObjectIterator i_end = io_ctx->nobjects_end();
47   for (; i != i_end; ++i) {
48     const std::string oid = i->get_oid();
49     dout(10) << "OID '" << oid << "'" << dendl;
50
51     // Compose OBJECT_BEGIN
52     // ====================
53     object_begin obj_begin;
54     obj_begin.hoid.hobj.oid = i->get_oid();
55     obj_begin.hoid.hobj.nspace = i->get_nspace();
56     obj_begin.hoid.hobj.set_key(i->get_locator());
57
58     // Only output head, RadosImport only wants that
59     obj_begin.hoid.hobj.snap = CEPH_NOSNAP;
60
61     // Skip setting object_begin.oi, RadosImport doesn't care
62
63     r = write_section(TYPE_OBJECT_BEGIN, obj_begin, file_fd);
64     if (r != 0) {
65       return r;
66     }
67
68     // Compose TYPE_DATA chunks
69     // ========================
70     const uint32_t op_size = 4096 * 1024;
71     uint64_t offset = 0;
72     io_ctx->set_namespace(i->get_nspace());
73     while (true) {
74       bufferlist outdata;
75       r = io_ctx->read(oid, outdata, op_size, offset);
76       if (r <= 0) {
77         // Error or no data
78         break;
79       }
80
81       r = write_section(TYPE_DATA,
82           data_section(offset, outdata.length(), outdata), file_fd);
83       if (r != 0) {
84         // Output stream error
85         return r;
86       }
87
88       if (outdata.length() < op_size) {
89         // No more data
90         r = 0;
91         break;
92       }
93       offset += outdata.length();
94     }
95
96     // Compose TYPE_ATTRS chunk
97     // ========================
98     std::map<std::string, bufferlist> raw_xattrs;
99     std::map<std::string, bufferlist> xattrs;
100     r = io_ctx->getxattrs(oid, raw_xattrs);
101     if (r < 0) {
102       cerr << "error getting xattr set " << oid << ": " << cpp_strerror(r)
103            << std::endl;
104       return r;
105     }
106     // Prepend "_" to mimic how user keys are represented in a pg export
107     for (std::map<std::string, bufferlist>::iterator i = raw_xattrs.begin();
108          i != raw_xattrs.end(); ++i) {
109       std::pair< std::string, bufferlist> item(std::string("_") + std::string(i->first.c_str()), i->second);
110       xattrs.insert(item);
111     }
112     r = write_section(TYPE_ATTRS, attr_section(xattrs), file_fd);
113     if (r != 0) {
114       return r;
115     }
116
117     // Compose TYPE_OMAP_HDR section
118     // =============================
119     bufferlist omap_header;
120     r = io_ctx->omap_get_header(oid, &omap_header);
121     if (r < 0) {
122       cerr << "error getting omap header " << oid
123            << ": " << cpp_strerror(r) << std::endl;
124       return r;
125     }
126     r = write_section(TYPE_OMAP_HDR, omap_hdr_section(omap_header), file_fd);
127     if (r != 0) {
128       return r;
129     }
130
131     // Compose TYPE_OMAP
132     int MAX_READ = 512;
133     string last_read = "";
134     do {
135       map<string, bufferlist> values;
136       r = io_ctx->omap_get_vals(oid, last_read, MAX_READ, &values);
137       if (r < 0) {
138         cerr << "error getting omap keys " << oid << ": "
139              << cpp_strerror(r) << std::endl;
140         return r;
141       }
142       if (values.size()) {
143         last_read = values.rbegin()->first;
144       } else {
145         break;
146       }
147
148       r = write_section(TYPE_OMAP, omap_section(values), file_fd);
149       if (r != 0) {
150         return r;
151       }
152       r = values.size();
153     } while (r == MAX_READ);
154     r = 0;
155
156     // Close object
157     // =============
158     r = write_simple(TYPE_OBJECT_END, file_fd);
159     if (r != 0) {
160       return r;
161     }
162   }
163
164   r = write_simple(TYPE_POOL_END, file_fd);
165 #if defined(__linux__)
166   if (file_fd != STDOUT_FILENO)
167     posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED);
168 #endif
169   return r;
170 }