return key;
}
+ void set_key(const std::string &key_) {
+ key = key_;
+ }
+
string to_str() const;
uint32_t get_hash() const {
tools/rados/rados.cc \
tools/rados/rados_import.cc \
tools/rados/rados_export.cc \
- tools/rados/rados_sync.cc
+ tools/rados/rados_sync.cc \
+ tools/RadosDump.cc \
+ tools/RadosImport.cc \
+ tools/rados/PoolDump.cc
rados_SOURCES += common/obj_bencher.cc # needs cleanup so it can go in libcommon.la
rados_LDADD = libcls_lock_client.la $(LIBRADOS) $(CEPH_GLOBAL)
bin_PROGRAMS += rados
tools/rados/rados_sync.h \
tools/RadosDump.h \
tools/RadosImport.h\
- tools/ceph_objectstore_tool.h
+ tools/ceph_objectstore_tool.h \
+ tools/rados/PoolDump.h
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "include/rados/librados.hpp"
+#include "common/errno.h"
+
+#include "PoolDump.h"
+
+using namespace librados;
+
+#define dout_subsys ceph_subsys_rados
+
+/**
+ * Export RADOS objects from a live cluster
+ * to a serialized format via a file descriptor.
+ *
+ * @returns 0 on success, else error code
+ */
+int PoolDump::dump(IoCtx *io_ctx)
+{
+ assert(io_ctx != NULL);
+
+ int r = 0;
+ write_super();
+
+ r = write_simple(TYPE_POOL_BEGIN, file_fd);
+ if (r != 0) {
+ return r;
+ }
+
+ librados::NObjectIterator i = io_ctx->nobjects_begin();
+
+ librados::NObjectIterator i_end = io_ctx->nobjects_end();
+ for (; i != i_end; ++i) {
+ const std::string oid = i->get_oid();
+ dout(10) << "OID '" << oid << "'" << dendl;
+
+ // Compose OBJECT_BEGIN
+ // ====================
+ object_begin obj_begin;
+ obj_begin.hoid.hobj.oid = i->get_oid();
+ obj_begin.hoid.hobj.nspace = i->get_nspace();
+ obj_begin.hoid.hobj.set_key(i->get_locator());
+
+ // Only output head, RadosImport only wants that
+ obj_begin.hoid.hobj.snap = CEPH_NOSNAP;
+
+ // Skip setting object_begin.oi, RadosImport doesn't care
+
+ r = write_section(TYPE_OBJECT_BEGIN, obj_begin, file_fd);
+ if (r != 0) {
+ return r;
+ }
+
+ // Compose TYPE_DATA chunks
+ // ========================
+ const uint32_t op_size = 4096 * 1024;
+ uint64_t offset = 0;
+ while (true) {
+ bufferlist outdata;
+ r = io_ctx->read(oid, outdata, op_size, offset);
+ if (r <= 0) {
+ // Error or no data
+ break;
+ }
+
+ r = write_section(TYPE_DATA,
+ data_section(offset, outdata.length(), outdata), file_fd);
+ if (r != 0) {
+ // Output stream error
+ return r;
+ }
+
+ if (outdata.length() < op_size) {
+ // No more data
+ r = 0;
+ break;
+ }
+ offset += outdata.length();
+ }
+
+ // Compose TYPE_ATTRS chunk
+ // ========================
+ std::map<std::string, bufferlist> xattrs;
+ r = io_ctx->getxattrs(oid, xattrs);
+ if (r < 0) {
+ cerr << "error getting xattr set " << oid << ": " << cpp_strerror(r)
+ << std::endl;
+ return r;
+ }
+ r = write_section(TYPE_ATTRS, attr_section(xattrs), file_fd);
+ if (r != 0) {
+ return r;
+ }
+
+ // Compose TYPE_OMAP_HDR section
+ // =============================
+ bufferlist omap_header;
+ r = io_ctx->omap_get_header(oid, &omap_header);
+ if (r < 0) {
+ cerr << "error getting omap header " << oid
+ << ": " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+ r = write_section(TYPE_OMAP_HDR, omap_hdr_section(omap_header), file_fd);
+ if (r != 0) {
+ return r;
+ }
+
+ // Compose TYPE_OMAP
+ int MAX_READ = 512;
+ string last_read = "";
+ do {
+ map<string, bufferlist> values;
+ r = io_ctx->omap_get_vals(oid, last_read, MAX_READ, &values);
+ if (r < 0) {
+ cerr << "error getting omap keys " << oid << ": "
+ << cpp_strerror(r) << std::endl;
+ return r;
+ }
+ if (values.size()) {
+ last_read = values.rbegin()->first;
+ } else {
+ break;
+ }
+
+ r = write_section(TYPE_OMAP, omap_section(values), file_fd);
+ if (r != 0) {
+ return r;
+ }
+ r = values.size();
+ } while (r == MAX_READ);
+ r = 0;
+
+ // Close object
+ // =============
+ r = write_simple(TYPE_OBJECT_END, file_fd);
+ if (r != 0) {
+ return r;
+ }
+ }
+
+ r = write_simple(TYPE_POOL_END, file_fd);
+
+ return r;
+}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+
+#ifndef POOL_DUMP_H_
+#define POOL_DUMP_H_
+
+#include "tools/RadosDump.h"
+
+namespace librados {
+ class IoCtx;
+}
+
+class PoolDump : public RadosDump
+{
+ public:
+ PoolDump(int file_fd_) : RadosDump(file_fd_, false) {}
+ int dump(librados::IoCtx *io_ctx);
+};
+
+#endif // POOL_DUMP_H_
#include "include/rados/librados.hpp"
#include "include/rados/rados_types.hpp"
#include "rados_sync.h"
-using namespace librados;
#include "common/config.h"
#include "common/ceph_argparse.h"
#include "include/compat.h"
#include "common/hobject.h"
+#include "PoolDump.h"
+#include "tools/RadosImport.h"
+
int rados_tool_sync(const std::map < std::string, std::string > &opts,
std::vector<const char*> &args);
+using namespace librados;
+
// two steps seem to be necessary to do this right
#define STR(x) _STR(x)
#define _STR(x) #x
" set allocation hint for an object\n"
"\n"
"IMPORT AND EXPORT\n"
-" import [options] <local-directory> <rados-pool>\n"
-" Upload <local-directory> to <rados-pool>\n"
-" export [options] <rados-pool> <local-directory>\n"
-" Download <rados-pool> to <local-directory>\n"
-" options:\n"
-" -f / --force Copy everything, even if it hasn't changed.\n"
-" -d / --delete-after After synchronizing, delete unreferenced\n"
-" files or objects from the target bucket\n"
-" or directory.\n"
-" --workers Number of worker threads to spawn \n"
-" (default " STR(DEFAULT_NUM_RADOS_WORKER_THREADS) ")\n"
+" export [filename]\n"
+" Serialize pool contents to a file or standard out.\n"
+" import [filename]\n"
+" Load pool contents from a file or standard in\n"
"\n"
"ADVISORY LOCKS\n"
" lock list <obj-name>\n"
vec.push_back(pool_name);
}
- map<string,pool_stat_t> stats;
+ map<string,librados::pool_stat_t> stats;
ret = rados.get_pool_stats(vec, stats);
if (ret < 0) {
cerr << "error fetching pool stats: " << cpp_strerror(ret) << std::endl;
formatter->open_object_section("stats");
formatter->open_array_section("pools");
}
- for (map<string,pool_stat_t>::iterator i = stats.begin();
+ for (map<string,librados::pool_stat_t>::iterator i = stats.begin();
i != stats.end();
++i) {
const char *pool_name = i->first.c_str();
- pool_stat_t& s = i->second;
+ librados::pool_stat_t& s = i->second;
if (!formatter) {
printf("%-15s "
"%12lld %12lld %12lld %12lld"
<< cpp_strerror(ret) << std::endl;
goto out;
}
+ } else if (strcmp(nargs[0], "export") == 0) {
+ // export [filename]
+ if (!pool_name || nargs.size() > 2) {
+ usage_exit();
+ }
+
+ int file_fd;
+ if (nargs.size() < 2 || std::string(nargs[1]) == "-") {
+ file_fd = STDOUT_FILENO;
+ } else {
+ file_fd = open(nargs[1], O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ if (file_fd < 0) {
+ cerr << "Error opening '" << nargs[1] << "': "
+ << cpp_strerror(file_fd) << std::endl;
+ ret = file_fd;
+ goto out;
+ }
+ }
+
+ ret = PoolDump(file_fd).dump(&io_ctx);
+ if (ret < 0) {
+ cerr << "error from export: "
+ << cpp_strerror(ret) << std::endl;
+ goto out;
+ }
+ } else if (strcmp(nargs[0], "import") == 0) {
+ // import [filename]
+ if (!pool_name || nargs.size() > 2) {
+ usage_exit();
+ }
+
+ int file_fd;
+ if (nargs.size() < 2 || std::string(nargs[1]) == "-") {
+ file_fd = STDIN_FILENO;
+ } else {
+ file_fd = open(nargs[1], O_RDONLY);
+ if (file_fd < 0) {
+ cerr << "Error opening '" << nargs[1] << "': "
+ << cpp_strerror(file_fd) << std::endl;
+ ret = file_fd;
+ goto out;
+ }
+ }
+
+ ret = RadosImport(file_fd, 0, false).import(io_ctx, false);
+ if (ret < 0) {
+ cerr << "error from import: "
+ << cpp_strerror(ret) << std::endl;
+ goto out;
+ }
} else {
cerr << "unrecognized command " << nargs[0] << "; -h or --help for usage" << std::endl;
ret = -EINVAL;
cerr << "rados: you must give an action. Try --help" << std::endl;
return 1;
}
- if ((strcmp(args[0], "import") == 0) || (strcmp(args[0], "export") == 0)) {
- cout << "The import and export operations are not available" << std::endl;
- exit(1);
- //return rados_tool_sync(opts, args);
- } else {
- return rados_tool_common(opts, args);
- }
+
+ return rados_tool_common(opts, args);
}