ceph_mon_CXXFLAGS = ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
bin_PROGRAMS += ceph-mon
-ceph_mon_store_converter_SOURCES = mon_store_converter.cc \
+ceph_mon_store_converter_SOURCES = tools/mon_store_converter.cc \
mon/MonitorStore.cc
ceph_mon_store_converter_LDFLAGS = ${AM_LDFLAGS}
ceph_mon_store_converter_LDADD = $(LIBOS_LDA) $(LIBGLOBAL_LDA)
# admin tools
-ceph_conf_SOURCES = ceph_conf.cc
+ceph_conf_SOURCES = tools/ceph_conf.cc
ceph_conf_LDADD = $(LIBGLOBAL_LDA)
ceph_conf_CXXFLAGS = ${AM_CXXFLAGS}
-ceph_authtool_SOURCES = ceph_authtool.cc
+ceph_authtool_SOURCES = tools/ceph_authtool.cc
ceph_authtool_LDADD = $(LIBGLOBAL_LDA)
ceph_filestore_dump_SOURCES = tools/ceph-filestore-dump.cc
ceph_filestore_dump_SOURCES += perfglue/disabled_heap_profiler.cc
ceph_monstore_tool_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
bin_DEBUGPROGRAMS += ceph-monstore-tool
-monmaptool_SOURCES = monmaptool.cc
+monmaptool_SOURCES = tools/monmaptool.cc
monmaptool_LDADD = $(LIBGLOBAL_LDA)
-crushtool_SOURCES = crushtool.cc
+crushtool_SOURCES = tools/crushtool.cc
crushtool_LDADD = $(LIBGLOBAL_LDA)
-osdmaptool_SOURCES = osdmaptool.cc
+osdmaptool_SOURCES = tools/osdmaptool.cc
osdmaptool_LDADD = $(LIBGLOBAL_LDA)
bin_PROGRAMS += monmaptool crushtool osdmaptool
endif # WITH_TCMALLOC
# debug targets
-ceph_psim_SOURCES = psim.cc
+ceph_psim_SOURCES = tools/psim.cc
ceph_psim_LDADD = $(LIBGLOBAL_LDA)
bin_DEBUGPROGRAMS += ceph_psim
ceph_test_ioctls_SOURCES = client/test_ioctls.c
bin_DEBUGPROGRAMS += ceph_test_ioctls
-ceph_dupstore_SOURCES = dupstore.cc
+ceph_dupstore_SOURCES = tools/dupstore.cc
ceph_dupstore_CXXFLAGS= ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
ceph_dupstore_LDADD = $(LIBOS_LDA) $(LIBGLOBAL_LDA)
ceph_streamtest_SOURCES = test/streamtest.cc
endif
-ceph_scratchtool_SOURCES = scratchtool.c
+ceph_scratchtool_SOURCES = tools/scratchtool.c
ceph_scratchtool_LDADD = librados.la $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXTRALIBS)
-ceph_scratchtoolpp_SOURCES = scratchtoolpp.cc
+ceph_scratchtoolpp_SOURCES = tools/scratchtoolpp.cc
ceph_scratchtoolpp_LDADD = librados.la $(PTHREAD_LIBS) -lm
-ceph_radosacl_SOURCES = radosacl.cc
+ceph_radosacl_SOURCES = tools/radosacl.cc
ceph_radosacl_LDADD = librados.la $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXTRALIBS)
bin_DEBUGPROGRAMS += ceph_scratchtool ceph_scratchtoolpp ceph_radosacl
+++ /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) 2004-2009 Sage Weil <sage@newdream.net>
- *
- * 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 "common/config.h"
-#include "common/strtol.h"
-
-#include "common/ConfUtils.h"
-#include "common/ceph_argparse.h"
-#include "global/global_context.h"
-#include "global/global_init.h"
-#include "auth/Crypto.h"
-#include "auth/Auth.h"
-#include "auth/KeyRing.h"
-
-#include <sstream>
-
-void usage()
-{
- cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n"
- << "where the options are:\n"
- << " -l, --list will list all keys and capabilities present in\n"
- << " the keyring\n"
- << " -p, --print-key will print an encoded key for the specified\n"
- << " entityname. This is suitable for the\n"
- << " 'mount -o secret=..' argument\n"
- << " -C, --create-keyring will create a new keyring, overwriting any\n"
- << " existing keyringfile\n"
- << " -g, --gen-key will generate a new secret key for the\n"
- << " specified entityname\n"
- << " --gen-print-key will generate a new secret key without set it\n"
- << " to the keyringfile, prints the secret to stdout\n"
- << " --import-keyring will import the content of a given keyring\n"
- << " into the keyringfile\n"
- << " -u, --set-uid sets the auid (authenticated user id) for the\n"
- << " specified entityname\n"
- << " -a, --add-key will add an encoded key to the keyring\n"
- << " --cap subsystem capability will set the capability for given subsystem\n"
- << " --caps capsfile will set all of capabilities associated with a\n"
- << " given key, for all subsystems"
- << std::endl;
- exit(1);
-}
-
-int main(int argc, const char **argv)
-{
- vector<const char*> args;
- argv_to_vec(argc, argv, args);
- env_to_vec(args);
-
- bool gen_key = false;
- bool gen_print_key = false;
- std::string add_key;
- bool list = false;
- bool print_key = false;
- bool create_keyring = false;
- std::string caps_fn;
- std::string import_keyring;
- bool set_auid = false;
- uint64_t auid = CEPH_AUTH_UID_DEFAULT;
- map<string,bufferlist> caps;
- std::string fn;
-
- global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
- CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
- std::vector<const char*>::iterator i;
- for (i = args.begin(); i != args.end(); ) {
- std::string val;
- if (ceph_argparse_double_dash(args, i)) {
- break;
- } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) {
- gen_key = true;
- } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) {
- gen_print_key = true;
- } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) {
- add_key = val;
- } else if (ceph_argparse_flag(args, i, &val, "-l", "--list", (char*)NULL)) {
- list = true;
- } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
- caps_fn = val;
- } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) {
- std::string my_key = val;
- if (i == args.end()) {
- cerr << "must give two arguments to --cap: key and val." << std::endl;
- exit(1);
- }
- std::string my_val = *i;
- ++i;
- ::encode(my_val, caps[my_key]);
- } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) {
- print_key = true;
- } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) {
- create_keyring = true;
- } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) {
- import_keyring = val;
- } else if (ceph_argparse_witharg(args, i, &val, "-u", "--set-uid", (char*)NULL)) {
- std::string err;
- auid = strict_strtoll(val.c_str(), 10, &err);
- if (!err.empty()) {
- cerr << "error parsing UID: " << err << std::endl;
- exit(1);
- }
- set_auid = true;
- } else if (fn.empty()) {
- fn = *i++;
- } else {
- cerr << argv[0] << ": unexpected '" << *i << "'" << std::endl;
- usage();
- }
- }
- if (fn.empty() && !gen_print_key) {
- cerr << argv[0] << ": must specify filename" << std::endl;
- usage();
- }
- if (!(gen_key ||
- gen_print_key ||
- !add_key.empty() ||
- list ||
- !caps_fn.empty() ||
- !caps.empty() ||
- set_auid ||
- print_key ||
- create_keyring ||
- !import_keyring.empty())) {
- cerr << "no command specified" << std::endl;
- usage();
- }
- if (gen_key && (!add_key.empty())) {
- cerr << "can't both gen_key and add_key" << std::endl;
- usage();
- }
-
- common_init_finish(g_ceph_context);
- EntityName ename(g_conf->name);
-
- if (gen_print_key) {
- CryptoKey key;
- key.create(g_ceph_context, CEPH_CRYPTO_AES);
- cout << key << std::endl;
- return 0;
- }
-
- // keyring --------
- bool modified = false;
- KeyRing keyring;
-
- bufferlist bl;
- int r = 0;
- if (create_keyring) {
- cout << "creating " << fn << std::endl;
- modified = true;
- } else {
- std::string err;
- r = bl.read_file(fn.c_str(), &err);
- if (r >= 0) {
- try {
- bufferlist::iterator iter = bl.begin();
- ::decode(keyring, iter);
- } catch (const buffer::error &err) {
- cerr << "error reading file " << fn << std::endl;
- exit(1);
- }
- } else {
- cerr << "can't open " << fn << ": " << err << std::endl;
- exit(1);
- }
- }
-
- // write commands
- if (!import_keyring.empty()) {
- KeyRing other;
- bufferlist obl;
- std::string err;
- int r = obl.read_file(import_keyring.c_str(), &err);
- if (r >= 0) {
- try {
- bufferlist::iterator iter = obl.begin();
- ::decode(other, iter);
- } catch (const buffer::error &err) {
- cerr << "error reading file " << import_keyring << std::endl;
- exit(1);
- }
-
- cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
- //other.print(cout);
- keyring.import(g_ceph_context, other);
- modified = true;
- } else {
- cerr << "can't open " << import_keyring << ": " << err << std::endl;
- exit(1);
- }
- }
- if (gen_key) {
- EntityAuth eauth;
- eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES);
- keyring.add(ename, eauth);
- modified = true;
- }
- if (!add_key.empty()) {
- EntityAuth eauth;
- try {
- eauth.key.decode_base64(add_key);
- } catch (const buffer::error &err) {
- cerr << "can't decode key '" << add_key << "'" << std::endl;
- exit(1);
- }
- keyring.add(ename, eauth);
- modified = true;
- cout << "added entity " << ename << " auth " << eauth << std::endl;
- }
- if (!caps_fn.empty()) {
- ConfFile cf;
- std::deque<std::string> parse_errors;
- if (cf.parse_file(caps_fn, &parse_errors, &cerr) != 0) {
- cerr << "could not parse caps file " << caps_fn << std::endl;
- exit(1);
- }
- complain_about_parse_errors(g_ceph_context, &parse_errors);
- map<string, bufferlist> caps;
- const char *key_names[] = { "mon", "osd", "mds", NULL };
- for (int i=0; key_names[i]; i++) {
- std::string val;
- if (cf.read("global", key_names[i], val) == 0) {
- bufferlist bl;
- ::encode(val, bl);
- string s(key_names[i]);
- caps[s] = bl;
- }
- }
- keyring.set_caps(ename, caps);
- modified = true;
- }
- if (!caps.empty()) {
- keyring.set_caps(ename, caps);
- modified = true;
- }
- if (set_auid) {
- keyring.set_uid(ename, auid);
- modified = true;
- }
-
- // read commands
- if (list) {
- keyring.print(cout);
- }
- if (print_key) {
- CryptoKey key;
- if (keyring.get_secret(ename, key)) {
- cout << key << std::endl;
- } else {
- cerr << "entity " << ename << " not found" << std::endl;
- }
- }
-
- // write result?
- if (modified) {
- bufferlist bl;
- keyring.encode_plaintext(bl);
- r = bl.write_file(fn.c_str(), 0600);
- if (r < 0) {
- cerr << "could not write " << fn << std::endl;
- }
- //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;
- }
-
- return 0;
-}
+++ /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) 2004-2010 Dreamhost
- *
- * 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 <fcntl.h>
-#include <iostream>
-#include <string>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "mon/AuthMonitor.h"
-#include "common/ConfUtils.h"
-#include "global/global_init.h"
-#include "common/entity_name.h"
-#include "common/ceph_argparse.h"
-#include "common/config.h"
-#include "include/str_list.h"
-
-using std::deque;
-using std::string;
-
-static void usage()
-{
- // TODO: add generic_usage once cerr/derr issues are resolved
- cerr << "Ceph configuration query tool\n\
-\n\
-USAGE\n\
-ceph-conf <flags> <action>\n\
-\n\
-ACTIONS\n\
- -L|--list-all-sections List all sections\n\
- -l|--list-sections <prefix> List sections with the given prefix\n\
- --filter-key <key> Filter section list to only include sections\n\
- with given key defined.\n\
- --filter-key-value <key>=<val> Filter section list to only include sections\n\
- with given key/value pair.\n\
- --lookup <key> Print a configuration setting to stdout.\n\
- Returns 0 (success) if the configuration setting is\n\
- found; 1 otherwise.\n\
- -r|--resolve-search search for the first file that exists and\n\
- can be opened in the resulted comma\n\
- delimited search list.\n\
-\n\
-FLAGS\n\
- --name name Set type.id\n\
- [-s <section>] Add to list of sections to search\n\
-\n\
-If there is no action given, the action will default to --lookup.\n\
-\n\
-EXAMPLES\n\
-$ ceph-conf --name mon.0 -c /etc/ceph/ceph.conf 'mon addr'\n\
-Find out what the value of 'mon add' is for monitor 0.\n\
-\n\
-$ ceph-conf -l mon\n\
-List sections beginning with 'mon'.\n\
-\n\
-RETURN CODE\n\
-Return code will be 0 on success; error code otherwise.\n\
-";
- exit(1);
-}
-
-static int list_sections(const std::string &prefix,
- const std::list<string>& filter_key,
- const std::map<string,string>& filter_key_value)
-{
- std::vector <std::string> sections;
- int ret = g_conf->get_all_sections(sections);
- if (ret)
- return 2;
- for (std::vector<std::string>::const_iterator p = sections.begin();
- p != sections.end(); ++p) {
- if (strncmp(prefix.c_str(), p->c_str(), prefix.size()))
- continue;
-
- std::vector<std::string> sec;
- sec.push_back(*p);
-
- int r = 0;
- for (std::list<string>::const_iterator q = filter_key.begin(); q != filter_key.end(); ++q) {
- string v;
- r = g_conf->get_val_from_conf_file(sec, q->c_str(), v, false);
- if (r < 0)
- break;
- }
- if (r < 0)
- continue;
-
- for (std::map<string,string>::const_iterator q = filter_key_value.begin();
- q != filter_key_value.end();
- ++q) {
- string v;
- r = g_conf->get_val_from_conf_file(sec, q->first.c_str(), v, false);
- if (r < 0 || v != q->second) {
- r = -1;
- break;
- }
- }
- if (r < 0)
- continue;
-
- cout << *p << std::endl;
- }
- return 0;
-}
-
-static int lookup(const std::deque<std::string> §ions,
- const std::string &key, bool resolve_search)
-{
- std::vector <std::string> my_sections;
- for (deque<string>::const_iterator s = sections.begin(); s != sections.end(); ++s) {
- my_sections.push_back(*s);
- }
- g_conf->get_my_sections(my_sections);
- std::string val;
- int ret = g_conf->get_val_from_conf_file(my_sections, key.c_str(), val, true);
- if (ret == -ENOENT)
- return 1;
- else if (ret == 0) {
- if (resolve_search) {
- string result;
- if (ceph_resolve_file_search(val, result))
- puts(result.c_str());
- }
- else {
- puts(val.c_str());
- }
- return 0;
- }
- else {
- cerr << "error looking up '" << key << "': error " << ret << std::endl;
- return 2;
- }
-}
-
-int main(int argc, const char **argv)
-{
- vector<const char*> args;
- deque<std::string> sections;
- bool resolve_search = false;
- std::string action;
- std::string lookup_key;
- std::string section_list_prefix;
- std::list<string> filter_key;
- std::map<string,string> filter_key_value;
-
- argv_to_vec(argc, argv, args);
- env_to_vec(args);
-
- global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
- CINIT_FLAG_NO_DAEMON_ACTIONS);
-
- // do not common_init_finish(); do not start threads; do not do any of thing
- // wonky things the daemon whose conf we are examining would do (like initialize
- // the admin socket).
- //common_init_finish(g_ceph_context);
-
- std::string val;
- for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
- if (ceph_argparse_double_dash(args, i)) {
- break;
- } else if (ceph_argparse_witharg(args, i, &val, "-s", "--section", (char*)NULL)) {
- sections.push_back(val);
- } else if (ceph_argparse_flag(args, i, "-r", "--resolve_search", (char*)NULL)) {
- resolve_search = true;
- } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
- action = "help";
- } else if (ceph_argparse_witharg(args, i, &val, "--lookup", (char*)NULL)) {
- action = "lookup";
- lookup_key = val;
- } else if (ceph_argparse_flag(args, i, "-L", "--list_all_sections", (char*)NULL)) {
- action = "list-sections";
- section_list_prefix = "";
- } else if (ceph_argparse_witharg(args, i, &val, "-l", "--list_sections", (char*)NULL)) {
- action = "list-sections";
- section_list_prefix = val;
- } else if (ceph_argparse_witharg(args, i, &val, "--filter_key", (char*)NULL)) {
- filter_key.push_back(val);
- } else if (ceph_argparse_witharg(args, i, &val, "--filter_key_value", (char*)NULL)) {
- size_t pos = val.find_first_of('=');
- if (pos == string::npos) {
- cerr << "expecting argument like 'key=value' for --filter-key-value (not '" << val << "')" << std::endl;
- usage();
- exit(1);
- }
- string key(val, 0, pos);
- string value(val, pos+1);
- filter_key_value[key] = value;
- } else {
- if (((action == "lookup") || (action == "")) && (lookup_key.empty())) {
- action = "lookup";
- lookup_key = *i++;
- } else {
- cerr << "unable to parse option: '" << *i << "'" << std::endl;
- usage();
- exit(1);
- }
- }
- }
-
- if (action == "help") {
- usage();
- exit(0);
- } else if (action == "list-sections") {
- return list_sections(section_list_prefix, filter_key, filter_key_value);
- } else if (action == "lookup") {
- return lookup(sections, lookup_key, resolve_search);
- } else {
- cerr << "You must give an action, such as --lookup or --list-all-sections." << std::endl;
- cerr << "Pass --help for more help." << std::endl;
- exit(1);
- }
-}
+++ /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) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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 <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <fstream>
-
-#include "common/debug.h"
-#include "common/errno.h"
-#include "common/config.h"
-
-#include "common/ceph_argparse.h"
-#include "global/global_context.h"
-#include "global/global_init.h"
-#include "crush/CrushWrapper.h"
-#include "crush/CrushCompiler.h"
-#include "crush/CrushTester.h"
-#include "include/assert.h"
-
-#define dout_subsys ceph_subsys_crush
-
-using namespace std;
-
-const char *infn = "stdin";
-
-
-////////////////////////////////////////////////////////////////////////////
-
-void data_analysis_usage()
-{
-cout << "data output from testing routine ...\n";
-cout << " absolute_weights\n";
-cout << " the decimal weight of each OSD\n";
-cout << " data layout: ROW MAJOR\n";
-cout << " OSD id (int), weight (int)\n";
-cout << " batch_device_expected_utilization_all\n";
-cout << " the expected number of objects each OSD should receive per placement batch\n";
-cout << " which may be a decimal value\n";
-cout << " data layout: COLUMN MAJOR\n";
-cout << " round (int), objects expected on OSD 0...OSD n (float)\n";
-cout << " batch_device_utilization_all\n";
-cout << " the number of objects stored on each OSD during each placement round\n";
-cout << " data layout: COLUMN MAJOR\n";
-cout << " round (int), objects stored on OSD 0...OSD n (int)\n";
-cout << " device_utilization_all\n";
-cout << " the number of objects stored on each OSD at the end of placements\n";
-cout << " data_layout: ROW MAJOR\n";
-cout << " OSD id (int), objects stored (int), objects expected (float)\n";
-cout << " device_utilization\n";
-cout << " the number of objects stored on each OSD marked 'up' at the end of placements\n";
-cout << " data_layout: ROW MAJOR\n";
-cout << " OSD id (int), objects stored (int), objects expected (float)\n";
-cout << " placement_information\n";
-cout << " the map of input -> OSD\n";
-cout << " data_layout: ROW MAJOR\n";
-cout << " input (int), OSD's mapped (int)\n";
-cout << " proportional_weights_all\n";
-cout << " the proportional weight of each OSD specified in the CRUSH map\n";
-cout << " data_layout: ROW MAJOR\n";
-cout << " OSD id (int), proportional weight (float)\n";
-cout << " proportional_weights\n";
-cout << " the proportional weight of each 'up' OSD specified in the CRUSH map\n";
-cout << " data_layout: ROW MAJOR\n";
-cout << " OSD id (int), proportional weight (float)\n";
-}
-
-void usage()
-{
- cout << "usage: crushtool ...\n";
- cout << " --decompile|-d map decompile a crush map to source\n";
- cout << " --compile|-c map.txt compile a map from source\n";
- cout << " [-o outfile [--clobber]]\n";
- cout << " specify output for for (de)compilation\n";
- cout << " --build --num_osds N layer1 ...\n";
- cout << " build a new map, where each 'layer' is\n";
- cout << " 'name (uniform|straw|list|tree) size'\n";
- cout << " -i mapfn --test test a range of inputs on the map\n";
- cout << " [--min-x x] [--max-x x] [--x x]\n";
- cout << " [--min-rule r] [--max-rule r] [--rule r]\n";
- cout << " [--num-rep n]\n";
- cout << " [--batches b] split the CRUSH mapping into b > 1 rounds\n";
- cout << " [--weight|-w devno weight]\n";
- cout << " where weight is 0 to 1.0\n";
- cout << " [--simulate] simulate placements using a random\n";
- cout << " number generator in place of the CRUSH\n";
- cout << " algorithm\n";
- cout << " -i mapfn --add-item id weight name [--loc type name ...]\n";
- cout << " insert an item into the hierarchy at the\n";
- cout << " given location\n";
- cout << " -i mapfn --update-item id weight name [--loc type name ...]\n";
- cout << " insert or move an item into the hierarchy at the\n";
- cout << " given location\n";
- cout << " -i mapfn --remove-item name\n"
- << " remove the given item\n";
- cout << " -i mapfn --reweight-item name weight\n";
- cout << " reweight a given item (and adjust ancestor\n"
- << " weights as needed)\n";
- cout << " -i mapfn --reweight recalculate all bucket weights\n";
- cout << " --show-utilization show OSD usage\n";
- cout << " --show utilization-all\n";
- cout << " include zero weight items\n";
- cout << " --show-statistics show chi squared statistics\n";
- cout << " --show-bad-mappings show bad mappings\n";
- cout << " --show-choose-tries show choose tries histogram\n";
- cout << " --set-choose-local-tries N\n";
- cout << " set choose local retries before re-descent\n";
- cout << " --set-choose-local-fallback-tries N\n";
- cout << " set choose local retries using fallback\n";
- cout << " permutation before re-descent\n";
- cout << " --set-choose-total-tries N\n";
- cout << " set choose total descent attempts\n";
- cout << " --set-chooseleaf-descend-once <0|1>\n";
- cout << " set chooseleaf to (not) retry the recursive descent\n";
- cout << " --output-name name\n";
- cout << " prepend the data file(s) generated during the\n";
- cout << " testing routine with name\n";
- cout << " --output-csv\n";
- cout << " export select data generated during testing routine\n";
- cout << " to CSV files for off-line post-processing\n";
- cout << " use --help-output for more information\n";
-}
-
-struct bucket_types_t {
- const char *name;
- int type;
-} bucket_types[] = {
- { "uniform", CRUSH_BUCKET_UNIFORM },
- { "list", CRUSH_BUCKET_LIST },
- { "straw", CRUSH_BUCKET_STRAW },
- { "tree", CRUSH_BUCKET_TREE },
- { 0, 0 },
-};
-
-struct layer_t {
- const char *name;
- const char *buckettype;
- int size;
-};
-
-int main(int argc, const char **argv)
-{
- vector<const char*> args;
- argv_to_vec(argc, argv, args);
-
- const char *me = argv[0];
- std::string infn, srcfn, outfn, add_name, remove_name, reweight_name;
- bool compile = false;
- bool decompile = false;
- bool test = false;
- bool display = false;
- bool write_to_file = false;
- int verbose = 0;
- bool unsafe_tunables = false;
-
- bool reweight = false;
- int add_item = -1;
- bool update_item = false;
- float add_weight = 0;
- map<string,string> add_loc;
- float reweight_weight = 0;
-
- bool adjust = false;
-
- int build = 0;
- int num_osds =0;
- vector<layer_t> layers;
-
- int choose_local_tries = -1;
- int choose_local_fallback_tries = -1;
- int choose_total_tries = -1;
- int chooseleaf_descend_once = -1;
-
- CrushWrapper crush;
-
- CrushTester tester(crush, cerr, 1);
-
- vector<const char *> empty_args; // we use -c, don't confuse the generic arg parsing
- global_init(NULL, empty_args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
- CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
- common_init_finish(g_ceph_context);
-
- int x;
- float y;
-
- std::string val;
- std::ostringstream err;
- int tmp;
- for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
- if (ceph_argparse_double_dash(args, i)) {
- break;
- } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
- usage();
- exit(0);
- } else if (ceph_argparse_witharg(args, i, &val, "-d", "--decompile", (char*)NULL)) {
- infn = val;
- decompile = true;
- } else if (ceph_argparse_witharg(args, i, &val, "-i", "--infn", (char*)NULL)) {
- infn = val;
- } else if (ceph_argparse_witharg(args, i, &val, "-o", "--outfn", (char*)NULL)) {
- outfn = val;
- } else if (ceph_argparse_flag(args, i, "-v", "--verbose", (char*)NULL)) {
- verbose += 1;
- } else if (ceph_argparse_flag(args, i, "--show_utilization", (char*)NULL)) {
- display = true;
- tester.set_output_utilization(true);
- } else if (ceph_argparse_flag(args, i, "--show_utilization_all", (char*)NULL)) {
- display = true;
- tester.set_output_utilization_all(true);
- } else if (ceph_argparse_flag(args, i, "--show_statistics", (char*)NULL)) {
- display = true;
- tester.set_output_statistics(true);
- } else if (ceph_argparse_flag(args, i, "--show_bad_mappings", (char*)NULL)) {
- display = true;
- tester.set_output_bad_mappings(true);
- } else if (ceph_argparse_flag(args, i, "--show_choose_tries", (char*)NULL)) {
- display = true;
- tester.set_output_choose_tries(true);
- } else if (ceph_argparse_witharg(args, i, &val, "-c", "--compile", (char*)NULL)) {
- srcfn = val;
- compile = true;
- } else if (ceph_argparse_flag(args, i, "-t", "--test", (char*)NULL)) {
- test = true;
- } else if (ceph_argparse_flag(args, i, "-s", "--simulate", (char*)NULL)) {
- tester.set_random_placement();
- } else if (ceph_argparse_flag(args, i, "--enable-unsafe-tunables", (char*)NULL)) {
- unsafe_tunables = true;
- } else if (ceph_argparse_withint(args, i, &choose_local_tries, &err,
- "--set_choose_local_tries", (char*)NULL)) {
- adjust = true;
- } else if (ceph_argparse_withint(args, i, &choose_local_fallback_tries, &err,
- "--set_choose_local_fallback_tries", (char*)NULL)) {
- adjust = true;
- } else if (ceph_argparse_withint(args, i, &choose_total_tries, &err,
- "--set_choose_total_tries", (char*)NULL)) {
- adjust = true;
- } else if (ceph_argparse_withint(args, i, &chooseleaf_descend_once, &err,
- "--set_chooseleaf_descend_once", (char*)NULL)) {
- adjust = true;
- } else if (ceph_argparse_flag(args, i, "--reweight", (char*)NULL)) {
- reweight = true;
- } else if (ceph_argparse_withint(args, i, &add_item, &err, "--add_item", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- if (i == args.end()) {
- cerr << "expecting additional argument to --add-item" << std::endl;
- exit(EXIT_FAILURE);
- }
- add_weight = atof(*i);
- i = args.erase(i);
- if (i == args.end()) {
- cerr << "expecting additional argument to --add-item" << std::endl;
- exit(EXIT_FAILURE);
- }
- add_name.assign(*i);
- i = args.erase(i);
- } else if (ceph_argparse_withint(args, i, &add_item, &err, "--update_item", (char*)NULL)) {
- update_item = true;
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- if (i == args.end()) {
- cerr << "expecting additional argument to --update-item" << std::endl;
- exit(EXIT_FAILURE);
- }
- add_weight = atof(*i);
- i = args.erase(i);
- if (i == args.end()) {
- cerr << "expecting additional argument to --update-item" << std::endl;
- exit(EXIT_FAILURE);
- }
- add_name.assign(*i);
- i = args.erase(i);
- } else if (ceph_argparse_witharg(args, i, &val, "--loc", (char*)NULL)) {
- std::string type(val);
- if (i == args.end()) {
- cerr << "expecting additional argument to --loc" << std::endl;
- exit(EXIT_FAILURE);
- }
- std::string name(*i);
- i = args.erase(i);
- add_loc[type] = name;
- } else if (ceph_argparse_flag(args, i, "--output-csv", (char*)NULL)) {
- write_to_file = true;
- tester.set_output_data_file(true);
- tester.set_output_csv(true);
- } else if (ceph_argparse_flag(args, i, "--help-output", (char*)NULL)) {
- data_analysis_usage();
- exit(0);
- } else if (ceph_argparse_witharg(args, i, &val, "--output-name", (char*)NULL)) {
- std::string name(val);
- if (i == args.end()) {
- cerr << "expecting additional argument to --output-name" << std::endl;
- exit(EXIT_FAILURE);
- }
- else {
- tester.set_output_data_file_name(name + "-");
- }
- } else if (ceph_argparse_witharg(args, i, &val, "--remove_item", (char*)NULL)) {
- remove_name = val;
- } else if (ceph_argparse_witharg(args, i, &val, "--reweight_item", (char*)NULL)) {
- reweight_name = val;
- if (i == args.end()) {
- cerr << "expecting additional argument to --reweight-item" << std::endl;
- exit(EXIT_FAILURE);
- }
- reweight_weight = atof(*i);
- i = args.erase(i);
- } else if (ceph_argparse_flag(args, i, "--build", (char*)NULL)) {
- build = true;
- } else if (ceph_argparse_withint(args, i, &num_osds, &err, "--num_osds", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- } else if (ceph_argparse_withint(args, i, &x, &err, "--num_rep", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_num_rep(x);
- } else if (ceph_argparse_withint(args, i, &x, &err, "--max_x", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_max_x(x);
- } else if (ceph_argparse_withint(args, i, &x, &err, "--min_x", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_min_x(x);
- } else if (ceph_argparse_withint(args, i, &x, &err, "--x", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_x(x);
- } else if (ceph_argparse_withint(args, i, &x, &err, "--max_rule", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_max_rule(x);
- } else if (ceph_argparse_withint(args, i, &x, &err, "--min_rule", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_min_rule(x);
- } else if (ceph_argparse_withint(args, i, &x, &err, "--rule", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_rule(x);
- } else if (ceph_argparse_withint(args, i, &x, &err, "--batches", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_batches(x);
- } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-ratio", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_device_down_ratio(y);
- } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-bucket-ratio", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- tester.set_bucket_down_ratio(y);
- } else if (ceph_argparse_withint(args, i, &tmp, &err, "--weight", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- int dev = tmp;
- if (i == args.end()) {
- cerr << "expecting additional argument to --weight" << std::endl;
- exit(EXIT_FAILURE);
- }
- float f = atof(*i);
- i = args.erase(i);
- tester.set_device_weight(dev, f);
- }
- else {
- ++i;
- }
- }
-
- if (test && !display && !write_to_file) {
- cerr << "WARNING: no output selected; use --output-csv or --show-X" << std::endl;
- exit(EXIT_FAILURE);
- }
-
- if (decompile + compile + build > 1) {
- cout << "cannot specify more than one of compile, decompile, and build" << std::endl;
- exit(EXIT_FAILURE);
- }
- if (!compile && !decompile && !build && !test && !reweight && !adjust &&
- add_item < 0 &&
- remove_name.empty() && reweight_name.empty()) {
- cout << "no action specified; -h for help" << std::endl;
- exit(EXIT_FAILURE);
- }
- if ((!build) && (!args.empty())) {
- cerr << "unrecognized arguments: " << args << std::endl;
- exit(EXIT_FAILURE);
- }
- else {
- if ((args.size() % 3) != 0U) {
- cerr << "layers must be specified with 3-tuples of (name, buckettype, size)"
- << std::endl;
- exit(EXIT_FAILURE);
- }
- for (size_t j = 0; j < args.size(); j += 3) {
- layer_t l;
- l.name = args[j];
- l.buckettype = args[j+1];
- l.size = atoi(args[j+2]);
- layers.push_back(l);
- }
- }
-
- /*
- if (outfn) cout << "outfn " << outfn << std::endl;
- if (cinfn) cout << "cinfn " << cinfn << std::endl;
- if (dinfn) cout << "dinfn " << dinfn << std::endl;
- */
-
- bool modified = false;
-
- if (!infn.empty()) {
- bufferlist bl;
- std::string error;
- int r = bl.read_file(infn.c_str(), &error);
- if (r < 0) {
- cerr << me << ": error reading '" << infn << "': "
- << error << std::endl;
- exit(1);
- }
- bufferlist::iterator p = bl.begin();
- crush.decode(p);
- }
-
- if (decompile) {
- CrushCompiler cc(crush, cerr, verbose);
- if (!outfn.empty()) {
- ofstream o;
- o.open(outfn.c_str(), ios::out | ios::binary | ios::trunc);
- if (!o.is_open()) {
- cerr << me << ": error writing '" << outfn << "'" << std::endl;
- exit(1);
- }
- cc.decompile(o);
- o.close();
- } else {
- cc.decompile(cout);
- }
- }
-
- if (compile) {
- crush.create();
-
- // read the file
- ifstream in(srcfn.c_str());
- if (!in.is_open()) {
- cerr << "input file " << srcfn << " not found" << std::endl;
- return -ENOENT;
- }
-
- CrushCompiler cc(crush, cerr, verbose);
- if (unsafe_tunables)
- cc.enable_unsafe_tunables();
- int r = cc.compile(in, srcfn.c_str());
- if (r < 0)
- exit(1);
-
- modified = true;
- }
-
- if (build) {
- if (layers.empty()) {
- cerr << me << ": must specify at least one layer" << std::endl;
- exit(1);
- }
-
- crush.create();
-
- vector<int> lower_items;
- vector<int> lower_weights;
-
- for (int i=0; i<num_osds; i++) {
- lower_items.push_back(i);
- lower_weights.push_back(0x10000);
- }
-
- int type = 1;
- int rootid = 0;
- for (vector<layer_t>::iterator p = layers.begin(); p != layers.end(); ++p, type++) {
- layer_t &l = *p;
-
- dout(0) << "layer " << type
- << " " << l.name
- << " bucket type " << l.buckettype
- << " " << l.size
- << dendl;
-
- crush.set_type_name(type, l.name);
-
- int buckettype = -1;
- for (int i = 0; bucket_types[i].name; i++)
- if (l.buckettype && strcmp(l.buckettype, bucket_types[i].name) == 0) {
- buckettype = bucket_types[i].type;
- break;
- }
- if (buckettype < 0) {
- cerr << "unknown bucket type '" << l.buckettype << "'" << std::endl << std::endl;
- exit(EXIT_FAILURE);
- }
-
- // build items
- vector<int> cur_items;
- vector<int> cur_weights;
- unsigned lower_pos = 0; // lower pos
-
- dout(0) << "lower_items " << lower_items << dendl;
- dout(0) << "lower_weights " << lower_weights << dendl;
-
- int i = 0;
- while (1) {
- if (lower_pos == lower_items.size())
- break;
-
- int items[num_osds];
- int weights[num_osds];
-
- int weight = 0;
- int j;
- for (j=0; j<l.size || l.size==0; j++) {
- if (lower_pos == lower_items.size())
- break;
- items[j] = lower_items[lower_pos];
- weights[j] = lower_weights[lower_pos];
- weight += weights[j];
- lower_pos++;
- dout(0) << " item " << items[j] << " weight " << weights[j] << dendl;
- }
-
- crush_bucket *b = crush_make_bucket(buckettype, CRUSH_HASH_DEFAULT, type, j, items, weights);
- assert(b);
- int id = crush_add_bucket(crush.crush, 0, b);
- rootid = id;
-
- char format[20];
- format[sizeof(format)-1] = '\0';
- if (l.size)
- snprintf(format, sizeof(format)-1, "%s%%d", l.name);
- else
- strncpy(format, l.name, sizeof(format)-1);
- char name[20];
- snprintf(name, sizeof(name), format, i);
- crush.set_item_name(id, name);
-
- dout(0) << " in bucket " << id << " '" << name << "' size " << j << " weight " << weight << dendl;
-
- cur_items.push_back(id);
- cur_weights.push_back(weight);
- i++;
- }
-
- lower_items.swap(cur_items);
- lower_weights.swap(cur_weights);
- }
-
- // make a generic rules
- int ruleset=1;
- crush_rule *rule = crush_make_rule(3, ruleset, CEPH_PG_TYPE_REP, 2, 2);
- assert(rule);
- crush_rule_set_step(rule, 0, CRUSH_RULE_TAKE, rootid, 0);
- crush_rule_set_step(rule, 1, CRUSH_RULE_CHOOSE_LEAF_FIRSTN, CRUSH_CHOOSE_N, 1);
- crush_rule_set_step(rule, 2, CRUSH_RULE_EMIT, 0, 0);
- int rno = crush_add_rule(crush.crush, rule, -1);
- crush.set_rule_name(rno, "data");
-
- modified = true;
- }
-
- if (!reweight_name.empty()) {
- cout << me << " reweighting item " << reweight_name << " to " << reweight_weight << std::endl;
- int r;
- if (!crush.name_exists(reweight_name)) {
- cerr << " name " << reweight_name << " dne" << std::endl;
- r = -ENOENT;
- } else {
- int item = crush.get_item_id(reweight_name);
- r = crush.adjust_item_weightf(g_ceph_context, item, reweight_weight);
- }
- if (r >= 0)
- modified = true;
- else {
- cerr << me << " " << cpp_strerror(r) << std::endl;
- return r;
- }
-
- }
- if (!remove_name.empty()) {
- cout << me << " removing item " << remove_name << std::endl;
- int r;
- if (!crush.name_exists(remove_name)) {
- cerr << " name " << remove_name << " dne" << std::endl;
- r = -ENOENT;
- } else {
- int remove_item = crush.get_item_id(remove_name);
- r = crush.remove_item(g_ceph_context, remove_item, false);
- }
- if (r == 0)
- modified = true;
- else {
- cerr << me << " " << cpp_strerror(r) << std::endl;
- return r;
- }
- }
- if (add_item >= 0) {
- int r;
- if (update_item) {
- r = crush.update_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc);
- } else {
- r = crush.insert_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc);
- }
- if (r >= 0) {
- modified = true;
- } else {
- cerr << me << " " << cpp_strerror(r) << std::endl;
- return r;
- }
- }
- if (reweight) {
- crush.reweight(g_ceph_context);
- modified = true;
- }
-
- const char *scary_tunables_message =
- "** tunables are DANGEROUS and NOT YET RECOMMENDED. DO NOT USE without\n"
- "** confirming with developers that your use-case is safe and correct.";
- if (choose_local_tries >= 0) {
- if (!unsafe_tunables) {
- cerr << scary_tunables_message << std::endl;
- return -1;
- }
- crush.set_choose_local_tries(choose_local_tries);
- modified = true;
- }
- if (choose_local_fallback_tries >= 0) {
- if (!unsafe_tunables) {
- cerr << scary_tunables_message << std::endl;
- return -1;
- }
- crush.set_choose_local_fallback_tries(choose_local_fallback_tries);
- modified = true;
- }
- if (choose_total_tries >= 0) {
- if (!unsafe_tunables) {
- cerr << scary_tunables_message << std::endl;
- return -1;
- }
- crush.set_choose_total_tries(choose_total_tries);
- modified = true;
- }
- if (chooseleaf_descend_once >= 0) {
- if (!unsafe_tunables) {
- cerr << scary_tunables_message << std::endl;
- return -1;
- }
- crush.set_chooseleaf_descend_once(chooseleaf_descend_once);
- modified = true;
- }
- if (modified) {
- crush.finalize();
-
- if (outfn.empty()) {
- cout << me << " successfully built or modified map. Use '-o <file>' to write it out." << std::endl;
- } else {
- bufferlist bl;
- crush.encode(bl);
- int r = bl.write_file(outfn.c_str());
- if (r < 0) {
- char buf[80];
- cerr << me << ": error writing '" << outfn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
- exit(1);
- }
- if (verbose)
- cout << "wrote crush map to " << outfn << std::endl;
- }
- }
-
- if (test) {
- int r = tester.test();
- if (r < 0)
- exit(1);
- }
-
- return 0;
-}
+++ /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) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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 <iostream>
-#include "os/FileStore.h"
-#include "common/ceph_argparse.h"
-#include "global/global_init.h"
-
-#include <ext/hash_map>
-using __gnu_cxx::hash_map;
-
-int dupstore(ObjectStore* src, ObjectStore* dst)
-{
- if (src->mount() < 0) return 1;
- if (dst->mkfs() < 0) return 1;
- if (dst->mount() < 0) return 1;
-
- // objects
- hash_map<hobject_t, coll_t> did_object;
-
- // collections
- vector<coll_t> collections;
-
- int ret = src->list_collections(collections);
- if (ret < 0) {
- cerr << "Error " << ret << " while listing collections" << std::endl;
- return 1;
- }
-
- int num = collections.size();
- cout << num << " collections" << std::endl;
- int i = 1;
- for (vector<coll_t>::iterator p = collections.begin();
- p != collections.end();
- ++p) {
- cout << "collection " << i++ << "/" << num << " " << hex << *p << dec << std::endl;
- {
- ObjectStore::Transaction t;
- t.create_collection(*p);
- map<string,bufferptr> attrs;
- src->collection_getattrs(*p, attrs);
- t.collection_setattrs(*p, attrs);
- dst->apply_transaction(t);
- }
-
- vector<hobject_t> o;
- src->collection_list(*p, o);
- int numo = o.size();
- int j = 1;
- for (vector<hobject_t>::iterator q = o.begin(); q != o.end(); ++q) {
- ObjectStore::Transaction t;
- if (did_object.count(*q))
- t.collection_add(*p, did_object[*q], *q);
- else {
- bufferlist bl;
- src->read(*p, *q, 0, 0, bl);
- cout << "object " << j++ << "/" << numo << " " << *q << " = " << bl.length() << " bytes" << std::endl;
- t.write(*p, *q, 0, bl.length(), bl);
- map<string,bufferptr> attrs;
- src->getattrs(*p, *q, attrs);
- t.setattrs(*p, *q, attrs);
- did_object[*q] = *p;
- }
- dst->apply_transaction(t);
- }
- }
-
- src->umount();
- dst->umount();
- return 0;
-}
-
-void usage()
-{
- cerr << "usage: ceph_dupstore filestore SRC filestore DST" << std::endl;
- exit(0);
-}
-
-int main(int argc, const char **argv)
-{
- vector<const char*> args;
- argv_to_vec(argc, argv, args);
- env_to_vec(args);
-
- global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
- common_init_finish(g_ceph_context);
-
- // args
- if (args.size() != 4)
- usage();
-
- ObjectStore *src = 0, *dst = 0;
-
- if (strcmp(args[0], "filestore") == 0)
- src = new FileStore(args[1], NULL);
- else usage();
-
- if (strcmp(args[2], "filestore") == 0)
- dst = new FileStore(args[3], NULL);
- else usage();
-
- return dupstore(src, dst);
-}
+++ /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) 2012 Inktank, Inc.
-*
-* 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 <iostream>
-#include <string>
-#include <sstream>
-#include <map>
-#include <set>
-#include <boost/scoped_ptr.hpp>
-#include <errno.h>
-
-#include "include/types.h"
-#include "include/buffer.h"
-#include "common/ceph_argparse.h"
-#include "global/global_init.h"
-#include "common/debug.h"
-#include "common/config.h"
-
-#include "mon/MonitorDBStore.h"
-#include "mon/MonitorStore.h"
-
-using namespace std;
-
-class MonitorStoreConverter {
-
- boost::scoped_ptr<MonitorDBStore> db;
- boost::scoped_ptr<MonitorStore> store;
-
- set<version_t> gvs;
- version_t highest_last_pn;
- version_t highest_accepted_pn;
-
- static const int PAXOS_MAX_VERSIONS = 50;
- string MONITOR_NAME;
-
- public:
- MonitorStoreConverter(string &store_path, string &db_store_path)
- : db(0), store(0),
- highest_last_pn(0), highest_accepted_pn(0),
- MONITOR_NAME("monitor")
- {
- MonitorStore *store_ptr = new MonitorStore(store_path);
- assert(!store_ptr->mount());
- store.reset(store_ptr);
-
- MonitorDBStore *db_ptr = new MonitorDBStore(db_store_path);
- db.reset(db_ptr);
- }
-
- int convert() {
- if (db->open(std::cerr) >= 0) {
- std::cerr << "store already exists" << std::endl;
- return EEXIST;
- }
- assert(!db->create_and_open(std::cerr));
- if (db->exists("mon_convert", "on_going")) {
- std::cout << __func__ << " found a mon store in mid-convertion; abort!"
- << std::endl;
- return EEXIST;
- }
- _mark_convert_start();
- _convert_monitor();
- _convert_machines();
- _mark_convert_finish();
-
- std::cout << __func__ << " finished conversion" << std::endl;
-
- return 0;
- }
-
- bool match() {
- return true;
- }
-
- private:
-
- set<string> _get_machines_names() {
- set<string> names;
- names.insert("auth");
- names.insert("logm");
- names.insert("mdsmap");
- names.insert("monmap");
- names.insert("osdmap");
- names.insert("pgmap");
-
- return names;
- }
-
- void _mark_convert_start() {
- MonitorDBStore::Transaction tx;
- tx.put("mon_convert", "on_going", 1);
- db->apply_transaction(tx);
- }
-
- void _mark_convert_finish() {
- MonitorDBStore::Transaction tx;
- tx.erase("mon_convert", "on_going");
- db->apply_transaction(tx);
- }
-
- void _convert_monitor() {
-
- assert(store->exists_bl_ss("magic"));
- assert(store->exists_bl_ss("keyring"));
- assert(store->exists_bl_ss("feature_set"));
- assert(store->exists_bl_ss("election_epoch"));
-
- MonitorDBStore::Transaction tx;
-
- if (store->exists_bl_ss("joined")) {
- version_t joined = store->get_int("joined");
- tx.put(MONITOR_NAME, "joined", joined);
- }
-
- vector<string> keys;
- keys.push_back("magic");
- keys.push_back("feature_set");
- keys.push_back("election_epoch");
- keys.push_back("cluster_uuid");
-
- vector<string>::iterator it;
- for (it = keys.begin(); it != keys.end(); ++it) {
- if (!store->exists_bl_ss((*it).c_str()))
- continue;
-
- bufferlist bl;
- int r = store->get_bl_ss(bl, (*it).c_str(), 0);
- assert(r > 0);
- tx.put(MONITOR_NAME, *it, bl);
- }
-
- assert(!tx.empty());
- db->apply_transaction(tx);
- }
-
- void _convert_machines(string machine) {
- std::cout << __func__ << " " << machine << std::endl;
-
- version_t first_committed =
- store->get_int(machine.c_str(), "first_committed");
- version_t last_committed =
- store->get_int(machine.c_str(), "last_committed");
-
- version_t accepted_pn = store->get_int(machine.c_str(), "accepted_pn");
- version_t last_pn = store->get_int(machine.c_str(), "last_pn");
-
- if (accepted_pn > highest_accepted_pn)
- highest_accepted_pn = accepted_pn;
- if (last_pn > highest_last_pn)
- highest_last_pn = last_pn;
-
- string machine_gv(machine);
- machine_gv.append("_gv");
- bool has_gv = true;
-
- if (!store->exists_bl_ss(machine_gv.c_str())) {
- std::cerr << __func__ << " " << machine
- << " no gv dir '" << machine_gv << "'" << std::endl;
- has_gv = false;
- }
-
- for (version_t ver = first_committed; ver <= last_committed; ver++) {
- if (!store->exists_bl_sn(machine.c_str(), ver)) {
- std::cerr << __func__ << " " << machine
- << " ver " << ver << " dne" << std::endl;
- continue;
- }
-
- bufferlist bl;
- int r = store->get_bl_sn(bl, machine.c_str(), ver);
- assert(r >= 0);
- std::cout << __func__ << " " << machine
- << " ver " << ver << " bl " << bl.length() << std::endl;
-
- MonitorDBStore::Transaction tx;
- tx.put(machine, ver, bl);
- tx.put(machine, "last_committed", ver);
-
- if (has_gv && store->exists_bl_sn(machine_gv.c_str(), ver)) {
- stringstream s;
- s << ver;
- string ver_str = s.str();
-
- version_t gv = store->get_int(machine_gv.c_str(), ver_str.c_str());
- std::cerr << __func__ << " " << machine
- << " ver " << ver << " -> " << gv << std::endl;
-
- if (gvs.count(gv) == 0) {
- gvs.insert(gv);
- } else {
- std::cerr << __func__ << " " << machine
- << " gv " << gv << " already exists"
- << std::endl;
- }
-
- bufferlist tx_bl;
- tx.encode(tx_bl);
- tx.put("paxos", gv, tx_bl);
- }
- db->apply_transaction(tx);
- }
-
- version_t lc = db->get(machine, "last_committed");
- assert(lc == last_committed);
-
- MonitorDBStore::Transaction tx;
- tx.put(machine, "first_committed", first_committed);
- tx.put(machine, "last_committed", last_committed);
-
- if (store->exists_bl_ss(machine.c_str(), "latest")) {
- bufferlist latest_bl_raw;
- int r = store->get_bl_ss(latest_bl_raw, machine.c_str(), "latest");
- assert(r >= 0);
- if (!latest_bl_raw.length()) {
- std::cerr << __func__ << " machine " << machine
- << " skip latest with size 0" << std::endl;
- goto out;
- }
-
- tx.put(machine, "latest", latest_bl_raw);
-
- bufferlist::iterator lbl_it = latest_bl_raw.begin();
- bufferlist latest_bl;
- version_t latest_ver;
- ::decode(latest_ver, lbl_it);
- ::decode(latest_bl, lbl_it);
-
- std::cout << __func__ << " machine " << machine
- << " latest ver " << latest_ver << std::endl;
-
- tx.put(machine, "full_latest", latest_ver);
- stringstream os;
- os << "full_" << latest_ver;
- tx.put(machine, os.str(), latest_bl);
- }
- out:
- db->apply_transaction(tx);
- }
-
- void _convert_paxos() {
- assert(!gvs.empty());
-
- set<version_t>::reverse_iterator rit = gvs.rbegin();
- version_t highest_gv = *rit;
- version_t last_gv = highest_gv;
-
- int n = 0;
- for (; (rit != gvs.rend()) && (n < PAXOS_MAX_VERSIONS); ++rit, ++n) {
-
- version_t gv = *rit;
-
- if (last_gv == gv)
- continue;
-
- if ((last_gv - gv) > 1) {
- // we are done; we found a gap and we are only interested in keeping
- // contiguous paxos versions.
- break;
- }
- last_gv = gv;
- }
-
- // erase all paxos versions between [first, last_gv[, with first being the
- // first gv in the map.
- MonitorDBStore::Transaction tx;
- set<version_t>::iterator it = gvs.begin();
- std::cout << __func__ << " first gv " << (*it)
- << " last gv " << last_gv << std::endl;
- for (; it != gvs.end() && (*it < last_gv); ++it) {
- tx.erase("paxos", *it);
- }
- tx.put("paxos", "first_committed", last_gv);
- tx.put("paxos", "last_committed", highest_gv);
- tx.put("paxos", "accepted_pn", highest_accepted_pn);
- tx.put("paxos", "last_pn", highest_last_pn);
- db->apply_transaction(tx);
- }
-
- void _convert_machines() {
-
- set<string> machine_names = _get_machines_names();
- set<string>::iterator it = machine_names.begin();
-
- std::cout << __func__ << std::endl;
-
- for (; it != machine_names.end(); ++it) {
- _convert_machines(*it);
- }
-
- _convert_paxos();
- }
-};
-
-
-void usage(const char *pname)
-{
- std::cerr << "Usage: " << pname << " <old store path>\n"
- << std::endl;
-}
-
-int main(int argc, const char *argv[])
-{
- vector<const char*> def_args;
- vector<const char*> args;
- const char *our_name = argv[0];
- argv_to_vec(argc, argv, args);
-
- global_init(&def_args, args,
- CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
- CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
- common_init_finish(g_ceph_context);
- g_ceph_context->_conf->apply_changes(NULL);
-
- if (args.empty()) {
- usage(our_name);
- return 1;
- }
- string store(args[0]);
- string new_store(store);
- MonitorStoreConverter converter(store, new_store);
- assert(!converter.convert());
- assert(converter.match());
-
- std::cout << "store successfully converted to new format" << std::endl;
-
- return 0;
-}
+++ /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) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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 <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <iostream>
-#include <string>
-using namespace std;
-
-#include "common/config.h"
-#include "common/ceph_argparse.h"
-#include "global/global_init.h"
-#include "mon/MonMap.h"
-#include "include/str_list.h"
-
-void usage()
-{
- cout << " usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] <mapfilename>" << std::endl;
- exit(1);
-}
-
-int main(int argc, const char **argv)
-{
- vector<const char*> args;
- argv_to_vec(argc, argv, args);
-
- const char *me = argv[0];
-
- std::string fn;
- bool print = false;
- bool create = false;
- bool clobber = false;
- bool modified = false;
- bool generate = false;
- bool filter = false;
- map<string,entity_addr_t> add;
- list<string> rm;
-
- global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
- CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
- common_init_finish(g_ceph_context);
- std::string val;
- for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
- if (ceph_argparse_double_dash(args, i)) {
- break;
- } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
- usage();
- } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) {
- print = true;
- } else if (ceph_argparse_flag(args, i, "--create", (char*)NULL)) {
- create = true;
- } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) {
- clobber = true;
- } else if (ceph_argparse_flag(args, i, "--generate", (char*)NULL)) {
- generate = true;
- } else if (ceph_argparse_flag(args, i, "--set-initial-members", (char*)NULL)) {
- filter = true;
- } else if (ceph_argparse_flag(args, i, "--add", (char*)NULL)) {
- string name = *i;
- i = args.erase(i);
- if (i == args.end())
- usage();
- entity_addr_t addr;
- if (!addr.parse(*i)) {
- cerr << me << ": invalid ip:port '" << *i << "'" << std::endl;
- return -1;
- }
- if (addr.get_port() == 0)
- addr.set_port(CEPH_MON_PORT);
- add[name] = addr;
- modified = true;
- i = args.erase(i);
- } else if (ceph_argparse_witharg(args, i, &val, "--rm", (char*)NULL)) {
- rm.push_back(val);
- modified = true;
- } else {
- ++i;
- }
- }
- if (args.empty()) {
- cerr << me << ": must specify monmap filename" << std::endl;
- usage();
- }
- else if (args.size() > 1) {
- cerr << me << ": too many arguments" << std::endl;
- usage();
- }
- fn = args[0];
-
- MonMap monmap;
-
- cout << me << ": monmap file " << fn << std::endl;
-
- int r = 0;
- if (!(create && clobber)) {
- try {
- r = monmap.read(fn.c_str());
- } catch (...) {
- cerr << me << ": unable to read monmap file" << std::endl;
- return -1;
- }
- }
-
- char buf[80];
- if (!create && r < 0) {
- cerr << me << ": couldn't open " << fn << ": " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
- return -1;
- }
- else if (create && !clobber && r == 0) {
- cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
- return -1;
- }
-
- if (create) {
- monmap.epoch = 0;
- monmap.created = ceph_clock_now(g_ceph_context);
- monmap.last_changed = monmap.created;
- srand(getpid() + time(0));
- if (g_conf->fsid.is_zero()) {
- monmap.generate_fsid();
- cout << me << ": generated fsid " << monmap.fsid << std::endl;
- }
- modified = true;
- }
-
- if (generate) {
- int r = monmap.build_initial(g_ceph_context, cerr);
- if (r < 0)
- return r;
- }
-
- if (filter) {
- // apply initial members
- list<string> initial_members;
- get_str_list(g_conf->mon_initial_members, initial_members);
- if (!initial_members.empty()) {
- cout << "initial_members " << initial_members << ", filtering seed monmap" << std::endl;
- set<entity_addr_t> removed;
- monmap.set_initial_members(g_ceph_context, initial_members,
- string(), entity_addr_t(),
- &removed);
- cout << "removed " << removed << std::endl;
- }
- modified = true;
- }
-
- if (!g_conf->fsid.is_zero()) {
- monmap.fsid = g_conf->fsid;
- cout << me << ": set fsid to " << monmap.fsid << std::endl;
- modified = true;
- }
-
- for (map<string,entity_addr_t>::iterator p = add.begin(); p != add.end(); ++p) {
- if (monmap.contains(p->first)) {
- cerr << me << ": map already contains mon." << p->first << std::endl;
- usage();
- }
- if (monmap.contains(p->second)) {
- cerr << me << ": map already contains " << p->second << std::endl;
- usage();
- }
- monmap.add(p->first, p->second);
- }
- for (list<string>::iterator p = rm.begin(); p != rm.end(); ++p) {
- cout << me << ": removing " << *p << std::endl;
- if (!monmap.contains(*p)) {
- cerr << me << ": map does not contain " << *p << std::endl;
- usage();
- }
- monmap.remove(*p);
- }
-
- if (!print && !modified)
- usage();
-
- if (print)
- monmap.print(cout);
-
- if (modified) {
- // write it out
- cout << me << ": writing epoch " << monmap.epoch
- << " to " << fn
- << " (" << monmap.size() << " monitors)"
- << std::endl;
- int r = monmap.write(fn.c_str());
- if (r < 0) {
- cerr << "monmaptool: error writing to '" << fn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
- return 1;
- }
- }
-
-
- return 0;
-}
+++ /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) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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 <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <iostream>
-#include <string>
-using namespace std;
-
-#include "common/config.h"
-
-#include "common/errno.h"
-#include "osd/OSDMap.h"
-#include "mon/MonMap.h"
-#include "common/ceph_argparse.h"
-#include "global/global_init.h"
-
-void usage()
-{
- cout << " usage: [--print] [--createsimple <numosd> [--clobber] [--pg_bits <bitsperosd>]] <mapfilename>" << std::endl;
- cout << " --export-crush <file> write osdmap's crush map to <file>" << std::endl;
- cout << " --import-crush <file> replace osdmap's crush map with <file>" << std::endl;
- cout << " --test-map-pg <pgid> map a pgid to osds" << std::endl;
- cout << " --test-map-object <objectname> [--pool <poolid>] map an object to osds"
- << std::endl;
- exit(1);
-}
-
-int main(int argc, const char **argv)
-{
- vector<const char*> args;
- argv_to_vec(argc, argv, args);
- env_to_vec(args);
-
- global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
- CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
- common_init_finish(g_ceph_context);
-
- const char *me = argv[0];
-
- std::string fn;
- bool print = false;
- bool print_json = false;
- bool tree = false;
- bool createsimple = false;
- bool create_from_conf = false;
- int num_osd = 0;
- int pg_bits = g_conf->osd_pg_bits;
- int pgp_bits = g_conf->osd_pgp_bits;
- bool clobber = false;
- bool modified = false;
- std::string export_crush, import_crush, test_map_pg, test_map_object;
- bool test_crush = false;
- int range_first = -1;
- int range_last = -1;
- int pool = 0;
-
- std::string val;
- std::ostringstream err;
- for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
- if (ceph_argparse_double_dash(args, i)) {
- break;
- } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
- usage();
- } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) {
- print = true;
- } else if (ceph_argparse_flag(args, i, "--dump-json", (char*)NULL)) {
- print_json = true;
- } else if (ceph_argparse_flag(args, i, "--tree", (char*)NULL)) {
- tree = true;
- } else if (ceph_argparse_withint(args, i, &num_osd, &err, "--createsimple", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- createsimple = true;
- } else if (ceph_argparse_flag(args, i, "--create-from-conf", (char*)NULL)) {
- create_from_conf = true;
- } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) {
- clobber = true;
- } else if (ceph_argparse_withint(args, i, &pg_bits, &err, "--pg_bits", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- } else if (ceph_argparse_withint(args, i, &pgp_bits, &err, "--pgp_bits", (char*)NULL)) {
- if (!err.str().empty()) {
- cerr << err.str() << std::endl;
- exit(EXIT_FAILURE);
- }
- } else if (ceph_argparse_witharg(args, i, &val, "--export_crush", (char*)NULL)) {
- export_crush = val;
- } else if (ceph_argparse_witharg(args, i, &val, "--import_crush", (char*)NULL)) {
- import_crush = val;
- } else if (ceph_argparse_witharg(args, i, &val, "--test_map_pg", (char*)NULL)) {
- test_map_pg = val;
- } else if (ceph_argparse_witharg(args, i, &val, "--test_map_object", (char*)NULL)) {
- test_map_object = val;
- } else if (ceph_argparse_flag(args, i, "--test_crush", (char*)NULL)) {
- test_crush = true;
- } else if (ceph_argparse_withint(args, i, &range_first, &err, "--range_first", (char*)NULL)) {
- } else if (ceph_argparse_withint(args, i, &range_last, &err, "--range_last", (char*)NULL)) {
- } else if (ceph_argparse_withint(args, i, &pool, &err, "--pool", (char*)NULL)) {
- } else {
- ++i;
- }
- }
- if (args.empty()) {
- cerr << me << ": must specify osdmap filename" << std::endl;
- usage();
- }
- else if (args.size() > 1) {
- cerr << me << ": too many arguments" << std::endl;
- usage();
- }
- fn = args[0];
-
- if (range_first >= 0 && range_last >= 0) {
- set<OSDMap*> maps;
- OSDMap *prev = NULL;
- for (int i=range_first; i <= range_last; i++) {
- ostringstream f;
- f << fn << "/" << i;
- bufferlist bl;
- string error, s = f.str();
- int r = bl.read_file(s.c_str(), &error);
- if (r < 0) {
- cerr << "unable to read " << s << ": " << cpp_strerror(r) << std::endl;
- exit(1);
- }
- cout << s << " got " << bl.length() << " bytes" << std::endl;
- OSDMap *o = new OSDMap;
- o->decode(bl);
- maps.insert(o);
- if (prev)
- OSDMap::dedup(prev, o);
- prev = o;
- }
- exit(0);
- }
-
- OSDMap osdmap;
- bufferlist bl;
-
- cout << me << ": osdmap file '" << fn << "'" << std::endl;
-
- int r = 0;
- struct stat st;
- if (!createsimple && !create_from_conf && !clobber) {
- std::string error;
- r = bl.read_file(fn.c_str(), &error);
- if (r == 0) {
- try {
- osdmap.decode(bl);
- }
- catch (const buffer::error &e) {
- cerr << me << ": error decoding osdmap '" << fn << "'" << std::endl;
- return -1;
- }
- }
- else {
- cerr << me << ": couldn't open " << fn << ": " << error << std::endl;
- return -1;
- }
- }
- else if ((createsimple || create_from_conf) && !clobber && ::stat(fn.c_str(), &st) == 0) {
- cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
- return -1;
- }
-
- if (createsimple) {
- if (num_osd < 1) {
- cerr << me << ": osd count must be > 0" << std::endl;
- exit(1);
- }
- uuid_d fsid;
- memset(&fsid, 0, sizeof(uuid_d));
- osdmap.build_simple(g_ceph_context, 0, fsid, num_osd, pg_bits, pgp_bits);
- modified = true;
- }
- if (create_from_conf) {
- uuid_d fsid;
- memset(&fsid, 0, sizeof(uuid_d));
- int r = osdmap.build_simple_from_conf(g_ceph_context, 0, fsid, pg_bits, pgp_bits);
- if (r < 0)
- return -1;
- modified = true;
- }
-
- if (!import_crush.empty()) {
- bufferlist cbl;
- std::string error;
- r = cbl.read_file(import_crush.c_str(), &error);
- if (r) {
- cerr << me << ": error reading crush map from " << import_crush
- << ": " << error << std::endl;
- exit(1);
- }
-
- // validate
- CrushWrapper cw;
- bufferlist::iterator p = cbl.begin();
- cw.decode(p);
-
- if (cw.get_max_devices() > osdmap.get_max_osd()) {
- cerr << me << ": crushmap max_devices " << cw.get_max_devices()
- << " > osdmap max_osd " << osdmap.get_max_osd() << std::endl;
- exit(1);
- }
-
- // apply
- OSDMap::Incremental inc;
- inc.fsid = osdmap.get_fsid();
- inc.epoch = osdmap.get_epoch()+1;
- inc.crush = cbl;
- osdmap.apply_incremental(inc);
- cout << me << ": imported " << cbl.length() << " byte crush map from " << import_crush << std::endl;
- modified = true;
- }
-
- if (!export_crush.empty()) {
- bufferlist cbl;
- osdmap.crush->encode(cbl);
- r = cbl.write_file(export_crush.c_str());
- if (r < 0) {
- cerr << me << ": error writing crush map to " << import_crush << std::endl;
- exit(1);
- }
- cout << me << ": exported crush map to " << export_crush << std::endl;
- }
-
- if (!test_map_object.empty()) {
- object_t oid(test_map_object);
- if (!osdmap.have_pg_pool(pool)) {
- cerr << "There is no pool " << pool << std::endl;
- exit(1);
- }
- object_locator_t loc(pool);
- pg_t raw_pgid = osdmap.object_locator_to_pg(oid, loc);
- pg_t pgid = osdmap.raw_pg_to_pg(raw_pgid);
-
- vector<int> acting;
- osdmap.pg_to_acting_osds(pgid, acting);
- cout << " object '" << oid
- << "' -> " << pgid
- << " -> " << acting
- << std::endl;
- }
- if (!test_map_pg.empty()) {
- pg_t pgid;
- if (!pgid.parse(test_map_pg.c_str())) {
- cerr << me << ": failed to parse pg '" << test_map_pg
- << "', r = " << r << std::endl;
- usage();
- }
- cout << " parsed '" << test_map_pg << "' -> " << pgid << std::endl;
-
- vector<int> raw, up, acting;
- osdmap.pg_to_osds(pgid, raw);
- osdmap.pg_to_up_acting_osds(pgid, up, acting);
- cout << pgid << " raw " << raw << " up " << up << " acting " << acting << std::endl;
- }
- if (test_crush) {
- int pass = 0;
- while (1) {
- cout << "pass " << ++pass << std::endl;
-
- hash_map<pg_t,vector<int> > m;
- for (map<int64_t,pg_pool_t>::const_iterator p = osdmap.get_pools().begin();
- p != osdmap.get_pools().end();
- ++p) {
- const pg_pool_t *pool = osdmap.get_pg_pool(p->first);
- for (ps_t ps = 0; ps < pool->get_pg_num(); ps++) {
- pg_t pgid(ps, p->first, -1);
- for (int i=0; i<100; i++) {
- cout << pgid << " attempt " << i << std::endl;
-
- vector<int> r;
- osdmap.pg_to_acting_osds(pgid, r);
- //cout << pgid << " " << r << std::endl;
- if (m.count(pgid)) {
- if (m[pgid] != r) {
- cout << pgid << " had " << m[pgid] << " now " << r << std::endl;
- assert(0);
- }
- } else
- m[pgid] = r;
- }
- }
- }
- }
- }
-
- if (!print && !print_json && !tree && !modified &&
- export_crush.empty() && import_crush.empty() &&
- test_map_pg.empty() && test_map_object.empty()) {
- cerr << me << ": no action specified?" << std::endl;
- usage();
- }
-
- if (modified)
- osdmap.inc_epoch();
-
- if (print)
- osdmap.print(cout);
- if (print_json)
- osdmap.dump_json(cout);
- if (tree)
- osdmap.print_tree(&cout, NULL);
-
- if (modified) {
- bl.clear();
- osdmap.encode(bl);
-
- // write it out
- cout << me << ": writing epoch " << osdmap.get_epoch()
- << " to " << fn
- << std::endl;
- int r = bl.write_file(fn.c_str());
- if (r) {
- cerr << "osdmaptool: error writing to '" << fn << "': "
- << cpp_strerror(r) << std::endl;
- return 1;
- }
- }
-
-
- return 0;
-}
+++ /dev/null
-
-#include <iostream>
-
-#include "crush/CrushWrapper.h"
-#include "osd/OSDMap.h"
-#include "common/config.h"
-#include "include/buffer.h"
-
-int main(int argc, char **argv)
-{
- /*
- * you need to create a suitable osdmap first. e.g., for 40 osds,
- * $ ./osdmaptool --createsimple 40 --clobber .ceph_osdmap
- */
- bufferlist bl;
- std::string error;
- if (bl.read_file(".ceph_osdmap", &error)) {
- cout << argv[0] << ": error reading .ceph_osdmap: " << error << std::endl;
- return 1;
- }
- OSDMap osdmap;
- osdmap.decode(bl);
-
- int n = osdmap.get_max_osd();
- int count[n];
- for (int i=0; i<n; i++) {
- osdmap.set_state(i, osdmap.get_state(i) | CEPH_OSD_UP);
- //if (i<8)
- osdmap.set_weight(i, CEPH_OSD_IN);
- count[i] = 0;
- }
-
- int size[4];
- for (int i=0; i<4; i++)
- size[i] = 0;
-
- for (int n = 0; n < 10; n++) { // namespaces
- char nspace[20];
- snprintf(nspace, sizeof(nspace), "n%d", n);
- for (int f = 0; f < 5000; f++) { // files
- for (int b = 0; b < 4; b++) { // blocks
- char foo[20];
- snprintf(foo, sizeof(foo), "%d.%d", f, b);
- object_t oid(foo);
- ceph_object_layout l = osdmap.make_object_layout(oid, 0, nspace);
- //osdmap.file_to_object_layout(oid, g_default_file_layout);
- vector<int> osds;
- pg_t pgid = pg_t(l.ol_pgid);
- //pgid.u.ps = f * 4 + b;
- osdmap.pg_to_osds(pgid, osds);
- size[osds.size()]++;
-#if 0
- if (0) {
- hash<object_t> H;
- int x = H(oid);
- x = ceph_stable_mod(x, 1023, 1023);
- int s = crush_hash32(x) % 15;
- //cout << "ceph_psim: x = " << x << " s = " << s << std::endl;
- //osds[0] = s;
- }
-#endif
- //osds[0] = crush_hash32(f) % n;
- //cout << "oid " << oid << " pgid " << pgid << " on " << osds << std::endl;
- for (unsigned i=0; i<osds.size(); i++) {
- //cout << " rep " << i << " on " << osds[i] << std::endl;
- count[osds[i]]++;
- }
- }
- }
- }
-
- uint64_t avg = 0;
- for (int i=0; i<n; i++) {
- cout << "osd." << i << "\t" << count[i] << std::endl;
- avg += count[i];
- }
- avg /= n;
- double dev = 0;
- for (int i=0; i<n; i++)
- dev += (avg - count[i]) * (avg - count[i]);
- dev /= n;
- dev = sqrt(dev);
-
- double pgavg = (double)osdmap.get_pg_pool(0)->get_pg_num() / (double)n;
- double edev = sqrt(pgavg) * (double)avg / pgavg;
- cout << " avg " << avg
- << " stddev " << dev
- << " (expected " << edev << ")"
- << " (indep object placement would be " << sqrt(avg) << ")" << std::endl;
-
- for (int i=0; i<4; i++) {
- cout << "size" << i << "\t" << size[i] << std::endl;
- }
-
- return 0;
-}
+++ /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) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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/types.h"
-#include "include/rados/librados.hpp"
-using namespace librados;
-
-#include <iostream>
-
-#include <stdlib.h>
-#include <time.h>
-#include <errno.h>
-
-void buf_to_hex(const unsigned char *buf, int len, char *str)
-{
- str[0] = '\0';
- for (int i = 0; i < len; i++) {
- sprintf(&str[i*2], "%02x", (int)buf[i]);
- }
-}
-
-
-#define ID_SIZE 8
-
-#define ACL_RD 0x1
-#define ACL_WR 0x2
-
-struct ACLID {
- char id[ID_SIZE + 1];
-
- void encode(bufferlist& bl) const {
- bl.append((const char *)id, ID_SIZE);
- }
- void decode(bufferlist::iterator& iter) {
- iter.copy(ID_SIZE, (char *)id);
- }
-};
-WRITE_CLASS_ENCODER(ACLID)
-
-typedef __u32 ACLFlags;
-
-
-inline bool operator<(const ACLID& l, const ACLID& r)
-{
- return (memcmp(&l, &r, ID_SIZE) > 0);
-}
-
-struct ACLPair {
- ACLID id;
- ACLFlags flags;
-};
-
-class ObjectACLs {
- map<ACLID, ACLFlags> acls_map;
-
-public:
-
- void encode(bufferlist& bl) const {
- ::encode(acls_map, bl);
- }
- void decode(bufferlist::iterator& bl) {
- ::decode(acls_map, bl);
- }
-
- int read_acl(ACLID& id, ACLFlags *flags);
- void set_acl(ACLID& id, ACLFlags flags);
-};
-WRITE_CLASS_ENCODER(ObjectACLs)
-
-int ObjectACLs::read_acl(ACLID& id, ACLFlags *flags)
-{
- if (!flags)
- return -EINVAL;
-
- map<ACLID, ACLFlags>::iterator iter = acls_map.find(id);
-
- if (iter == acls_map.end())
- return -ENOENT;
-
- *flags = iter->second;
-
- return 0;
-}
-
-void ObjectACLs::set_acl(ACLID& id, ACLFlags flags)
-{
- acls_map[id] = flags;
-}
-
-
-
-class ACLEntity
-{
- string name;
- map<ACLID, ACLEntity> groups;
-};
-
-typedef map<ACLID, ACLEntity> tACLIDEntityMap;
-
-static map<ACLID, ACLEntity> users;
-static map<ACLID, ACLEntity> groups;
-
-void get_user(ACLID& aclid, ACLEntity *entity)
-{
- //users.find(aclid);
-}
-
-
-
-
-
-int main(int argc, const char **argv)
-{
- Rados rados;
- if (rados.init(NULL) < 0) {
- cerr << "couldn't initialize rados!" << std::endl;
- exit(1);
- }
- if (rados.conf_read_file(NULL)) {
- cerr << "couldn't read Ceph configuration file!" << std::endl;
- exit(1);
- }
- if (rados.connect() < 0) {
- cerr << "couldn't connect to cluster!" << std::endl;
- exit(1);
- }
-
- time_t tm;
- bufferlist bl, bl2;
- char buf[128];
-
- time(&tm);
- snprintf(buf, 128, "%s", ctime(&tm));
- bl.append(buf, strlen(buf));
-
- const char *oid = "bar";
-
- IoCtx io_ctx;
- int r = rados.ioctx_create("data", io_ctx);
- cout << "open io_ctx result = " << r << " pool = " << io_ctx.get_pool_name() << std::endl;
-
- ACLID id;
-
- snprintf(id.id, ID_SIZE + 1, "%.16x", 0x1234);
- cout << "id=" << id.id << std::endl;
-
- r = io_ctx.exec(oid, "acl", "get", bl, bl2);
- cout << "exec returned " << r << " len=" << bl2.length() << std::endl;
- ObjectACLs oa;
- if (r >= 0) {
- bufferlist::iterator iter = bl2.begin();
- oa.decode(iter);
- }
-
- oa.set_acl(id, ACL_RD);
- bl.clear();
- oa.encode(bl);
- r = io_ctx.exec(oid, "acl", "set", bl, bl2);
-
- const unsigned char *md5 = (const unsigned char *)bl2.c_str();
- char md5_str[bl2.length()*2 + 1];
- buf_to_hex(md5, bl2.length(), md5_str);
- cout << "md5 result=" << md5_str << std::endl;
-
- int size = io_ctx.read(oid, bl2, 128, 0);
- cout << "read result=" << bl2.c_str() << std::endl;
- cout << "size=" << size << std::endl;
-
-#if 0
- Rados::ListCtx ctx;
- int entries;
- do {
- list<object_t> vec;
- r = rados.list(io_ctx, 2, vec, ctx);
- entries = vec.size();
- cout << "list result=" << r << " entries=" << entries << std::endl;
- list<object_t>::iterator iter;
- for (iter = vec.begin(); iter != vec.end(); ++iter) {
- cout << *iter << std::endl;
- }
- } while (entries);
-#endif
-#if 0
- r = rados.remove(io_ctx, oid);
- cout << "remove result=" << r << std::endl;
- rados.close_io_ctx(io_ctx);
-#endif
-
- return 0;
-}
-
+++ /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) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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.h"
-
-#include <assert.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-static int do_rados_setxattr(rados_ioctx_t io_ctx, const char *oid,
- const char *key, const char *val)
-{
- int ret = rados_setxattr(io_ctx, oid, key, val, strlen(val) + 1);
- if (ret < 0) {
- printf("rados_setxattr failed with error %d\n", ret);
- return 1;
- }
- printf("rados_setxattr %s=%s\n", key, val);
- return 0;
-}
-
-static int do_rados_getxattr(rados_ioctx_t io_ctx, const char *oid,
- const char *key, const char *expected)
-{
- size_t blen = strlen(expected) + 1;
- char buf[blen];
- memset(buf, 0, sizeof(buf));
- int r = rados_getxattr(io_ctx, oid, key, buf, blen);
- if (r < 0) {
- printf("rados_getxattr(%s) failed with error %d\n", key, r);
- return 1;
- }
- if (strcmp(buf, expected) != 0) {
- printf("rados_getxattr(%s) got wrong result! "
- "expected: '%s'. got '%s'\n", key, expected, buf);
- return 1;
- }
- printf("rados_getxattr %s=%s\n", key, buf);
- return 0;
-}
-
-static int do_rados_getxattrs(rados_ioctx_t io_ctx, const char *oid,
- const char **exkeys, const char **exvals)
-{
- rados_xattrs_iter_t iter;
- int nval = 0, i, nfound = 0, ret = 0;
-
- for (i = 0; exvals[i]; ++i) {
- ++nval;
- }
- ret = rados_getxattrs(io_ctx, oid, &iter);
- if (ret) {
- printf("rados_getxattrs(%s) failed with error %d\n", oid, ret);
- return 1;
- }
- while (1) {
- size_t len;
- const char *key, *val;
- ret = rados_getxattrs_next(iter, &key, &val, &len);
- if (ret) {
- printf("rados_getxattrs(%s): rados_getxattrs_next "
- "returned error %d\n", oid, ret);
- return 1;
- }
- if (!key)
- break;
- for (i = 0; i < nval; ++i) {
- if (strcmp(exkeys[i], key))
- continue;
- if ((len == strlen(exvals[i]) + 1) && (!strcmp(exvals[i], val))) {
- nfound++;
- break;
- }
- printf("rados_getxattrs(%s): got key %s, but the "
- "value was %s rather than %s.\n",
- oid, key, val, exvals[i]);
- return 1;
- }
- }
- if (nfound != nval) {
- printf("rados_getxattrs(%s): only found %d extended attributes. "
- "Expected %d\n", oid, nfound, nval);
- return 1;
- }
- rados_getxattrs_end(iter);
- printf("rados_getxattrs(%s)\n", oid);
- return 0;
-}
-
-static int testrados(void)
-{
- char tmp[32];
- int i, r;
- int ret = 1; //set 1 as error case
- rados_t cl;
-
- if (rados_create(&cl, NULL) < 0) {
- printf("error initializing\n");
- return 1;
- }
-
- if (rados_conf_read_file(cl, NULL)) {
- printf("error reading configuration file\n");
- goto out_err;
- }
-
- // Try to set a configuration option that doesn't exist.
- // This should fail.
- if (!rados_conf_set(cl, "config option that doesn't exist",
- "some random value")) {
- printf("error: succeeded in setting nonexistent config option\n");
- goto out_err;
- }
-
- if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
- printf("error: failed to read log_to_stderr from config\n");
- goto out_err;
- }
-
- // Can we change it?
- if (rados_conf_set(cl, "log to stderr", "true")) {
- printf("error: error setting log_to_stderr\n");
- goto out_err;
- }
- if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
- printf("error: failed to read log_to_stderr from config\n");
- goto out_err;
- }
- if (strcmp(tmp, "true")) {
- printf("error: new setting for log_to_stderr failed to take effect.\n");
- goto out_err;
- }
-
- if (rados_connect(cl)) {
- printf("error connecting\n");
- goto out_err;
- }
- if (rados_connect(cl) == 0) {
- printf("second connect attempt didn't return an error\n");
- goto out_err;
- }
-
- /* create an io_ctx */
- r = rados_pool_create(cl, "foo");
- printf("rados_pool_create = %d\n", r);
-
- rados_ioctx_t io_ctx;
- r = rados_ioctx_create(cl, "foo", &io_ctx);
- printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx);
-
- /* list all pools */
- {
- int buf_sz = rados_pool_list(cl, NULL, 0);
- printf("need buffer size of %d\n", buf_sz);
- char buf[buf_sz];
- int r = rados_pool_list(cl, buf, buf_sz);
- if (r != buf_sz) {
- printf("buffer size mismatch: got %d the first time, but %d "
- "the second.\n", buf_sz, r);
- goto out_err;
- }
- const char *b = buf;
- printf("begin pools.\n");
- while (1) {
- if (b[0] == '\0')
- break;
- printf(" pool: '%s'\n", b);
- b += strlen(b) + 1;
- };
- printf("end pools.\n");
- }
-
-
- /* stat */
- struct rados_pool_stat_t st;
- r = rados_ioctx_pool_stat(io_ctx, &st);
- printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
-
- /* snapshots */
- r = rados_ioctx_snap_create(io_ctx, "snap1");
- printf("rados_ioctx_snap_create snap1 = %d\n", r);
- rados_snap_t snaps[10];
- r = rados_ioctx_snap_list(io_ctx, snaps, 10);
- for (i=0; i<r; i++) {
- char name[100];
- rados_ioctx_snap_get_name(io_ctx, snaps[i], name, sizeof(name));
- printf("rados_ioctx_snap_list got snap %lld %s\n", (long long)snaps[i], name);
- }
- rados_snap_t snapid;
- r = rados_ioctx_snap_lookup(io_ctx, "snap1", &snapid);
- printf("rados_ioctx_snap_lookup snap1 got %lld, result %d\n", (long long)snapid, r);
- r = rados_ioctx_snap_remove(io_ctx, "snap1");
- printf("rados_ioctx_snap_remove snap1 = %d\n", r);
-
- /* sync io */
- time_t tm;
- char buf[128], buf2[128];
- time(&tm);
- snprintf(buf, 128, "%s", ctime(&tm));
- const char *oid = "foo_object";
- r = rados_write(io_ctx, oid, buf, strlen(buf) + 1, 0);
- printf("rados_write = %d\n", r);
- r = rados_read(io_ctx, oid, buf2, sizeof(buf2), 0);
- printf("rados_read = %d\n", r);
- if (memcmp(buf, buf2, r))
- printf("*** content mismatch ***\n");
-
- /* attrs */
- if (do_rados_setxattr(io_ctx, oid, "b", "2"))
- goto out_err;
- if (do_rados_setxattr(io_ctx, oid, "a", "1"))
- goto out_err;
- if (do_rados_setxattr(io_ctx, oid, "c", "3"))
- goto out_err;
- if (do_rados_getxattr(io_ctx, oid, "a", "1"))
- goto out_err;
- if (do_rados_getxattr(io_ctx, oid, "b", "2"))
- goto out_err;
- if (do_rados_getxattr(io_ctx, oid, "c", "3"))
- goto out_err;
- const char *exkeys[] = { "a", "b", "c", NULL };
- const char *exvals[] = { "1", "2", "3", NULL };
- if (do_rados_getxattrs(io_ctx, oid, exkeys, exvals))
- goto out_err;
-
- uint64_t size;
- time_t mtime;
- r = rados_stat(io_ctx, oid, &size, &mtime);
- printf("rados_stat size = %lld mtime = %d = %d\n", (long long)size, (int)mtime, r);
- r = rados_stat(io_ctx, "does_not_exist", NULL, NULL);
- printf("rados_stat(does_not_exist) = %d\n", r);
-
- /* exec */
- rados_exec(io_ctx, oid, "crypto", "md5", buf, strlen(buf) + 1, buf, 128);
- printf("exec result=%s\n", buf);
- r = rados_read(io_ctx, oid, buf2, 128, 0);
- printf("read result=%s\n", buf2);
- printf("size=%d\n", r);
-
- /* aio */
- rados_completion_t a, b;
- rados_aio_create_completion(0, 0, 0, &a);
- rados_aio_create_completion(0, 0, 0, &b);
- rados_aio_write(io_ctx, "a", a, buf, 100, 0);
- rados_aio_write(io_ctx, "../b/bb_bb_bb\\foo\\bar", b, buf, 100, 0);
- rados_aio_wait_for_safe(a);
- printf("a safe\n");
- rados_aio_wait_for_safe(b);
- printf("b safe\n");
- rados_aio_release(a);
- rados_aio_release(b);
-
- /* test flush */
- printf("testing aio flush\n");
- rados_completion_t c;
- rados_aio_create_completion(0, 0, 0, &c);
- rados_aio_write(io_ctx, "c", c, buf, 100, 0);
- int safe = rados_aio_is_safe(c);
- printf("a should not yet be safe and ... %s\n", safe ? "is":"is not");
- assert(!safe);
- rados_aio_flush(io_ctx);
- safe = rados_aio_is_safe(c);
- printf("a should be safe and ... %s\n", safe ? "is":"is not");
- assert(safe);
- rados_aio_release(c);
-
- rados_read(io_ctx, "../b/bb_bb_bb\\foo\\bar", buf2, 128, 0);
-
- /* list objects */
- rados_list_ctx_t h;
- r = rados_objects_list_open(io_ctx, &h);
- printf("rados_list_objects_open = %d, h = %p\n", r, h);
- const char *poolname;
- while (rados_objects_list_next(h, &poolname, NULL) == 0)
- printf("rados_list_objects_next got object '%s'\n", poolname);
- rados_objects_list_close(h);
-
- /* stat */
- r = rados_ioctx_pool_stat(io_ctx, &st);
- printf("rados_stat_pool = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
-
- /* delete a pool */
- printf("rados_delete_pool = %d\n", r);
- rados_ioctx_destroy(io_ctx);
-
- r = rados_pool_delete(cl, "foo");
- printf("rados_ioctx_pool_delete = %d\n", r);
-
- ret = 0;
-out_err:
- rados_shutdown(cl);
- return ret;
-}
-
-int main(int argc, const char **argv)
-{
- return testrados();
-}
+++ /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) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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/types.h"
-#include "include/rados/librados.hpp"
-
-using namespace librados;
-
-#include <iostream>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-
-void buf_to_hex(const unsigned char *buf, int len, char *str)
-{
- str[0] = '\0';
- for (int i = 0; i < len; i++) {
- sprintf(&str[i*2], "%02x", (int)buf[i]);
- }
-}
-
-class C_Watch : public WatchCtx {
-public:
- C_Watch() {}
- void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) {
- cout << "C_Watch::notify() opcode=" << (int)opcode << " ver=" << ver << std::endl;
- }
-};
-
-void testradospp_milestone(void)
-{
- cout << "*** press enter to continue ***" << std::endl;
- getchar();
-}
-
-int main(int argc, const char **argv)
-{
- Rados rados;
- if (rados.init(NULL) < 0) {
- cerr << "couldn't initialize rados!" << std::endl;
- exit(1);
- }
-
- if (rados.conf_read_file(NULL)) {
- cerr << "couldn't read configuration file." << std::endl;
- exit(1);
- }
- rados.conf_parse_argv(argc, argv);
-
- if (!rados.conf_set("config option that doesn't exist",
- "some random value")) {
- printf("error: succeeded in setting nonexistent config option\n");
- exit(1);
- }
- if (rados.conf_set("log to stderr", "true")) {
- printf("error: error setting log_to_stderr\n");
- exit(1);
- }
- std::string tmp;
- if (rados.conf_get("log to stderr", tmp)) {
- printf("error: failed to read log_to_stderr from config\n");
- exit(1);
- }
- if (tmp != "true") {
- printf("error: new setting for log_to_stderr failed to take effect.\n");
- exit(1);
- }
-
- if (rados.connect()) {
- printf("error connecting\n");
- exit(1);
- }
-
- cout << "rados_initialize completed" << std::endl;
- testradospp_milestone();
-
- time_t tm;
- bufferlist bl, bl2, blf;
- char buf[128];
-
- time(&tm);
- snprintf(buf, 128, "%s", ctime(&tm));
- bl.append(buf, strlen(buf));
- blf.append(buf, 16);
-
- const char *oid = "bar";
-
- IoCtx io_ctx;
- int r = rados.ioctx_create("data", io_ctx);
- cout << "ioctx_create result = " << r << std::endl;
-
- r = io_ctx.write(oid, bl, bl.length(), 0);
- uint64_t objver = io_ctx.get_last_version();
- assert(objver > 0);
- cout << "io_ctx.write returned " << r << " last_ver=" << objver << std::endl;
-
- uint64_t stat_size;
- time_t stat_mtime;
- r = io_ctx.stat(oid, &stat_size, &stat_mtime);
- cout << "io_ctx.stat returned " << r << " size = " << stat_size << " mtime = " << stat_mtime << std::endl;
-
- r = io_ctx.stat(oid, NULL, NULL);
- cout << "io_ctx.stat(does_not_exist) = " << r;
-
- uint64_t handle;
- C_Watch wc;
- r = io_ctx.watch(oid, objver, &handle, &wc);
- cout << "io_ctx.watch returned " << r << std::endl;
-
- testradospp_milestone();
- io_ctx.set_notify_timeout(7);
- bufferlist notify_bl;
- r = io_ctx.notify(oid, objver, notify_bl);
- cout << "io_ctx.notify returned " << r << std::endl;
- testradospp_milestone();
-
- r = io_ctx.notify(oid, objver, notify_bl);
- cout << "io_ctx.notify returned " << r << std::endl;
- testradospp_milestone();
-
- r = io_ctx.unwatch(oid, handle);
- cout << "io_ctx.unwatch returned " << r << std::endl;
- cout << "*** press enter to continue ***" << std::endl;
- testradospp_milestone();
-
- r = io_ctx.notify(oid, objver, notify_bl);
- cout << "io_ctx.notify returned " << r << std::endl;
- cout << "*** press enter to continue ***" << std::endl;
- testradospp_milestone();
- io_ctx.set_assert_version(objver);
-
- r = io_ctx.write(oid, bl, bl.length() - 1, 0);
- cout << "io_ctx.write returned " << r << std::endl;
-
- r = io_ctx.write(oid, bl, bl.length() - 2, 0);
- cout << "io_ctx.write returned " << r << std::endl;
- r = io_ctx.write(oid, bl, bl.length() - 3, 0);
- cout << "rados.write returned " << r << std::endl;
- r = io_ctx.append(oid, bl, bl.length());
- cout << "rados.write returned " << r << std::endl;
- r = io_ctx.write_full(oid, blf);
- cout << "rados.write_full returned " << r << std::endl;
- r = io_ctx.read(oid, bl, bl.length(), 0);
- cout << "rados.read returned " << r << std::endl;
- r = io_ctx.trunc(oid, 8);
- cout << "rados.trunc returned " << r << std::endl;
- r = io_ctx.read(oid, bl, bl.length(), 0);
- cout << "rados.read returned " << r << std::endl;
- r = io_ctx.exec(oid, "crypto", "md5", bl, bl2);
- cout << "exec returned " << r << " buf size=" << bl2.length() << std::endl;
- const unsigned char *md5 = (const unsigned char *)bl2.c_str();
- char md5_str[bl2.length()*2 + 1];
- buf_to_hex(md5, bl2.length(), md5_str);
- cout << "md5 result=" << md5_str << std::endl;
-
- // test assert_version
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r >= 0);
- uint64_t v = io_ctx.get_last_version();
- cout << oid << " version is " << v << std::endl;
- assert(v > 0);
- io_ctx.set_assert_version(v);
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r >= 0);
- io_ctx.set_assert_version(v - 1);
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r == -ERANGE);
- io_ctx.set_assert_version(v + 1);
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r == -EOVERFLOW);
-
- // test assert_src_version
- const char *dest = "baz";
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r >= 0);
- v = io_ctx.get_last_version();
- cout << oid << " version is " << v << std::endl;
- io_ctx.set_assert_src_version(oid, v);
- r = io_ctx.clone_range(dest, 0, oid, 0, 1);
- assert(r >= 0);
- io_ctx.set_assert_src_version(oid, v-1);
- r = io_ctx.clone_range(dest, 0, oid, 0, 1);
- assert(r == -ERANGE);
- io_ctx.set_assert_src_version(oid, v+1);
- r = io_ctx.clone_range(dest, 0, oid, 0, 1);
- assert(r == -EOVERFLOW);
-
- r = io_ctx.exec(oid, "crypto", "sha1", bl, bl2);
- cout << "exec returned " << r << std::endl;
- const unsigned char *sha1 = (const unsigned char *)bl2.c_str();
- char sha1_str[bl2.length()*2 + 1];
- buf_to_hex(sha1, bl2.length(), sha1_str);
- cout << "sha1 result=" << sha1_str << std::endl;
-
- r = io_ctx.exec(oid, "acl", "set", bl, bl2);
- cout << "exec (set) returned " << r << std::endl;
- r = io_ctx.exec(oid, "acl", "get", bl, bl2);
- cout << "exec (get) returned " << r << std::endl;
- if (bl2.length() > 0) {
- cout << "attr=" << bl2.c_str() << std::endl;
- }
-
- int size = io_ctx.read(oid, bl2, 128, 0);
- if (size <= 0) {
- cout << "failed to read oid " << oid << "." << std::endl;
- exit(1);
- }
- if (size > 4096) {
- cout << "read too many bytes from oid " << oid << "." << std::endl;
- exit(1);
- }
- char rbuf[size + 1];
- memcpy(rbuf, bl2.c_str(), size);
- rbuf[size] = '\0';
- cout << "read result='" << rbuf << "'" << std::endl;
- cout << "size=" << size << std::endl;
-
- const char *oid2 = "jjj10.rbd";
- r = io_ctx.exec(oid2, "rbd", "snap_list", bl, bl2);
- cout << "snap_list result=" << r << std::endl;
- r = io_ctx.exec(oid2, "rbd", "snap_add", bl, bl2);
- cout << "snap_add result=" << r << std::endl;
-
- if (r > 0) {
- char *s = bl2.c_str();
- for (int i=0; i<r; i++, s += strlen(s) + 1)
- cout << s << std::endl;
- }
-
- cout << "compound operation..." << std::endl;
- ObjectWriteOperation o;
- o.write(0, bl);
- o.setxattr("foo", bl2);
- r = io_ctx.operate(oid, &o);
- cout << "operate result=" << r << std::endl;
-
- cout << "cmpxattr" << std::endl;
- bufferlist val;
- val.append("foo");
- r = io_ctx.setxattr(oid, "foo", val);
- assert(r >= 0);
- {
- ObjectReadOperation o;
- o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
- r = io_ctx.operate(oid, &o, &bl2);
- cout << " got " << r << " wanted >= 0" << std::endl;
- assert(r >= 0);
- }
- val.append("...");
- {
- ObjectReadOperation o;
- o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
- r = io_ctx.operate(oid, &o, &bl2);
- cout << " got " << r << " wanted ECANCELED" << std::endl;
- assert(r == -ECANCELED);
- }
-
- cout << "src_cmpxattr" << std::endl;
- const char *oidb = "bar-clone";
- {
- ObjectWriteOperation o;
- o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
- io_ctx.locator_set_key(oid);
- o.write_full(val);
- r = io_ctx.operate(oidb, &o);
- cout << " got " << r << " wanted ECANCELED" << std::endl;
- assert(r == -ECANCELED);
- }
- {
- ObjectWriteOperation o;
- o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_NE, val);
- io_ctx.locator_set_key(oid);
- o.write_full(val);
- r = io_ctx.operate(oidb, &o);
- cout << " got " << r << " wanted >= 0" << std::endl;
- assert(r >= 0);
- }
- io_ctx.locator_set_key(string());
-
-
- cout << "iterating over objects..." << std::endl;
- int num_objs = 0;
- for (ObjectIterator iter = io_ctx.objects_begin();
- iter != io_ctx.objects_end(); ++iter) {
- num_objs++;
- cout << "'" << *iter << "'" << std::endl;
- }
- cout << "iterated over " << num_objs << " objects." << std::endl;
- map<string, bufferlist> attrset;
- io_ctx.getxattrs(oid, attrset);
-
- map<string, bufferlist>::iterator it;
- for (it = attrset.begin(); it != attrset.end(); ++it) {
- cout << "xattr: " << it->first << std::endl;
- }
-
- r = io_ctx.remove(oid);
- cout << "remove result=" << r << std::endl;
- rados.shutdown();
-
- return 0;
-}
-
--- /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) 2004-2009 Sage Weil <sage@newdream.net>
+ *
+ * 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 "common/config.h"
+#include "common/strtol.h"
+
+#include "common/ConfUtils.h"
+#include "common/ceph_argparse.h"
+#include "global/global_context.h"
+#include "global/global_init.h"
+#include "auth/Crypto.h"
+#include "auth/Auth.h"
+#include "auth/KeyRing.h"
+
+#include <sstream>
+
+void usage()
+{
+ cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n"
+ << "where the options are:\n"
+ << " -l, --list will list all keys and capabilities present in\n"
+ << " the keyring\n"
+ << " -p, --print-key will print an encoded key for the specified\n"
+ << " entityname. This is suitable for the\n"
+ << " 'mount -o secret=..' argument\n"
+ << " -C, --create-keyring will create a new keyring, overwriting any\n"
+ << " existing keyringfile\n"
+ << " -g, --gen-key will generate a new secret key for the\n"
+ << " specified entityname\n"
+ << " --gen-print-key will generate a new secret key without set it\n"
+ << " to the keyringfile, prints the secret to stdout\n"
+ << " --import-keyring will import the content of a given keyring\n"
+ << " into the keyringfile\n"
+ << " -u, --set-uid sets the auid (authenticated user id) for the\n"
+ << " specified entityname\n"
+ << " -a, --add-key will add an encoded key to the keyring\n"
+ << " --cap subsystem capability will set the capability for given subsystem\n"
+ << " --caps capsfile will set all of capabilities associated with a\n"
+ << " given key, for all subsystems"
+ << std::endl;
+ exit(1);
+}
+
+int main(int argc, const char **argv)
+{
+ vector<const char*> args;
+ argv_to_vec(argc, argv, args);
+ env_to_vec(args);
+
+ bool gen_key = false;
+ bool gen_print_key = false;
+ std::string add_key;
+ bool list = false;
+ bool print_key = false;
+ bool create_keyring = false;
+ std::string caps_fn;
+ std::string import_keyring;
+ bool set_auid = false;
+ uint64_t auid = CEPH_AUTH_UID_DEFAULT;
+ map<string,bufferlist> caps;
+ std::string fn;
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
+ CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ std::vector<const char*>::iterator i;
+ for (i = args.begin(); i != args.end(); ) {
+ std::string val;
+ if (ceph_argparse_double_dash(args, i)) {
+ break;
+ } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) {
+ gen_key = true;
+ } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) {
+ gen_print_key = true;
+ } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) {
+ add_key = val;
+ } else if (ceph_argparse_flag(args, i, &val, "-l", "--list", (char*)NULL)) {
+ list = true;
+ } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
+ caps_fn = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) {
+ std::string my_key = val;
+ if (i == args.end()) {
+ cerr << "must give two arguments to --cap: key and val." << std::endl;
+ exit(1);
+ }
+ std::string my_val = *i;
+ ++i;
+ ::encode(my_val, caps[my_key]);
+ } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) {
+ print_key = true;
+ } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) {
+ create_keyring = true;
+ } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) {
+ import_keyring = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "-u", "--set-uid", (char*)NULL)) {
+ std::string err;
+ auid = strict_strtoll(val.c_str(), 10, &err);
+ if (!err.empty()) {
+ cerr << "error parsing UID: " << err << std::endl;
+ exit(1);
+ }
+ set_auid = true;
+ } else if (fn.empty()) {
+ fn = *i++;
+ } else {
+ cerr << argv[0] << ": unexpected '" << *i << "'" << std::endl;
+ usage();
+ }
+ }
+ if (fn.empty() && !gen_print_key) {
+ cerr << argv[0] << ": must specify filename" << std::endl;
+ usage();
+ }
+ if (!(gen_key ||
+ gen_print_key ||
+ !add_key.empty() ||
+ list ||
+ !caps_fn.empty() ||
+ !caps.empty() ||
+ set_auid ||
+ print_key ||
+ create_keyring ||
+ !import_keyring.empty())) {
+ cerr << "no command specified" << std::endl;
+ usage();
+ }
+ if (gen_key && (!add_key.empty())) {
+ cerr << "can't both gen_key and add_key" << std::endl;
+ usage();
+ }
+
+ common_init_finish(g_ceph_context);
+ EntityName ename(g_conf->name);
+
+ if (gen_print_key) {
+ CryptoKey key;
+ key.create(g_ceph_context, CEPH_CRYPTO_AES);
+ cout << key << std::endl;
+ return 0;
+ }
+
+ // keyring --------
+ bool modified = false;
+ KeyRing keyring;
+
+ bufferlist bl;
+ int r = 0;
+ if (create_keyring) {
+ cout << "creating " << fn << std::endl;
+ modified = true;
+ } else {
+ std::string err;
+ r = bl.read_file(fn.c_str(), &err);
+ if (r >= 0) {
+ try {
+ bufferlist::iterator iter = bl.begin();
+ ::decode(keyring, iter);
+ } catch (const buffer::error &err) {
+ cerr << "error reading file " << fn << std::endl;
+ exit(1);
+ }
+ } else {
+ cerr << "can't open " << fn << ": " << err << std::endl;
+ exit(1);
+ }
+ }
+
+ // write commands
+ if (!import_keyring.empty()) {
+ KeyRing other;
+ bufferlist obl;
+ std::string err;
+ int r = obl.read_file(import_keyring.c_str(), &err);
+ if (r >= 0) {
+ try {
+ bufferlist::iterator iter = obl.begin();
+ ::decode(other, iter);
+ } catch (const buffer::error &err) {
+ cerr << "error reading file " << import_keyring << std::endl;
+ exit(1);
+ }
+
+ cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
+ //other.print(cout);
+ keyring.import(g_ceph_context, other);
+ modified = true;
+ } else {
+ cerr << "can't open " << import_keyring << ": " << err << std::endl;
+ exit(1);
+ }
+ }
+ if (gen_key) {
+ EntityAuth eauth;
+ eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES);
+ keyring.add(ename, eauth);
+ modified = true;
+ }
+ if (!add_key.empty()) {
+ EntityAuth eauth;
+ try {
+ eauth.key.decode_base64(add_key);
+ } catch (const buffer::error &err) {
+ cerr << "can't decode key '" << add_key << "'" << std::endl;
+ exit(1);
+ }
+ keyring.add(ename, eauth);
+ modified = true;
+ cout << "added entity " << ename << " auth " << eauth << std::endl;
+ }
+ if (!caps_fn.empty()) {
+ ConfFile cf;
+ std::deque<std::string> parse_errors;
+ if (cf.parse_file(caps_fn, &parse_errors, &cerr) != 0) {
+ cerr << "could not parse caps file " << caps_fn << std::endl;
+ exit(1);
+ }
+ complain_about_parse_errors(g_ceph_context, &parse_errors);
+ map<string, bufferlist> caps;
+ const char *key_names[] = { "mon", "osd", "mds", NULL };
+ for (int i=0; key_names[i]; i++) {
+ std::string val;
+ if (cf.read("global", key_names[i], val) == 0) {
+ bufferlist bl;
+ ::encode(val, bl);
+ string s(key_names[i]);
+ caps[s] = bl;
+ }
+ }
+ keyring.set_caps(ename, caps);
+ modified = true;
+ }
+ if (!caps.empty()) {
+ keyring.set_caps(ename, caps);
+ modified = true;
+ }
+ if (set_auid) {
+ keyring.set_uid(ename, auid);
+ modified = true;
+ }
+
+ // read commands
+ if (list) {
+ keyring.print(cout);
+ }
+ if (print_key) {
+ CryptoKey key;
+ if (keyring.get_secret(ename, key)) {
+ cout << key << std::endl;
+ } else {
+ cerr << "entity " << ename << " not found" << std::endl;
+ }
+ }
+
+ // write result?
+ if (modified) {
+ bufferlist bl;
+ keyring.encode_plaintext(bl);
+ r = bl.write_file(fn.c_str(), 0600);
+ if (r < 0) {
+ cerr << "could not write " << fn << std::endl;
+ }
+ //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;
+ }
+
+ return 0;
+}
--- /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) 2004-2010 Dreamhost
+ *
+ * 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 <fcntl.h>
+#include <iostream>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "mon/AuthMonitor.h"
+#include "common/ConfUtils.h"
+#include "global/global_init.h"
+#include "common/entity_name.h"
+#include "common/ceph_argparse.h"
+#include "common/config.h"
+#include "include/str_list.h"
+
+using std::deque;
+using std::string;
+
+static void usage()
+{
+ // TODO: add generic_usage once cerr/derr issues are resolved
+ cerr << "Ceph configuration query tool\n\
+\n\
+USAGE\n\
+ceph-conf <flags> <action>\n\
+\n\
+ACTIONS\n\
+ -L|--list-all-sections List all sections\n\
+ -l|--list-sections <prefix> List sections with the given prefix\n\
+ --filter-key <key> Filter section list to only include sections\n\
+ with given key defined.\n\
+ --filter-key-value <key>=<val> Filter section list to only include sections\n\
+ with given key/value pair.\n\
+ --lookup <key> Print a configuration setting to stdout.\n\
+ Returns 0 (success) if the configuration setting is\n\
+ found; 1 otherwise.\n\
+ -r|--resolve-search search for the first file that exists and\n\
+ can be opened in the resulted comma\n\
+ delimited search list.\n\
+\n\
+FLAGS\n\
+ --name name Set type.id\n\
+ [-s <section>] Add to list of sections to search\n\
+\n\
+If there is no action given, the action will default to --lookup.\n\
+\n\
+EXAMPLES\n\
+$ ceph-conf --name mon.0 -c /etc/ceph/ceph.conf 'mon addr'\n\
+Find out what the value of 'mon add' is for monitor 0.\n\
+\n\
+$ ceph-conf -l mon\n\
+List sections beginning with 'mon'.\n\
+\n\
+RETURN CODE\n\
+Return code will be 0 on success; error code otherwise.\n\
+";
+ exit(1);
+}
+
+static int list_sections(const std::string &prefix,
+ const std::list<string>& filter_key,
+ const std::map<string,string>& filter_key_value)
+{
+ std::vector <std::string> sections;
+ int ret = g_conf->get_all_sections(sections);
+ if (ret)
+ return 2;
+ for (std::vector<std::string>::const_iterator p = sections.begin();
+ p != sections.end(); ++p) {
+ if (strncmp(prefix.c_str(), p->c_str(), prefix.size()))
+ continue;
+
+ std::vector<std::string> sec;
+ sec.push_back(*p);
+
+ int r = 0;
+ for (std::list<string>::const_iterator q = filter_key.begin(); q != filter_key.end(); ++q) {
+ string v;
+ r = g_conf->get_val_from_conf_file(sec, q->c_str(), v, false);
+ if (r < 0)
+ break;
+ }
+ if (r < 0)
+ continue;
+
+ for (std::map<string,string>::const_iterator q = filter_key_value.begin();
+ q != filter_key_value.end();
+ ++q) {
+ string v;
+ r = g_conf->get_val_from_conf_file(sec, q->first.c_str(), v, false);
+ if (r < 0 || v != q->second) {
+ r = -1;
+ break;
+ }
+ }
+ if (r < 0)
+ continue;
+
+ cout << *p << std::endl;
+ }
+ return 0;
+}
+
+static int lookup(const std::deque<std::string> §ions,
+ const std::string &key, bool resolve_search)
+{
+ std::vector <std::string> my_sections;
+ for (deque<string>::const_iterator s = sections.begin(); s != sections.end(); ++s) {
+ my_sections.push_back(*s);
+ }
+ g_conf->get_my_sections(my_sections);
+ std::string val;
+ int ret = g_conf->get_val_from_conf_file(my_sections, key.c_str(), val, true);
+ if (ret == -ENOENT)
+ return 1;
+ else if (ret == 0) {
+ if (resolve_search) {
+ string result;
+ if (ceph_resolve_file_search(val, result))
+ puts(result.c_str());
+ }
+ else {
+ puts(val.c_str());
+ }
+ return 0;
+ }
+ else {
+ cerr << "error looking up '" << key << "': error " << ret << std::endl;
+ return 2;
+ }
+}
+
+int main(int argc, const char **argv)
+{
+ vector<const char*> args;
+ deque<std::string> sections;
+ bool resolve_search = false;
+ std::string action;
+ std::string lookup_key;
+ std::string section_list_prefix;
+ std::list<string> filter_key;
+ std::map<string,string> filter_key_value;
+
+ argv_to_vec(argc, argv, args);
+ env_to_vec(args);
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
+ CINIT_FLAG_NO_DAEMON_ACTIONS);
+
+ // do not common_init_finish(); do not start threads; do not do any of thing
+ // wonky things the daemon whose conf we are examining would do (like initialize
+ // the admin socket).
+ //common_init_finish(g_ceph_context);
+
+ std::string val;
+ for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
+ if (ceph_argparse_double_dash(args, i)) {
+ break;
+ } else if (ceph_argparse_witharg(args, i, &val, "-s", "--section", (char*)NULL)) {
+ sections.push_back(val);
+ } else if (ceph_argparse_flag(args, i, "-r", "--resolve_search", (char*)NULL)) {
+ resolve_search = true;
+ } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
+ action = "help";
+ } else if (ceph_argparse_witharg(args, i, &val, "--lookup", (char*)NULL)) {
+ action = "lookup";
+ lookup_key = val;
+ } else if (ceph_argparse_flag(args, i, "-L", "--list_all_sections", (char*)NULL)) {
+ action = "list-sections";
+ section_list_prefix = "";
+ } else if (ceph_argparse_witharg(args, i, &val, "-l", "--list_sections", (char*)NULL)) {
+ action = "list-sections";
+ section_list_prefix = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--filter_key", (char*)NULL)) {
+ filter_key.push_back(val);
+ } else if (ceph_argparse_witharg(args, i, &val, "--filter_key_value", (char*)NULL)) {
+ size_t pos = val.find_first_of('=');
+ if (pos == string::npos) {
+ cerr << "expecting argument like 'key=value' for --filter-key-value (not '" << val << "')" << std::endl;
+ usage();
+ exit(1);
+ }
+ string key(val, 0, pos);
+ string value(val, pos+1);
+ filter_key_value[key] = value;
+ } else {
+ if (((action == "lookup") || (action == "")) && (lookup_key.empty())) {
+ action = "lookup";
+ lookup_key = *i++;
+ } else {
+ cerr << "unable to parse option: '" << *i << "'" << std::endl;
+ usage();
+ exit(1);
+ }
+ }
+ }
+
+ if (action == "help") {
+ usage();
+ exit(0);
+ } else if (action == "list-sections") {
+ return list_sections(section_list_prefix, filter_key, filter_key_value);
+ } else if (action == "lookup") {
+ return lookup(sections, lookup_key, resolve_search);
+ } else {
+ cerr << "You must give an action, such as --lookup or --list-all-sections." << std::endl;
+ cerr << "Pass --help for more help." << std::endl;
+ exit(1);
+ }
+}
--- /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) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <fstream>
+
+#include "common/debug.h"
+#include "common/errno.h"
+#include "common/config.h"
+
+#include "common/ceph_argparse.h"
+#include "global/global_context.h"
+#include "global/global_init.h"
+#include "crush/CrushWrapper.h"
+#include "crush/CrushCompiler.h"
+#include "crush/CrushTester.h"
+#include "include/assert.h"
+
+#define dout_subsys ceph_subsys_crush
+
+using namespace std;
+
+const char *infn = "stdin";
+
+
+////////////////////////////////////////////////////////////////////////////
+
+void data_analysis_usage()
+{
+cout << "data output from testing routine ...\n";
+cout << " absolute_weights\n";
+cout << " the decimal weight of each OSD\n";
+cout << " data layout: ROW MAJOR\n";
+cout << " OSD id (int), weight (int)\n";
+cout << " batch_device_expected_utilization_all\n";
+cout << " the expected number of objects each OSD should receive per placement batch\n";
+cout << " which may be a decimal value\n";
+cout << " data layout: COLUMN MAJOR\n";
+cout << " round (int), objects expected on OSD 0...OSD n (float)\n";
+cout << " batch_device_utilization_all\n";
+cout << " the number of objects stored on each OSD during each placement round\n";
+cout << " data layout: COLUMN MAJOR\n";
+cout << " round (int), objects stored on OSD 0...OSD n (int)\n";
+cout << " device_utilization_all\n";
+cout << " the number of objects stored on each OSD at the end of placements\n";
+cout << " data_layout: ROW MAJOR\n";
+cout << " OSD id (int), objects stored (int), objects expected (float)\n";
+cout << " device_utilization\n";
+cout << " the number of objects stored on each OSD marked 'up' at the end of placements\n";
+cout << " data_layout: ROW MAJOR\n";
+cout << " OSD id (int), objects stored (int), objects expected (float)\n";
+cout << " placement_information\n";
+cout << " the map of input -> OSD\n";
+cout << " data_layout: ROW MAJOR\n";
+cout << " input (int), OSD's mapped (int)\n";
+cout << " proportional_weights_all\n";
+cout << " the proportional weight of each OSD specified in the CRUSH map\n";
+cout << " data_layout: ROW MAJOR\n";
+cout << " OSD id (int), proportional weight (float)\n";
+cout << " proportional_weights\n";
+cout << " the proportional weight of each 'up' OSD specified in the CRUSH map\n";
+cout << " data_layout: ROW MAJOR\n";
+cout << " OSD id (int), proportional weight (float)\n";
+}
+
+void usage()
+{
+ cout << "usage: crushtool ...\n";
+ cout << " --decompile|-d map decompile a crush map to source\n";
+ cout << " --compile|-c map.txt compile a map from source\n";
+ cout << " [-o outfile [--clobber]]\n";
+ cout << " specify output for for (de)compilation\n";
+ cout << " --build --num_osds N layer1 ...\n";
+ cout << " build a new map, where each 'layer' is\n";
+ cout << " 'name (uniform|straw|list|tree) size'\n";
+ cout << " -i mapfn --test test a range of inputs on the map\n";
+ cout << " [--min-x x] [--max-x x] [--x x]\n";
+ cout << " [--min-rule r] [--max-rule r] [--rule r]\n";
+ cout << " [--num-rep n]\n";
+ cout << " [--batches b] split the CRUSH mapping into b > 1 rounds\n";
+ cout << " [--weight|-w devno weight]\n";
+ cout << " where weight is 0 to 1.0\n";
+ cout << " [--simulate] simulate placements using a random\n";
+ cout << " number generator in place of the CRUSH\n";
+ cout << " algorithm\n";
+ cout << " -i mapfn --add-item id weight name [--loc type name ...]\n";
+ cout << " insert an item into the hierarchy at the\n";
+ cout << " given location\n";
+ cout << " -i mapfn --update-item id weight name [--loc type name ...]\n";
+ cout << " insert or move an item into the hierarchy at the\n";
+ cout << " given location\n";
+ cout << " -i mapfn --remove-item name\n"
+ << " remove the given item\n";
+ cout << " -i mapfn --reweight-item name weight\n";
+ cout << " reweight a given item (and adjust ancestor\n"
+ << " weights as needed)\n";
+ cout << " -i mapfn --reweight recalculate all bucket weights\n";
+ cout << " --show-utilization show OSD usage\n";
+ cout << " --show utilization-all\n";
+ cout << " include zero weight items\n";
+ cout << " --show-statistics show chi squared statistics\n";
+ cout << " --show-bad-mappings show bad mappings\n";
+ cout << " --show-choose-tries show choose tries histogram\n";
+ cout << " --set-choose-local-tries N\n";
+ cout << " set choose local retries before re-descent\n";
+ cout << " --set-choose-local-fallback-tries N\n";
+ cout << " set choose local retries using fallback\n";
+ cout << " permutation before re-descent\n";
+ cout << " --set-choose-total-tries N\n";
+ cout << " set choose total descent attempts\n";
+ cout << " --set-chooseleaf-descend-once <0|1>\n";
+ cout << " set chooseleaf to (not) retry the recursive descent\n";
+ cout << " --output-name name\n";
+ cout << " prepend the data file(s) generated during the\n";
+ cout << " testing routine with name\n";
+ cout << " --output-csv\n";
+ cout << " export select data generated during testing routine\n";
+ cout << " to CSV files for off-line post-processing\n";
+ cout << " use --help-output for more information\n";
+}
+
+struct bucket_types_t {
+ const char *name;
+ int type;
+} bucket_types[] = {
+ { "uniform", CRUSH_BUCKET_UNIFORM },
+ { "list", CRUSH_BUCKET_LIST },
+ { "straw", CRUSH_BUCKET_STRAW },
+ { "tree", CRUSH_BUCKET_TREE },
+ { 0, 0 },
+};
+
+struct layer_t {
+ const char *name;
+ const char *buckettype;
+ int size;
+};
+
+int main(int argc, const char **argv)
+{
+ vector<const char*> args;
+ argv_to_vec(argc, argv, args);
+
+ const char *me = argv[0];
+ std::string infn, srcfn, outfn, add_name, remove_name, reweight_name;
+ bool compile = false;
+ bool decompile = false;
+ bool test = false;
+ bool display = false;
+ bool write_to_file = false;
+ int verbose = 0;
+ bool unsafe_tunables = false;
+
+ bool reweight = false;
+ int add_item = -1;
+ bool update_item = false;
+ float add_weight = 0;
+ map<string,string> add_loc;
+ float reweight_weight = 0;
+
+ bool adjust = false;
+
+ int build = 0;
+ int num_osds =0;
+ vector<layer_t> layers;
+
+ int choose_local_tries = -1;
+ int choose_local_fallback_tries = -1;
+ int choose_total_tries = -1;
+ int chooseleaf_descend_once = -1;
+
+ CrushWrapper crush;
+
+ CrushTester tester(crush, cerr, 1);
+
+ vector<const char *> empty_args; // we use -c, don't confuse the generic arg parsing
+ global_init(NULL, empty_args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
+ CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ common_init_finish(g_ceph_context);
+
+ int x;
+ float y;
+
+ std::string val;
+ std::ostringstream err;
+ int tmp;
+ for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
+ if (ceph_argparse_double_dash(args, i)) {
+ break;
+ } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
+ usage();
+ exit(0);
+ } else if (ceph_argparse_witharg(args, i, &val, "-d", "--decompile", (char*)NULL)) {
+ infn = val;
+ decompile = true;
+ } else if (ceph_argparse_witharg(args, i, &val, "-i", "--infn", (char*)NULL)) {
+ infn = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "-o", "--outfn", (char*)NULL)) {
+ outfn = val;
+ } else if (ceph_argparse_flag(args, i, "-v", "--verbose", (char*)NULL)) {
+ verbose += 1;
+ } else if (ceph_argparse_flag(args, i, "--show_utilization", (char*)NULL)) {
+ display = true;
+ tester.set_output_utilization(true);
+ } else if (ceph_argparse_flag(args, i, "--show_utilization_all", (char*)NULL)) {
+ display = true;
+ tester.set_output_utilization_all(true);
+ } else if (ceph_argparse_flag(args, i, "--show_statistics", (char*)NULL)) {
+ display = true;
+ tester.set_output_statistics(true);
+ } else if (ceph_argparse_flag(args, i, "--show_bad_mappings", (char*)NULL)) {
+ display = true;
+ tester.set_output_bad_mappings(true);
+ } else if (ceph_argparse_flag(args, i, "--show_choose_tries", (char*)NULL)) {
+ display = true;
+ tester.set_output_choose_tries(true);
+ } else if (ceph_argparse_witharg(args, i, &val, "-c", "--compile", (char*)NULL)) {
+ srcfn = val;
+ compile = true;
+ } else if (ceph_argparse_flag(args, i, "-t", "--test", (char*)NULL)) {
+ test = true;
+ } else if (ceph_argparse_flag(args, i, "-s", "--simulate", (char*)NULL)) {
+ tester.set_random_placement();
+ } else if (ceph_argparse_flag(args, i, "--enable-unsafe-tunables", (char*)NULL)) {
+ unsafe_tunables = true;
+ } else if (ceph_argparse_withint(args, i, &choose_local_tries, &err,
+ "--set_choose_local_tries", (char*)NULL)) {
+ adjust = true;
+ } else if (ceph_argparse_withint(args, i, &choose_local_fallback_tries, &err,
+ "--set_choose_local_fallback_tries", (char*)NULL)) {
+ adjust = true;
+ } else if (ceph_argparse_withint(args, i, &choose_total_tries, &err,
+ "--set_choose_total_tries", (char*)NULL)) {
+ adjust = true;
+ } else if (ceph_argparse_withint(args, i, &chooseleaf_descend_once, &err,
+ "--set_chooseleaf_descend_once", (char*)NULL)) {
+ adjust = true;
+ } else if (ceph_argparse_flag(args, i, "--reweight", (char*)NULL)) {
+ reweight = true;
+ } else if (ceph_argparse_withint(args, i, &add_item, &err, "--add_item", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --add-item" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ add_weight = atof(*i);
+ i = args.erase(i);
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --add-item" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ add_name.assign(*i);
+ i = args.erase(i);
+ } else if (ceph_argparse_withint(args, i, &add_item, &err, "--update_item", (char*)NULL)) {
+ update_item = true;
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --update-item" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ add_weight = atof(*i);
+ i = args.erase(i);
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --update-item" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ add_name.assign(*i);
+ i = args.erase(i);
+ } else if (ceph_argparse_witharg(args, i, &val, "--loc", (char*)NULL)) {
+ std::string type(val);
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --loc" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ std::string name(*i);
+ i = args.erase(i);
+ add_loc[type] = name;
+ } else if (ceph_argparse_flag(args, i, "--output-csv", (char*)NULL)) {
+ write_to_file = true;
+ tester.set_output_data_file(true);
+ tester.set_output_csv(true);
+ } else if (ceph_argparse_flag(args, i, "--help-output", (char*)NULL)) {
+ data_analysis_usage();
+ exit(0);
+ } else if (ceph_argparse_witharg(args, i, &val, "--output-name", (char*)NULL)) {
+ std::string name(val);
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --output-name" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ else {
+ tester.set_output_data_file_name(name + "-");
+ }
+ } else if (ceph_argparse_witharg(args, i, &val, "--remove_item", (char*)NULL)) {
+ remove_name = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--reweight_item", (char*)NULL)) {
+ reweight_name = val;
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --reweight-item" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ reweight_weight = atof(*i);
+ i = args.erase(i);
+ } else if (ceph_argparse_flag(args, i, "--build", (char*)NULL)) {
+ build = true;
+ } else if (ceph_argparse_withint(args, i, &num_osds, &err, "--num_osds", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--num_rep", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_num_rep(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--max_x", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_max_x(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--min_x", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_min_x(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--x", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_x(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--max_rule", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_max_rule(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--min_rule", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_min_rule(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--rule", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_rule(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--batches", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_batches(x);
+ } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-ratio", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_device_down_ratio(y);
+ } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-bucket-ratio", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ tester.set_bucket_down_ratio(y);
+ } else if (ceph_argparse_withint(args, i, &tmp, &err, "--weight", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ int dev = tmp;
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --weight" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ float f = atof(*i);
+ i = args.erase(i);
+ tester.set_device_weight(dev, f);
+ }
+ else {
+ ++i;
+ }
+ }
+
+ if (test && !display && !write_to_file) {
+ cerr << "WARNING: no output selected; use --output-csv or --show-X" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (decompile + compile + build > 1) {
+ cout << "cannot specify more than one of compile, decompile, and build" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ if (!compile && !decompile && !build && !test && !reweight && !adjust &&
+ add_item < 0 &&
+ remove_name.empty() && reweight_name.empty()) {
+ cout << "no action specified; -h for help" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ if ((!build) && (!args.empty())) {
+ cerr << "unrecognized arguments: " << args << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ else {
+ if ((args.size() % 3) != 0U) {
+ cerr << "layers must be specified with 3-tuples of (name, buckettype, size)"
+ << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ for (size_t j = 0; j < args.size(); j += 3) {
+ layer_t l;
+ l.name = args[j];
+ l.buckettype = args[j+1];
+ l.size = atoi(args[j+2]);
+ layers.push_back(l);
+ }
+ }
+
+ /*
+ if (outfn) cout << "outfn " << outfn << std::endl;
+ if (cinfn) cout << "cinfn " << cinfn << std::endl;
+ if (dinfn) cout << "dinfn " << dinfn << std::endl;
+ */
+
+ bool modified = false;
+
+ if (!infn.empty()) {
+ bufferlist bl;
+ std::string error;
+ int r = bl.read_file(infn.c_str(), &error);
+ if (r < 0) {
+ cerr << me << ": error reading '" << infn << "': "
+ << error << std::endl;
+ exit(1);
+ }
+ bufferlist::iterator p = bl.begin();
+ crush.decode(p);
+ }
+
+ if (decompile) {
+ CrushCompiler cc(crush, cerr, verbose);
+ if (!outfn.empty()) {
+ ofstream o;
+ o.open(outfn.c_str(), ios::out | ios::binary | ios::trunc);
+ if (!o.is_open()) {
+ cerr << me << ": error writing '" << outfn << "'" << std::endl;
+ exit(1);
+ }
+ cc.decompile(o);
+ o.close();
+ } else {
+ cc.decompile(cout);
+ }
+ }
+
+ if (compile) {
+ crush.create();
+
+ // read the file
+ ifstream in(srcfn.c_str());
+ if (!in.is_open()) {
+ cerr << "input file " << srcfn << " not found" << std::endl;
+ return -ENOENT;
+ }
+
+ CrushCompiler cc(crush, cerr, verbose);
+ if (unsafe_tunables)
+ cc.enable_unsafe_tunables();
+ int r = cc.compile(in, srcfn.c_str());
+ if (r < 0)
+ exit(1);
+
+ modified = true;
+ }
+
+ if (build) {
+ if (layers.empty()) {
+ cerr << me << ": must specify at least one layer" << std::endl;
+ exit(1);
+ }
+
+ crush.create();
+
+ vector<int> lower_items;
+ vector<int> lower_weights;
+
+ for (int i=0; i<num_osds; i++) {
+ lower_items.push_back(i);
+ lower_weights.push_back(0x10000);
+ }
+
+ int type = 1;
+ int rootid = 0;
+ for (vector<layer_t>::iterator p = layers.begin(); p != layers.end(); ++p, type++) {
+ layer_t &l = *p;
+
+ dout(0) << "layer " << type
+ << " " << l.name
+ << " bucket type " << l.buckettype
+ << " " << l.size
+ << dendl;
+
+ crush.set_type_name(type, l.name);
+
+ int buckettype = -1;
+ for (int i = 0; bucket_types[i].name; i++)
+ if (l.buckettype && strcmp(l.buckettype, bucket_types[i].name) == 0) {
+ buckettype = bucket_types[i].type;
+ break;
+ }
+ if (buckettype < 0) {
+ cerr << "unknown bucket type '" << l.buckettype << "'" << std::endl << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ // build items
+ vector<int> cur_items;
+ vector<int> cur_weights;
+ unsigned lower_pos = 0; // lower pos
+
+ dout(0) << "lower_items " << lower_items << dendl;
+ dout(0) << "lower_weights " << lower_weights << dendl;
+
+ int i = 0;
+ while (1) {
+ if (lower_pos == lower_items.size())
+ break;
+
+ int items[num_osds];
+ int weights[num_osds];
+
+ int weight = 0;
+ int j;
+ for (j=0; j<l.size || l.size==0; j++) {
+ if (lower_pos == lower_items.size())
+ break;
+ items[j] = lower_items[lower_pos];
+ weights[j] = lower_weights[lower_pos];
+ weight += weights[j];
+ lower_pos++;
+ dout(0) << " item " << items[j] << " weight " << weights[j] << dendl;
+ }
+
+ crush_bucket *b = crush_make_bucket(buckettype, CRUSH_HASH_DEFAULT, type, j, items, weights);
+ assert(b);
+ int id = crush_add_bucket(crush.crush, 0, b);
+ rootid = id;
+
+ char format[20];
+ format[sizeof(format)-1] = '\0';
+ if (l.size)
+ snprintf(format, sizeof(format)-1, "%s%%d", l.name);
+ else
+ strncpy(format, l.name, sizeof(format)-1);
+ char name[20];
+ snprintf(name, sizeof(name), format, i);
+ crush.set_item_name(id, name);
+
+ dout(0) << " in bucket " << id << " '" << name << "' size " << j << " weight " << weight << dendl;
+
+ cur_items.push_back(id);
+ cur_weights.push_back(weight);
+ i++;
+ }
+
+ lower_items.swap(cur_items);
+ lower_weights.swap(cur_weights);
+ }
+
+ // make a generic rules
+ int ruleset=1;
+ crush_rule *rule = crush_make_rule(3, ruleset, CEPH_PG_TYPE_REP, 2, 2);
+ assert(rule);
+ crush_rule_set_step(rule, 0, CRUSH_RULE_TAKE, rootid, 0);
+ crush_rule_set_step(rule, 1, CRUSH_RULE_CHOOSE_LEAF_FIRSTN, CRUSH_CHOOSE_N, 1);
+ crush_rule_set_step(rule, 2, CRUSH_RULE_EMIT, 0, 0);
+ int rno = crush_add_rule(crush.crush, rule, -1);
+ crush.set_rule_name(rno, "data");
+
+ modified = true;
+ }
+
+ if (!reweight_name.empty()) {
+ cout << me << " reweighting item " << reweight_name << " to " << reweight_weight << std::endl;
+ int r;
+ if (!crush.name_exists(reweight_name)) {
+ cerr << " name " << reweight_name << " dne" << std::endl;
+ r = -ENOENT;
+ } else {
+ int item = crush.get_item_id(reweight_name);
+ r = crush.adjust_item_weightf(g_ceph_context, item, reweight_weight);
+ }
+ if (r >= 0)
+ modified = true;
+ else {
+ cerr << me << " " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ }
+ if (!remove_name.empty()) {
+ cout << me << " removing item " << remove_name << std::endl;
+ int r;
+ if (!crush.name_exists(remove_name)) {
+ cerr << " name " << remove_name << " dne" << std::endl;
+ r = -ENOENT;
+ } else {
+ int remove_item = crush.get_item_id(remove_name);
+ r = crush.remove_item(g_ceph_context, remove_item, false);
+ }
+ if (r == 0)
+ modified = true;
+ else {
+ cerr << me << " " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+ }
+ if (add_item >= 0) {
+ int r;
+ if (update_item) {
+ r = crush.update_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc);
+ } else {
+ r = crush.insert_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc);
+ }
+ if (r >= 0) {
+ modified = true;
+ } else {
+ cerr << me << " " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+ }
+ if (reweight) {
+ crush.reweight(g_ceph_context);
+ modified = true;
+ }
+
+ const char *scary_tunables_message =
+ "** tunables are DANGEROUS and NOT YET RECOMMENDED. DO NOT USE without\n"
+ "** confirming with developers that your use-case is safe and correct.";
+ if (choose_local_tries >= 0) {
+ if (!unsafe_tunables) {
+ cerr << scary_tunables_message << std::endl;
+ return -1;
+ }
+ crush.set_choose_local_tries(choose_local_tries);
+ modified = true;
+ }
+ if (choose_local_fallback_tries >= 0) {
+ if (!unsafe_tunables) {
+ cerr << scary_tunables_message << std::endl;
+ return -1;
+ }
+ crush.set_choose_local_fallback_tries(choose_local_fallback_tries);
+ modified = true;
+ }
+ if (choose_total_tries >= 0) {
+ if (!unsafe_tunables) {
+ cerr << scary_tunables_message << std::endl;
+ return -1;
+ }
+ crush.set_choose_total_tries(choose_total_tries);
+ modified = true;
+ }
+ if (chooseleaf_descend_once >= 0) {
+ if (!unsafe_tunables) {
+ cerr << scary_tunables_message << std::endl;
+ return -1;
+ }
+ crush.set_chooseleaf_descend_once(chooseleaf_descend_once);
+ modified = true;
+ }
+ if (modified) {
+ crush.finalize();
+
+ if (outfn.empty()) {
+ cout << me << " successfully built or modified map. Use '-o <file>' to write it out." << std::endl;
+ } else {
+ bufferlist bl;
+ crush.encode(bl);
+ int r = bl.write_file(outfn.c_str());
+ if (r < 0) {
+ char buf[80];
+ cerr << me << ": error writing '" << outfn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
+ exit(1);
+ }
+ if (verbose)
+ cout << "wrote crush map to " << outfn << std::endl;
+ }
+ }
+
+ if (test) {
+ int r = tester.test();
+ if (r < 0)
+ exit(1);
+ }
+
+ return 0;
+}
--- /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) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 <iostream>
+#include "os/FileStore.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+
+#include <ext/hash_map>
+using __gnu_cxx::hash_map;
+
+int dupstore(ObjectStore* src, ObjectStore* dst)
+{
+ if (src->mount() < 0) return 1;
+ if (dst->mkfs() < 0) return 1;
+ if (dst->mount() < 0) return 1;
+
+ // objects
+ hash_map<hobject_t, coll_t> did_object;
+
+ // collections
+ vector<coll_t> collections;
+
+ int ret = src->list_collections(collections);
+ if (ret < 0) {
+ cerr << "Error " << ret << " while listing collections" << std::endl;
+ return 1;
+ }
+
+ int num = collections.size();
+ cout << num << " collections" << std::endl;
+ int i = 1;
+ for (vector<coll_t>::iterator p = collections.begin();
+ p != collections.end();
+ ++p) {
+ cout << "collection " << i++ << "/" << num << " " << hex << *p << dec << std::endl;
+ {
+ ObjectStore::Transaction t;
+ t.create_collection(*p);
+ map<string,bufferptr> attrs;
+ src->collection_getattrs(*p, attrs);
+ t.collection_setattrs(*p, attrs);
+ dst->apply_transaction(t);
+ }
+
+ vector<hobject_t> o;
+ src->collection_list(*p, o);
+ int numo = o.size();
+ int j = 1;
+ for (vector<hobject_t>::iterator q = o.begin(); q != o.end(); ++q) {
+ ObjectStore::Transaction t;
+ if (did_object.count(*q))
+ t.collection_add(*p, did_object[*q], *q);
+ else {
+ bufferlist bl;
+ src->read(*p, *q, 0, 0, bl);
+ cout << "object " << j++ << "/" << numo << " " << *q << " = " << bl.length() << " bytes" << std::endl;
+ t.write(*p, *q, 0, bl.length(), bl);
+ map<string,bufferptr> attrs;
+ src->getattrs(*p, *q, attrs);
+ t.setattrs(*p, *q, attrs);
+ did_object[*q] = *p;
+ }
+ dst->apply_transaction(t);
+ }
+ }
+
+ src->umount();
+ dst->umount();
+ return 0;
+}
+
+void usage()
+{
+ cerr << "usage: ceph_dupstore filestore SRC filestore DST" << std::endl;
+ exit(0);
+}
+
+int main(int argc, const char **argv)
+{
+ vector<const char*> args;
+ argv_to_vec(argc, argv, args);
+ env_to_vec(args);
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(g_ceph_context);
+
+ // args
+ if (args.size() != 4)
+ usage();
+
+ ObjectStore *src = 0, *dst = 0;
+
+ if (strcmp(args[0], "filestore") == 0)
+ src = new FileStore(args[1], NULL);
+ else usage();
+
+ if (strcmp(args[2], "filestore") == 0)
+ dst = new FileStore(args[3], NULL);
+ else usage();
+
+ return dupstore(src, dst);
+}
--- /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) 2012 Inktank, Inc.
+*
+* 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 <iostream>
+#include <string>
+#include <sstream>
+#include <map>
+#include <set>
+#include <boost/scoped_ptr.hpp>
+#include <errno.h>
+
+#include "include/types.h"
+#include "include/buffer.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include "common/debug.h"
+#include "common/config.h"
+
+#include "mon/MonitorDBStore.h"
+#include "mon/MonitorStore.h"
+
+using namespace std;
+
+class MonitorStoreConverter {
+
+ boost::scoped_ptr<MonitorDBStore> db;
+ boost::scoped_ptr<MonitorStore> store;
+
+ set<version_t> gvs;
+ version_t highest_last_pn;
+ version_t highest_accepted_pn;
+
+ static const int PAXOS_MAX_VERSIONS = 50;
+ string MONITOR_NAME;
+
+ public:
+ MonitorStoreConverter(string &store_path, string &db_store_path)
+ : db(0), store(0),
+ highest_last_pn(0), highest_accepted_pn(0),
+ MONITOR_NAME("monitor")
+ {
+ MonitorStore *store_ptr = new MonitorStore(store_path);
+ assert(!store_ptr->mount());
+ store.reset(store_ptr);
+
+ MonitorDBStore *db_ptr = new MonitorDBStore(db_store_path);
+ db.reset(db_ptr);
+ }
+
+ int convert() {
+ if (db->open(std::cerr) >= 0) {
+ std::cerr << "store already exists" << std::endl;
+ return EEXIST;
+ }
+ assert(!db->create_and_open(std::cerr));
+ if (db->exists("mon_convert", "on_going")) {
+ std::cout << __func__ << " found a mon store in mid-convertion; abort!"
+ << std::endl;
+ return EEXIST;
+ }
+ _mark_convert_start();
+ _convert_monitor();
+ _convert_machines();
+ _mark_convert_finish();
+
+ std::cout << __func__ << " finished conversion" << std::endl;
+
+ return 0;
+ }
+
+ bool match() {
+ return true;
+ }
+
+ private:
+
+ set<string> _get_machines_names() {
+ set<string> names;
+ names.insert("auth");
+ names.insert("logm");
+ names.insert("mdsmap");
+ names.insert("monmap");
+ names.insert("osdmap");
+ names.insert("pgmap");
+
+ return names;
+ }
+
+ void _mark_convert_start() {
+ MonitorDBStore::Transaction tx;
+ tx.put("mon_convert", "on_going", 1);
+ db->apply_transaction(tx);
+ }
+
+ void _mark_convert_finish() {
+ MonitorDBStore::Transaction tx;
+ tx.erase("mon_convert", "on_going");
+ db->apply_transaction(tx);
+ }
+
+ void _convert_monitor() {
+
+ assert(store->exists_bl_ss("magic"));
+ assert(store->exists_bl_ss("keyring"));
+ assert(store->exists_bl_ss("feature_set"));
+ assert(store->exists_bl_ss("election_epoch"));
+
+ MonitorDBStore::Transaction tx;
+
+ if (store->exists_bl_ss("joined")) {
+ version_t joined = store->get_int("joined");
+ tx.put(MONITOR_NAME, "joined", joined);
+ }
+
+ vector<string> keys;
+ keys.push_back("magic");
+ keys.push_back("feature_set");
+ keys.push_back("election_epoch");
+ keys.push_back("cluster_uuid");
+
+ vector<string>::iterator it;
+ for (it = keys.begin(); it != keys.end(); ++it) {
+ if (!store->exists_bl_ss((*it).c_str()))
+ continue;
+
+ bufferlist bl;
+ int r = store->get_bl_ss(bl, (*it).c_str(), 0);
+ assert(r > 0);
+ tx.put(MONITOR_NAME, *it, bl);
+ }
+
+ assert(!tx.empty());
+ db->apply_transaction(tx);
+ }
+
+ void _convert_machines(string machine) {
+ std::cout << __func__ << " " << machine << std::endl;
+
+ version_t first_committed =
+ store->get_int(machine.c_str(), "first_committed");
+ version_t last_committed =
+ store->get_int(machine.c_str(), "last_committed");
+
+ version_t accepted_pn = store->get_int(machine.c_str(), "accepted_pn");
+ version_t last_pn = store->get_int(machine.c_str(), "last_pn");
+
+ if (accepted_pn > highest_accepted_pn)
+ highest_accepted_pn = accepted_pn;
+ if (last_pn > highest_last_pn)
+ highest_last_pn = last_pn;
+
+ string machine_gv(machine);
+ machine_gv.append("_gv");
+ bool has_gv = true;
+
+ if (!store->exists_bl_ss(machine_gv.c_str())) {
+ std::cerr << __func__ << " " << machine
+ << " no gv dir '" << machine_gv << "'" << std::endl;
+ has_gv = false;
+ }
+
+ for (version_t ver = first_committed; ver <= last_committed; ver++) {
+ if (!store->exists_bl_sn(machine.c_str(), ver)) {
+ std::cerr << __func__ << " " << machine
+ << " ver " << ver << " dne" << std::endl;
+ continue;
+ }
+
+ bufferlist bl;
+ int r = store->get_bl_sn(bl, machine.c_str(), ver);
+ assert(r >= 0);
+ std::cout << __func__ << " " << machine
+ << " ver " << ver << " bl " << bl.length() << std::endl;
+
+ MonitorDBStore::Transaction tx;
+ tx.put(machine, ver, bl);
+ tx.put(machine, "last_committed", ver);
+
+ if (has_gv && store->exists_bl_sn(machine_gv.c_str(), ver)) {
+ stringstream s;
+ s << ver;
+ string ver_str = s.str();
+
+ version_t gv = store->get_int(machine_gv.c_str(), ver_str.c_str());
+ std::cerr << __func__ << " " << machine
+ << " ver " << ver << " -> " << gv << std::endl;
+
+ if (gvs.count(gv) == 0) {
+ gvs.insert(gv);
+ } else {
+ std::cerr << __func__ << " " << machine
+ << " gv " << gv << " already exists"
+ << std::endl;
+ }
+
+ bufferlist tx_bl;
+ tx.encode(tx_bl);
+ tx.put("paxos", gv, tx_bl);
+ }
+ db->apply_transaction(tx);
+ }
+
+ version_t lc = db->get(machine, "last_committed");
+ assert(lc == last_committed);
+
+ MonitorDBStore::Transaction tx;
+ tx.put(machine, "first_committed", first_committed);
+ tx.put(machine, "last_committed", last_committed);
+
+ if (store->exists_bl_ss(machine.c_str(), "latest")) {
+ bufferlist latest_bl_raw;
+ int r = store->get_bl_ss(latest_bl_raw, machine.c_str(), "latest");
+ assert(r >= 0);
+ if (!latest_bl_raw.length()) {
+ std::cerr << __func__ << " machine " << machine
+ << " skip latest with size 0" << std::endl;
+ goto out;
+ }
+
+ tx.put(machine, "latest", latest_bl_raw);
+
+ bufferlist::iterator lbl_it = latest_bl_raw.begin();
+ bufferlist latest_bl;
+ version_t latest_ver;
+ ::decode(latest_ver, lbl_it);
+ ::decode(latest_bl, lbl_it);
+
+ std::cout << __func__ << " machine " << machine
+ << " latest ver " << latest_ver << std::endl;
+
+ tx.put(machine, "full_latest", latest_ver);
+ stringstream os;
+ os << "full_" << latest_ver;
+ tx.put(machine, os.str(), latest_bl);
+ }
+ out:
+ db->apply_transaction(tx);
+ }
+
+ void _convert_paxos() {
+ assert(!gvs.empty());
+
+ set<version_t>::reverse_iterator rit = gvs.rbegin();
+ version_t highest_gv = *rit;
+ version_t last_gv = highest_gv;
+
+ int n = 0;
+ for (; (rit != gvs.rend()) && (n < PAXOS_MAX_VERSIONS); ++rit, ++n) {
+
+ version_t gv = *rit;
+
+ if (last_gv == gv)
+ continue;
+
+ if ((last_gv - gv) > 1) {
+ // we are done; we found a gap and we are only interested in keeping
+ // contiguous paxos versions.
+ break;
+ }
+ last_gv = gv;
+ }
+
+ // erase all paxos versions between [first, last_gv[, with first being the
+ // first gv in the map.
+ MonitorDBStore::Transaction tx;
+ set<version_t>::iterator it = gvs.begin();
+ std::cout << __func__ << " first gv " << (*it)
+ << " last gv " << last_gv << std::endl;
+ for (; it != gvs.end() && (*it < last_gv); ++it) {
+ tx.erase("paxos", *it);
+ }
+ tx.put("paxos", "first_committed", last_gv);
+ tx.put("paxos", "last_committed", highest_gv);
+ tx.put("paxos", "accepted_pn", highest_accepted_pn);
+ tx.put("paxos", "last_pn", highest_last_pn);
+ db->apply_transaction(tx);
+ }
+
+ void _convert_machines() {
+
+ set<string> machine_names = _get_machines_names();
+ set<string>::iterator it = machine_names.begin();
+
+ std::cout << __func__ << std::endl;
+
+ for (; it != machine_names.end(); ++it) {
+ _convert_machines(*it);
+ }
+
+ _convert_paxos();
+ }
+};
+
+
+void usage(const char *pname)
+{
+ std::cerr << "Usage: " << pname << " <old store path>\n"
+ << std::endl;
+}
+
+int main(int argc, const char *argv[])
+{
+ vector<const char*> def_args;
+ vector<const char*> args;
+ const char *our_name = argv[0];
+ argv_to_vec(argc, argv, args);
+
+ global_init(&def_args, args,
+ CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
+ CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ common_init_finish(g_ceph_context);
+ g_ceph_context->_conf->apply_changes(NULL);
+
+ if (args.empty()) {
+ usage(our_name);
+ return 1;
+ }
+ string store(args[0]);
+ string new_store(store);
+ MonitorStoreConverter converter(store, new_store);
+ assert(!converter.convert());
+ assert(converter.match());
+
+ std::cout << "store successfully converted to new format" << std::endl;
+
+ return 0;
+}
--- /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) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <iostream>
+#include <string>
+using namespace std;
+
+#include "common/config.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include "mon/MonMap.h"
+#include "include/str_list.h"
+
+void usage()
+{
+ cout << " usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] <mapfilename>" << std::endl;
+ exit(1);
+}
+
+int main(int argc, const char **argv)
+{
+ vector<const char*> args;
+ argv_to_vec(argc, argv, args);
+
+ const char *me = argv[0];
+
+ std::string fn;
+ bool print = false;
+ bool create = false;
+ bool clobber = false;
+ bool modified = false;
+ bool generate = false;
+ bool filter = false;
+ map<string,entity_addr_t> add;
+ list<string> rm;
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
+ CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ common_init_finish(g_ceph_context);
+ std::string val;
+ for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
+ if (ceph_argparse_double_dash(args, i)) {
+ break;
+ } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
+ usage();
+ } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) {
+ print = true;
+ } else if (ceph_argparse_flag(args, i, "--create", (char*)NULL)) {
+ create = true;
+ } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) {
+ clobber = true;
+ } else if (ceph_argparse_flag(args, i, "--generate", (char*)NULL)) {
+ generate = true;
+ } else if (ceph_argparse_flag(args, i, "--set-initial-members", (char*)NULL)) {
+ filter = true;
+ } else if (ceph_argparse_flag(args, i, "--add", (char*)NULL)) {
+ string name = *i;
+ i = args.erase(i);
+ if (i == args.end())
+ usage();
+ entity_addr_t addr;
+ if (!addr.parse(*i)) {
+ cerr << me << ": invalid ip:port '" << *i << "'" << std::endl;
+ return -1;
+ }
+ if (addr.get_port() == 0)
+ addr.set_port(CEPH_MON_PORT);
+ add[name] = addr;
+ modified = true;
+ i = args.erase(i);
+ } else if (ceph_argparse_witharg(args, i, &val, "--rm", (char*)NULL)) {
+ rm.push_back(val);
+ modified = true;
+ } else {
+ ++i;
+ }
+ }
+ if (args.empty()) {
+ cerr << me << ": must specify monmap filename" << std::endl;
+ usage();
+ }
+ else if (args.size() > 1) {
+ cerr << me << ": too many arguments" << std::endl;
+ usage();
+ }
+ fn = args[0];
+
+ MonMap monmap;
+
+ cout << me << ": monmap file " << fn << std::endl;
+
+ int r = 0;
+ if (!(create && clobber)) {
+ try {
+ r = monmap.read(fn.c_str());
+ } catch (...) {
+ cerr << me << ": unable to read monmap file" << std::endl;
+ return -1;
+ }
+ }
+
+ char buf[80];
+ if (!create && r < 0) {
+ cerr << me << ": couldn't open " << fn << ": " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
+ return -1;
+ }
+ else if (create && !clobber && r == 0) {
+ cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
+ return -1;
+ }
+
+ if (create) {
+ monmap.epoch = 0;
+ monmap.created = ceph_clock_now(g_ceph_context);
+ monmap.last_changed = monmap.created;
+ srand(getpid() + time(0));
+ if (g_conf->fsid.is_zero()) {
+ monmap.generate_fsid();
+ cout << me << ": generated fsid " << monmap.fsid << std::endl;
+ }
+ modified = true;
+ }
+
+ if (generate) {
+ int r = monmap.build_initial(g_ceph_context, cerr);
+ if (r < 0)
+ return r;
+ }
+
+ if (filter) {
+ // apply initial members
+ list<string> initial_members;
+ get_str_list(g_conf->mon_initial_members, initial_members);
+ if (!initial_members.empty()) {
+ cout << "initial_members " << initial_members << ", filtering seed monmap" << std::endl;
+ set<entity_addr_t> removed;
+ monmap.set_initial_members(g_ceph_context, initial_members,
+ string(), entity_addr_t(),
+ &removed);
+ cout << "removed " << removed << std::endl;
+ }
+ modified = true;
+ }
+
+ if (!g_conf->fsid.is_zero()) {
+ monmap.fsid = g_conf->fsid;
+ cout << me << ": set fsid to " << monmap.fsid << std::endl;
+ modified = true;
+ }
+
+ for (map<string,entity_addr_t>::iterator p = add.begin(); p != add.end(); ++p) {
+ if (monmap.contains(p->first)) {
+ cerr << me << ": map already contains mon." << p->first << std::endl;
+ usage();
+ }
+ if (monmap.contains(p->second)) {
+ cerr << me << ": map already contains " << p->second << std::endl;
+ usage();
+ }
+ monmap.add(p->first, p->second);
+ }
+ for (list<string>::iterator p = rm.begin(); p != rm.end(); ++p) {
+ cout << me << ": removing " << *p << std::endl;
+ if (!monmap.contains(*p)) {
+ cerr << me << ": map does not contain " << *p << std::endl;
+ usage();
+ }
+ monmap.remove(*p);
+ }
+
+ if (!print && !modified)
+ usage();
+
+ if (print)
+ monmap.print(cout);
+
+ if (modified) {
+ // write it out
+ cout << me << ": writing epoch " << monmap.epoch
+ << " to " << fn
+ << " (" << monmap.size() << " monitors)"
+ << std::endl;
+ int r = monmap.write(fn.c_str());
+ if (r < 0) {
+ cerr << "monmaptool: error writing to '" << fn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
+ return 1;
+ }
+ }
+
+
+ return 0;
+}
--- /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) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <iostream>
+#include <string>
+using namespace std;
+
+#include "common/config.h"
+
+#include "common/errno.h"
+#include "osd/OSDMap.h"
+#include "mon/MonMap.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+
+void usage()
+{
+ cout << " usage: [--print] [--createsimple <numosd> [--clobber] [--pg_bits <bitsperosd>]] <mapfilename>" << std::endl;
+ cout << " --export-crush <file> write osdmap's crush map to <file>" << std::endl;
+ cout << " --import-crush <file> replace osdmap's crush map with <file>" << std::endl;
+ cout << " --test-map-pg <pgid> map a pgid to osds" << std::endl;
+ cout << " --test-map-object <objectname> [--pool <poolid>] map an object to osds"
+ << std::endl;
+ exit(1);
+}
+
+int main(int argc, const char **argv)
+{
+ vector<const char*> args;
+ argv_to_vec(argc, argv, args);
+ env_to_vec(args);
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
+ CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+ common_init_finish(g_ceph_context);
+
+ const char *me = argv[0];
+
+ std::string fn;
+ bool print = false;
+ bool print_json = false;
+ bool tree = false;
+ bool createsimple = false;
+ bool create_from_conf = false;
+ int num_osd = 0;
+ int pg_bits = g_conf->osd_pg_bits;
+ int pgp_bits = g_conf->osd_pgp_bits;
+ bool clobber = false;
+ bool modified = false;
+ std::string export_crush, import_crush, test_map_pg, test_map_object;
+ bool test_crush = false;
+ int range_first = -1;
+ int range_last = -1;
+ int pool = 0;
+
+ std::string val;
+ std::ostringstream err;
+ for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
+ if (ceph_argparse_double_dash(args, i)) {
+ break;
+ } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
+ usage();
+ } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) {
+ print = true;
+ } else if (ceph_argparse_flag(args, i, "--dump-json", (char*)NULL)) {
+ print_json = true;
+ } else if (ceph_argparse_flag(args, i, "--tree", (char*)NULL)) {
+ tree = true;
+ } else if (ceph_argparse_withint(args, i, &num_osd, &err, "--createsimple", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ createsimple = true;
+ } else if (ceph_argparse_flag(args, i, "--create-from-conf", (char*)NULL)) {
+ create_from_conf = true;
+ } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) {
+ clobber = true;
+ } else if (ceph_argparse_withint(args, i, &pg_bits, &err, "--pg_bits", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ } else if (ceph_argparse_withint(args, i, &pgp_bits, &err, "--pgp_bits", (char*)NULL)) {
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ } else if (ceph_argparse_witharg(args, i, &val, "--export_crush", (char*)NULL)) {
+ export_crush = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--import_crush", (char*)NULL)) {
+ import_crush = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--test_map_pg", (char*)NULL)) {
+ test_map_pg = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--test_map_object", (char*)NULL)) {
+ test_map_object = val;
+ } else if (ceph_argparse_flag(args, i, "--test_crush", (char*)NULL)) {
+ test_crush = true;
+ } else if (ceph_argparse_withint(args, i, &range_first, &err, "--range_first", (char*)NULL)) {
+ } else if (ceph_argparse_withint(args, i, &range_last, &err, "--range_last", (char*)NULL)) {
+ } else if (ceph_argparse_withint(args, i, &pool, &err, "--pool", (char*)NULL)) {
+ } else {
+ ++i;
+ }
+ }
+ if (args.empty()) {
+ cerr << me << ": must specify osdmap filename" << std::endl;
+ usage();
+ }
+ else if (args.size() > 1) {
+ cerr << me << ": too many arguments" << std::endl;
+ usage();
+ }
+ fn = args[0];
+
+ if (range_first >= 0 && range_last >= 0) {
+ set<OSDMap*> maps;
+ OSDMap *prev = NULL;
+ for (int i=range_first; i <= range_last; i++) {
+ ostringstream f;
+ f << fn << "/" << i;
+ bufferlist bl;
+ string error, s = f.str();
+ int r = bl.read_file(s.c_str(), &error);
+ if (r < 0) {
+ cerr << "unable to read " << s << ": " << cpp_strerror(r) << std::endl;
+ exit(1);
+ }
+ cout << s << " got " << bl.length() << " bytes" << std::endl;
+ OSDMap *o = new OSDMap;
+ o->decode(bl);
+ maps.insert(o);
+ if (prev)
+ OSDMap::dedup(prev, o);
+ prev = o;
+ }
+ exit(0);
+ }
+
+ OSDMap osdmap;
+ bufferlist bl;
+
+ cout << me << ": osdmap file '" << fn << "'" << std::endl;
+
+ int r = 0;
+ struct stat st;
+ if (!createsimple && !create_from_conf && !clobber) {
+ std::string error;
+ r = bl.read_file(fn.c_str(), &error);
+ if (r == 0) {
+ try {
+ osdmap.decode(bl);
+ }
+ catch (const buffer::error &e) {
+ cerr << me << ": error decoding osdmap '" << fn << "'" << std::endl;
+ return -1;
+ }
+ }
+ else {
+ cerr << me << ": couldn't open " << fn << ": " << error << std::endl;
+ return -1;
+ }
+ }
+ else if ((createsimple || create_from_conf) && !clobber && ::stat(fn.c_str(), &st) == 0) {
+ cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
+ return -1;
+ }
+
+ if (createsimple) {
+ if (num_osd < 1) {
+ cerr << me << ": osd count must be > 0" << std::endl;
+ exit(1);
+ }
+ uuid_d fsid;
+ memset(&fsid, 0, sizeof(uuid_d));
+ osdmap.build_simple(g_ceph_context, 0, fsid, num_osd, pg_bits, pgp_bits);
+ modified = true;
+ }
+ if (create_from_conf) {
+ uuid_d fsid;
+ memset(&fsid, 0, sizeof(uuid_d));
+ int r = osdmap.build_simple_from_conf(g_ceph_context, 0, fsid, pg_bits, pgp_bits);
+ if (r < 0)
+ return -1;
+ modified = true;
+ }
+
+ if (!import_crush.empty()) {
+ bufferlist cbl;
+ std::string error;
+ r = cbl.read_file(import_crush.c_str(), &error);
+ if (r) {
+ cerr << me << ": error reading crush map from " << import_crush
+ << ": " << error << std::endl;
+ exit(1);
+ }
+
+ // validate
+ CrushWrapper cw;
+ bufferlist::iterator p = cbl.begin();
+ cw.decode(p);
+
+ if (cw.get_max_devices() > osdmap.get_max_osd()) {
+ cerr << me << ": crushmap max_devices " << cw.get_max_devices()
+ << " > osdmap max_osd " << osdmap.get_max_osd() << std::endl;
+ exit(1);
+ }
+
+ // apply
+ OSDMap::Incremental inc;
+ inc.fsid = osdmap.get_fsid();
+ inc.epoch = osdmap.get_epoch()+1;
+ inc.crush = cbl;
+ osdmap.apply_incremental(inc);
+ cout << me << ": imported " << cbl.length() << " byte crush map from " << import_crush << std::endl;
+ modified = true;
+ }
+
+ if (!export_crush.empty()) {
+ bufferlist cbl;
+ osdmap.crush->encode(cbl);
+ r = cbl.write_file(export_crush.c_str());
+ if (r < 0) {
+ cerr << me << ": error writing crush map to " << import_crush << std::endl;
+ exit(1);
+ }
+ cout << me << ": exported crush map to " << export_crush << std::endl;
+ }
+
+ if (!test_map_object.empty()) {
+ object_t oid(test_map_object);
+ if (!osdmap.have_pg_pool(pool)) {
+ cerr << "There is no pool " << pool << std::endl;
+ exit(1);
+ }
+ object_locator_t loc(pool);
+ pg_t raw_pgid = osdmap.object_locator_to_pg(oid, loc);
+ pg_t pgid = osdmap.raw_pg_to_pg(raw_pgid);
+
+ vector<int> acting;
+ osdmap.pg_to_acting_osds(pgid, acting);
+ cout << " object '" << oid
+ << "' -> " << pgid
+ << " -> " << acting
+ << std::endl;
+ }
+ if (!test_map_pg.empty()) {
+ pg_t pgid;
+ if (!pgid.parse(test_map_pg.c_str())) {
+ cerr << me << ": failed to parse pg '" << test_map_pg
+ << "', r = " << r << std::endl;
+ usage();
+ }
+ cout << " parsed '" << test_map_pg << "' -> " << pgid << std::endl;
+
+ vector<int> raw, up, acting;
+ osdmap.pg_to_osds(pgid, raw);
+ osdmap.pg_to_up_acting_osds(pgid, up, acting);
+ cout << pgid << " raw " << raw << " up " << up << " acting " << acting << std::endl;
+ }
+ if (test_crush) {
+ int pass = 0;
+ while (1) {
+ cout << "pass " << ++pass << std::endl;
+
+ hash_map<pg_t,vector<int> > m;
+ for (map<int64_t,pg_pool_t>::const_iterator p = osdmap.get_pools().begin();
+ p != osdmap.get_pools().end();
+ ++p) {
+ const pg_pool_t *pool = osdmap.get_pg_pool(p->first);
+ for (ps_t ps = 0; ps < pool->get_pg_num(); ps++) {
+ pg_t pgid(ps, p->first, -1);
+ for (int i=0; i<100; i++) {
+ cout << pgid << " attempt " << i << std::endl;
+
+ vector<int> r;
+ osdmap.pg_to_acting_osds(pgid, r);
+ //cout << pgid << " " << r << std::endl;
+ if (m.count(pgid)) {
+ if (m[pgid] != r) {
+ cout << pgid << " had " << m[pgid] << " now " << r << std::endl;
+ assert(0);
+ }
+ } else
+ m[pgid] = r;
+ }
+ }
+ }
+ }
+ }
+
+ if (!print && !print_json && !tree && !modified &&
+ export_crush.empty() && import_crush.empty() &&
+ test_map_pg.empty() && test_map_object.empty()) {
+ cerr << me << ": no action specified?" << std::endl;
+ usage();
+ }
+
+ if (modified)
+ osdmap.inc_epoch();
+
+ if (print)
+ osdmap.print(cout);
+ if (print_json)
+ osdmap.dump_json(cout);
+ if (tree)
+ osdmap.print_tree(&cout, NULL);
+
+ if (modified) {
+ bl.clear();
+ osdmap.encode(bl);
+
+ // write it out
+ cout << me << ": writing epoch " << osdmap.get_epoch()
+ << " to " << fn
+ << std::endl;
+ int r = bl.write_file(fn.c_str());
+ if (r) {
+ cerr << "osdmaptool: error writing to '" << fn << "': "
+ << cpp_strerror(r) << std::endl;
+ return 1;
+ }
+ }
+
+
+ return 0;
+}
--- /dev/null
+
+#include <iostream>
+
+#include "crush/CrushWrapper.h"
+#include "osd/OSDMap.h"
+#include "common/config.h"
+#include "include/buffer.h"
+
+int main(int argc, char **argv)
+{
+ /*
+ * you need to create a suitable osdmap first. e.g., for 40 osds,
+ * $ ./osdmaptool --createsimple 40 --clobber .ceph_osdmap
+ */
+ bufferlist bl;
+ std::string error;
+ if (bl.read_file(".ceph_osdmap", &error)) {
+ cout << argv[0] << ": error reading .ceph_osdmap: " << error << std::endl;
+ return 1;
+ }
+ OSDMap osdmap;
+ osdmap.decode(bl);
+
+ int n = osdmap.get_max_osd();
+ int count[n];
+ for (int i=0; i<n; i++) {
+ osdmap.set_state(i, osdmap.get_state(i) | CEPH_OSD_UP);
+ //if (i<8)
+ osdmap.set_weight(i, CEPH_OSD_IN);
+ count[i] = 0;
+ }
+
+ int size[4];
+ for (int i=0; i<4; i++)
+ size[i] = 0;
+
+ for (int n = 0; n < 10; n++) { // namespaces
+ char nspace[20];
+ snprintf(nspace, sizeof(nspace), "n%d", n);
+ for (int f = 0; f < 5000; f++) { // files
+ for (int b = 0; b < 4; b++) { // blocks
+ char foo[20];
+ snprintf(foo, sizeof(foo), "%d.%d", f, b);
+ object_t oid(foo);
+ ceph_object_layout l = osdmap.make_object_layout(oid, 0, nspace);
+ //osdmap.file_to_object_layout(oid, g_default_file_layout);
+ vector<int> osds;
+ pg_t pgid = pg_t(l.ol_pgid);
+ //pgid.u.ps = f * 4 + b;
+ osdmap.pg_to_osds(pgid, osds);
+ size[osds.size()]++;
+#if 0
+ if (0) {
+ hash<object_t> H;
+ int x = H(oid);
+ x = ceph_stable_mod(x, 1023, 1023);
+ int s = crush_hash32(x) % 15;
+ //cout << "ceph_psim: x = " << x << " s = " << s << std::endl;
+ //osds[0] = s;
+ }
+#endif
+ //osds[0] = crush_hash32(f) % n;
+ //cout << "oid " << oid << " pgid " << pgid << " on " << osds << std::endl;
+ for (unsigned i=0; i<osds.size(); i++) {
+ //cout << " rep " << i << " on " << osds[i] << std::endl;
+ count[osds[i]]++;
+ }
+ }
+ }
+ }
+
+ uint64_t avg = 0;
+ for (int i=0; i<n; i++) {
+ cout << "osd." << i << "\t" << count[i] << std::endl;
+ avg += count[i];
+ }
+ avg /= n;
+ double dev = 0;
+ for (int i=0; i<n; i++)
+ dev += (avg - count[i]) * (avg - count[i]);
+ dev /= n;
+ dev = sqrt(dev);
+
+ double pgavg = (double)osdmap.get_pg_pool(0)->get_pg_num() / (double)n;
+ double edev = sqrt(pgavg) * (double)avg / pgavg;
+ cout << " avg " << avg
+ << " stddev " << dev
+ << " (expected " << edev << ")"
+ << " (indep object placement would be " << sqrt(avg) << ")" << std::endl;
+
+ for (int i=0; i<4; i++) {
+ cout << "size" << i << "\t" << size[i] << std::endl;
+ }
+
+ return 0;
+}
--- /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) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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/types.h"
+#include "include/rados/librados.hpp"
+using namespace librados;
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+
+void buf_to_hex(const unsigned char *buf, int len, char *str)
+{
+ str[0] = '\0';
+ for (int i = 0; i < len; i++) {
+ sprintf(&str[i*2], "%02x", (int)buf[i]);
+ }
+}
+
+
+#define ID_SIZE 8
+
+#define ACL_RD 0x1
+#define ACL_WR 0x2
+
+struct ACLID {
+ char id[ID_SIZE + 1];
+
+ void encode(bufferlist& bl) const {
+ bl.append((const char *)id, ID_SIZE);
+ }
+ void decode(bufferlist::iterator& iter) {
+ iter.copy(ID_SIZE, (char *)id);
+ }
+};
+WRITE_CLASS_ENCODER(ACLID)
+
+typedef __u32 ACLFlags;
+
+
+inline bool operator<(const ACLID& l, const ACLID& r)
+{
+ return (memcmp(&l, &r, ID_SIZE) > 0);
+}
+
+struct ACLPair {
+ ACLID id;
+ ACLFlags flags;
+};
+
+class ObjectACLs {
+ map<ACLID, ACLFlags> acls_map;
+
+public:
+
+ void encode(bufferlist& bl) const {
+ ::encode(acls_map, bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ ::decode(acls_map, bl);
+ }
+
+ int read_acl(ACLID& id, ACLFlags *flags);
+ void set_acl(ACLID& id, ACLFlags flags);
+};
+WRITE_CLASS_ENCODER(ObjectACLs)
+
+int ObjectACLs::read_acl(ACLID& id, ACLFlags *flags)
+{
+ if (!flags)
+ return -EINVAL;
+
+ map<ACLID, ACLFlags>::iterator iter = acls_map.find(id);
+
+ if (iter == acls_map.end())
+ return -ENOENT;
+
+ *flags = iter->second;
+
+ return 0;
+}
+
+void ObjectACLs::set_acl(ACLID& id, ACLFlags flags)
+{
+ acls_map[id] = flags;
+}
+
+
+
+class ACLEntity
+{
+ string name;
+ map<ACLID, ACLEntity> groups;
+};
+
+typedef map<ACLID, ACLEntity> tACLIDEntityMap;
+
+static map<ACLID, ACLEntity> users;
+static map<ACLID, ACLEntity> groups;
+
+void get_user(ACLID& aclid, ACLEntity *entity)
+{
+ //users.find(aclid);
+}
+
+
+
+
+
+int main(int argc, const char **argv)
+{
+ Rados rados;
+ if (rados.init(NULL) < 0) {
+ cerr << "couldn't initialize rados!" << std::endl;
+ exit(1);
+ }
+ if (rados.conf_read_file(NULL)) {
+ cerr << "couldn't read Ceph configuration file!" << std::endl;
+ exit(1);
+ }
+ if (rados.connect() < 0) {
+ cerr << "couldn't connect to cluster!" << std::endl;
+ exit(1);
+ }
+
+ time_t tm;
+ bufferlist bl, bl2;
+ char buf[128];
+
+ time(&tm);
+ snprintf(buf, 128, "%s", ctime(&tm));
+ bl.append(buf, strlen(buf));
+
+ const char *oid = "bar";
+
+ IoCtx io_ctx;
+ int r = rados.ioctx_create("data", io_ctx);
+ cout << "open io_ctx result = " << r << " pool = " << io_ctx.get_pool_name() << std::endl;
+
+ ACLID id;
+
+ snprintf(id.id, ID_SIZE + 1, "%.16x", 0x1234);
+ cout << "id=" << id.id << std::endl;
+
+ r = io_ctx.exec(oid, "acl", "get", bl, bl2);
+ cout << "exec returned " << r << " len=" << bl2.length() << std::endl;
+ ObjectACLs oa;
+ if (r >= 0) {
+ bufferlist::iterator iter = bl2.begin();
+ oa.decode(iter);
+ }
+
+ oa.set_acl(id, ACL_RD);
+ bl.clear();
+ oa.encode(bl);
+ r = io_ctx.exec(oid, "acl", "set", bl, bl2);
+
+ const unsigned char *md5 = (const unsigned char *)bl2.c_str();
+ char md5_str[bl2.length()*2 + 1];
+ buf_to_hex(md5, bl2.length(), md5_str);
+ cout << "md5 result=" << md5_str << std::endl;
+
+ int size = io_ctx.read(oid, bl2, 128, 0);
+ cout << "read result=" << bl2.c_str() << std::endl;
+ cout << "size=" << size << std::endl;
+
+#if 0
+ Rados::ListCtx ctx;
+ int entries;
+ do {
+ list<object_t> vec;
+ r = rados.list(io_ctx, 2, vec, ctx);
+ entries = vec.size();
+ cout << "list result=" << r << " entries=" << entries << std::endl;
+ list<object_t>::iterator iter;
+ for (iter = vec.begin(); iter != vec.end(); ++iter) {
+ cout << *iter << std::endl;
+ }
+ } while (entries);
+#endif
+#if 0
+ r = rados.remove(io_ctx, oid);
+ cout << "remove result=" << r << std::endl;
+ rados.close_io_ctx(io_ctx);
+#endif
+
+ return 0;
+}
+
--- /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) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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.h"
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+static int do_rados_setxattr(rados_ioctx_t io_ctx, const char *oid,
+ const char *key, const char *val)
+{
+ int ret = rados_setxattr(io_ctx, oid, key, val, strlen(val) + 1);
+ if (ret < 0) {
+ printf("rados_setxattr failed with error %d\n", ret);
+ return 1;
+ }
+ printf("rados_setxattr %s=%s\n", key, val);
+ return 0;
+}
+
+static int do_rados_getxattr(rados_ioctx_t io_ctx, const char *oid,
+ const char *key, const char *expected)
+{
+ size_t blen = strlen(expected) + 1;
+ char buf[blen];
+ memset(buf, 0, sizeof(buf));
+ int r = rados_getxattr(io_ctx, oid, key, buf, blen);
+ if (r < 0) {
+ printf("rados_getxattr(%s) failed with error %d\n", key, r);
+ return 1;
+ }
+ if (strcmp(buf, expected) != 0) {
+ printf("rados_getxattr(%s) got wrong result! "
+ "expected: '%s'. got '%s'\n", key, expected, buf);
+ return 1;
+ }
+ printf("rados_getxattr %s=%s\n", key, buf);
+ return 0;
+}
+
+static int do_rados_getxattrs(rados_ioctx_t io_ctx, const char *oid,
+ const char **exkeys, const char **exvals)
+{
+ rados_xattrs_iter_t iter;
+ int nval = 0, i, nfound = 0, ret = 0;
+
+ for (i = 0; exvals[i]; ++i) {
+ ++nval;
+ }
+ ret = rados_getxattrs(io_ctx, oid, &iter);
+ if (ret) {
+ printf("rados_getxattrs(%s) failed with error %d\n", oid, ret);
+ return 1;
+ }
+ while (1) {
+ size_t len;
+ const char *key, *val;
+ ret = rados_getxattrs_next(iter, &key, &val, &len);
+ if (ret) {
+ printf("rados_getxattrs(%s): rados_getxattrs_next "
+ "returned error %d\n", oid, ret);
+ return 1;
+ }
+ if (!key)
+ break;
+ for (i = 0; i < nval; ++i) {
+ if (strcmp(exkeys[i], key))
+ continue;
+ if ((len == strlen(exvals[i]) + 1) && (!strcmp(exvals[i], val))) {
+ nfound++;
+ break;
+ }
+ printf("rados_getxattrs(%s): got key %s, but the "
+ "value was %s rather than %s.\n",
+ oid, key, val, exvals[i]);
+ return 1;
+ }
+ }
+ if (nfound != nval) {
+ printf("rados_getxattrs(%s): only found %d extended attributes. "
+ "Expected %d\n", oid, nfound, nval);
+ return 1;
+ }
+ rados_getxattrs_end(iter);
+ printf("rados_getxattrs(%s)\n", oid);
+ return 0;
+}
+
+static int testrados(void)
+{
+ char tmp[32];
+ int i, r;
+ int ret = 1; //set 1 as error case
+ rados_t cl;
+
+ if (rados_create(&cl, NULL) < 0) {
+ printf("error initializing\n");
+ return 1;
+ }
+
+ if (rados_conf_read_file(cl, NULL)) {
+ printf("error reading configuration file\n");
+ goto out_err;
+ }
+
+ // Try to set a configuration option that doesn't exist.
+ // This should fail.
+ if (!rados_conf_set(cl, "config option that doesn't exist",
+ "some random value")) {
+ printf("error: succeeded in setting nonexistent config option\n");
+ goto out_err;
+ }
+
+ if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
+ printf("error: failed to read log_to_stderr from config\n");
+ goto out_err;
+ }
+
+ // Can we change it?
+ if (rados_conf_set(cl, "log to stderr", "true")) {
+ printf("error: error setting log_to_stderr\n");
+ goto out_err;
+ }
+ if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) {
+ printf("error: failed to read log_to_stderr from config\n");
+ goto out_err;
+ }
+ if (strcmp(tmp, "true")) {
+ printf("error: new setting for log_to_stderr failed to take effect.\n");
+ goto out_err;
+ }
+
+ if (rados_connect(cl)) {
+ printf("error connecting\n");
+ goto out_err;
+ }
+ if (rados_connect(cl) == 0) {
+ printf("second connect attempt didn't return an error\n");
+ goto out_err;
+ }
+
+ /* create an io_ctx */
+ r = rados_pool_create(cl, "foo");
+ printf("rados_pool_create = %d\n", r);
+
+ rados_ioctx_t io_ctx;
+ r = rados_ioctx_create(cl, "foo", &io_ctx);
+ printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx);
+
+ /* list all pools */
+ {
+ int buf_sz = rados_pool_list(cl, NULL, 0);
+ printf("need buffer size of %d\n", buf_sz);
+ char buf[buf_sz];
+ int r = rados_pool_list(cl, buf, buf_sz);
+ if (r != buf_sz) {
+ printf("buffer size mismatch: got %d the first time, but %d "
+ "the second.\n", buf_sz, r);
+ goto out_err;
+ }
+ const char *b = buf;
+ printf("begin pools.\n");
+ while (1) {
+ if (b[0] == '\0')
+ break;
+ printf(" pool: '%s'\n", b);
+ b += strlen(b) + 1;
+ };
+ printf("end pools.\n");
+ }
+
+
+ /* stat */
+ struct rados_pool_stat_t st;
+ r = rados_ioctx_pool_stat(io_ctx, &st);
+ printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
+
+ /* snapshots */
+ r = rados_ioctx_snap_create(io_ctx, "snap1");
+ printf("rados_ioctx_snap_create snap1 = %d\n", r);
+ rados_snap_t snaps[10];
+ r = rados_ioctx_snap_list(io_ctx, snaps, 10);
+ for (i=0; i<r; i++) {
+ char name[100];
+ rados_ioctx_snap_get_name(io_ctx, snaps[i], name, sizeof(name));
+ printf("rados_ioctx_snap_list got snap %lld %s\n", (long long)snaps[i], name);
+ }
+ rados_snap_t snapid;
+ r = rados_ioctx_snap_lookup(io_ctx, "snap1", &snapid);
+ printf("rados_ioctx_snap_lookup snap1 got %lld, result %d\n", (long long)snapid, r);
+ r = rados_ioctx_snap_remove(io_ctx, "snap1");
+ printf("rados_ioctx_snap_remove snap1 = %d\n", r);
+
+ /* sync io */
+ time_t tm;
+ char buf[128], buf2[128];
+ time(&tm);
+ snprintf(buf, 128, "%s", ctime(&tm));
+ const char *oid = "foo_object";
+ r = rados_write(io_ctx, oid, buf, strlen(buf) + 1, 0);
+ printf("rados_write = %d\n", r);
+ r = rados_read(io_ctx, oid, buf2, sizeof(buf2), 0);
+ printf("rados_read = %d\n", r);
+ if (memcmp(buf, buf2, r))
+ printf("*** content mismatch ***\n");
+
+ /* attrs */
+ if (do_rados_setxattr(io_ctx, oid, "b", "2"))
+ goto out_err;
+ if (do_rados_setxattr(io_ctx, oid, "a", "1"))
+ goto out_err;
+ if (do_rados_setxattr(io_ctx, oid, "c", "3"))
+ goto out_err;
+ if (do_rados_getxattr(io_ctx, oid, "a", "1"))
+ goto out_err;
+ if (do_rados_getxattr(io_ctx, oid, "b", "2"))
+ goto out_err;
+ if (do_rados_getxattr(io_ctx, oid, "c", "3"))
+ goto out_err;
+ const char *exkeys[] = { "a", "b", "c", NULL };
+ const char *exvals[] = { "1", "2", "3", NULL };
+ if (do_rados_getxattrs(io_ctx, oid, exkeys, exvals))
+ goto out_err;
+
+ uint64_t size;
+ time_t mtime;
+ r = rados_stat(io_ctx, oid, &size, &mtime);
+ printf("rados_stat size = %lld mtime = %d = %d\n", (long long)size, (int)mtime, r);
+ r = rados_stat(io_ctx, "does_not_exist", NULL, NULL);
+ printf("rados_stat(does_not_exist) = %d\n", r);
+
+ /* exec */
+ rados_exec(io_ctx, oid, "crypto", "md5", buf, strlen(buf) + 1, buf, 128);
+ printf("exec result=%s\n", buf);
+ r = rados_read(io_ctx, oid, buf2, 128, 0);
+ printf("read result=%s\n", buf2);
+ printf("size=%d\n", r);
+
+ /* aio */
+ rados_completion_t a, b;
+ rados_aio_create_completion(0, 0, 0, &a);
+ rados_aio_create_completion(0, 0, 0, &b);
+ rados_aio_write(io_ctx, "a", a, buf, 100, 0);
+ rados_aio_write(io_ctx, "../b/bb_bb_bb\\foo\\bar", b, buf, 100, 0);
+ rados_aio_wait_for_safe(a);
+ printf("a safe\n");
+ rados_aio_wait_for_safe(b);
+ printf("b safe\n");
+ rados_aio_release(a);
+ rados_aio_release(b);
+
+ /* test flush */
+ printf("testing aio flush\n");
+ rados_completion_t c;
+ rados_aio_create_completion(0, 0, 0, &c);
+ rados_aio_write(io_ctx, "c", c, buf, 100, 0);
+ int safe = rados_aio_is_safe(c);
+ printf("a should not yet be safe and ... %s\n", safe ? "is":"is not");
+ assert(!safe);
+ rados_aio_flush(io_ctx);
+ safe = rados_aio_is_safe(c);
+ printf("a should be safe and ... %s\n", safe ? "is":"is not");
+ assert(safe);
+ rados_aio_release(c);
+
+ rados_read(io_ctx, "../b/bb_bb_bb\\foo\\bar", buf2, 128, 0);
+
+ /* list objects */
+ rados_list_ctx_t h;
+ r = rados_objects_list_open(io_ctx, &h);
+ printf("rados_list_objects_open = %d, h = %p\n", r, h);
+ const char *poolname;
+ while (rados_objects_list_next(h, &poolname, NULL) == 0)
+ printf("rados_list_objects_next got object '%s'\n", poolname);
+ rados_objects_list_close(h);
+
+ /* stat */
+ r = rados_ioctx_pool_stat(io_ctx, &st);
+ printf("rados_stat_pool = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects);
+
+ /* delete a pool */
+ printf("rados_delete_pool = %d\n", r);
+ rados_ioctx_destroy(io_ctx);
+
+ r = rados_pool_delete(cl, "foo");
+ printf("rados_ioctx_pool_delete = %d\n", r);
+
+ ret = 0;
+out_err:
+ rados_shutdown(cl);
+ return ret;
+}
+
+int main(int argc, const char **argv)
+{
+ return testrados();
+}
--- /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) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * 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/types.h"
+#include "include/rados/librados.hpp"
+
+using namespace librados;
+
+#include <iostream>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+
+void buf_to_hex(const unsigned char *buf, int len, char *str)
+{
+ str[0] = '\0';
+ for (int i = 0; i < len; i++) {
+ sprintf(&str[i*2], "%02x", (int)buf[i]);
+ }
+}
+
+class C_Watch : public WatchCtx {
+public:
+ C_Watch() {}
+ void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) {
+ cout << "C_Watch::notify() opcode=" << (int)opcode << " ver=" << ver << std::endl;
+ }
+};
+
+void testradospp_milestone(void)
+{
+ cout << "*** press enter to continue ***" << std::endl;
+ getchar();
+}
+
+int main(int argc, const char **argv)
+{
+ Rados rados;
+ if (rados.init(NULL) < 0) {
+ cerr << "couldn't initialize rados!" << std::endl;
+ exit(1);
+ }
+
+ if (rados.conf_read_file(NULL)) {
+ cerr << "couldn't read configuration file." << std::endl;
+ exit(1);
+ }
+ rados.conf_parse_argv(argc, argv);
+
+ if (!rados.conf_set("config option that doesn't exist",
+ "some random value")) {
+ printf("error: succeeded in setting nonexistent config option\n");
+ exit(1);
+ }
+ if (rados.conf_set("log to stderr", "true")) {
+ printf("error: error setting log_to_stderr\n");
+ exit(1);
+ }
+ std::string tmp;
+ if (rados.conf_get("log to stderr", tmp)) {
+ printf("error: failed to read log_to_stderr from config\n");
+ exit(1);
+ }
+ if (tmp != "true") {
+ printf("error: new setting for log_to_stderr failed to take effect.\n");
+ exit(1);
+ }
+
+ if (rados.connect()) {
+ printf("error connecting\n");
+ exit(1);
+ }
+
+ cout << "rados_initialize completed" << std::endl;
+ testradospp_milestone();
+
+ time_t tm;
+ bufferlist bl, bl2, blf;
+ char buf[128];
+
+ time(&tm);
+ snprintf(buf, 128, "%s", ctime(&tm));
+ bl.append(buf, strlen(buf));
+ blf.append(buf, 16);
+
+ const char *oid = "bar";
+
+ IoCtx io_ctx;
+ int r = rados.ioctx_create("data", io_ctx);
+ cout << "ioctx_create result = " << r << std::endl;
+
+ r = io_ctx.write(oid, bl, bl.length(), 0);
+ uint64_t objver = io_ctx.get_last_version();
+ assert(objver > 0);
+ cout << "io_ctx.write returned " << r << " last_ver=" << objver << std::endl;
+
+ uint64_t stat_size;
+ time_t stat_mtime;
+ r = io_ctx.stat(oid, &stat_size, &stat_mtime);
+ cout << "io_ctx.stat returned " << r << " size = " << stat_size << " mtime = " << stat_mtime << std::endl;
+
+ r = io_ctx.stat(oid, NULL, NULL);
+ cout << "io_ctx.stat(does_not_exist) = " << r;
+
+ uint64_t handle;
+ C_Watch wc;
+ r = io_ctx.watch(oid, objver, &handle, &wc);
+ cout << "io_ctx.watch returned " << r << std::endl;
+
+ testradospp_milestone();
+ io_ctx.set_notify_timeout(7);
+ bufferlist notify_bl;
+ r = io_ctx.notify(oid, objver, notify_bl);
+ cout << "io_ctx.notify returned " << r << std::endl;
+ testradospp_milestone();
+
+ r = io_ctx.notify(oid, objver, notify_bl);
+ cout << "io_ctx.notify returned " << r << std::endl;
+ testradospp_milestone();
+
+ r = io_ctx.unwatch(oid, handle);
+ cout << "io_ctx.unwatch returned " << r << std::endl;
+ cout << "*** press enter to continue ***" << std::endl;
+ testradospp_milestone();
+
+ r = io_ctx.notify(oid, objver, notify_bl);
+ cout << "io_ctx.notify returned " << r << std::endl;
+ cout << "*** press enter to continue ***" << std::endl;
+ testradospp_milestone();
+ io_ctx.set_assert_version(objver);
+
+ r = io_ctx.write(oid, bl, bl.length() - 1, 0);
+ cout << "io_ctx.write returned " << r << std::endl;
+
+ r = io_ctx.write(oid, bl, bl.length() - 2, 0);
+ cout << "io_ctx.write returned " << r << std::endl;
+ r = io_ctx.write(oid, bl, bl.length() - 3, 0);
+ cout << "rados.write returned " << r << std::endl;
+ r = io_ctx.append(oid, bl, bl.length());
+ cout << "rados.write returned " << r << std::endl;
+ r = io_ctx.write_full(oid, blf);
+ cout << "rados.write_full returned " << r << std::endl;
+ r = io_ctx.read(oid, bl, bl.length(), 0);
+ cout << "rados.read returned " << r << std::endl;
+ r = io_ctx.trunc(oid, 8);
+ cout << "rados.trunc returned " << r << std::endl;
+ r = io_ctx.read(oid, bl, bl.length(), 0);
+ cout << "rados.read returned " << r << std::endl;
+ r = io_ctx.exec(oid, "crypto", "md5", bl, bl2);
+ cout << "exec returned " << r << " buf size=" << bl2.length() << std::endl;
+ const unsigned char *md5 = (const unsigned char *)bl2.c_str();
+ char md5_str[bl2.length()*2 + 1];
+ buf_to_hex(md5, bl2.length(), md5_str);
+ cout << "md5 result=" << md5_str << std::endl;
+
+ // test assert_version
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r >= 0);
+ uint64_t v = io_ctx.get_last_version();
+ cout << oid << " version is " << v << std::endl;
+ assert(v > 0);
+ io_ctx.set_assert_version(v);
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r >= 0);
+ io_ctx.set_assert_version(v - 1);
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r == -ERANGE);
+ io_ctx.set_assert_version(v + 1);
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r == -EOVERFLOW);
+
+ // test assert_src_version
+ const char *dest = "baz";
+ r = io_ctx.read(oid, bl, 0, 1);
+ assert(r >= 0);
+ v = io_ctx.get_last_version();
+ cout << oid << " version is " << v << std::endl;
+ io_ctx.set_assert_src_version(oid, v);
+ r = io_ctx.clone_range(dest, 0, oid, 0, 1);
+ assert(r >= 0);
+ io_ctx.set_assert_src_version(oid, v-1);
+ r = io_ctx.clone_range(dest, 0, oid, 0, 1);
+ assert(r == -ERANGE);
+ io_ctx.set_assert_src_version(oid, v+1);
+ r = io_ctx.clone_range(dest, 0, oid, 0, 1);
+ assert(r == -EOVERFLOW);
+
+ r = io_ctx.exec(oid, "crypto", "sha1", bl, bl2);
+ cout << "exec returned " << r << std::endl;
+ const unsigned char *sha1 = (const unsigned char *)bl2.c_str();
+ char sha1_str[bl2.length()*2 + 1];
+ buf_to_hex(sha1, bl2.length(), sha1_str);
+ cout << "sha1 result=" << sha1_str << std::endl;
+
+ r = io_ctx.exec(oid, "acl", "set", bl, bl2);
+ cout << "exec (set) returned " << r << std::endl;
+ r = io_ctx.exec(oid, "acl", "get", bl, bl2);
+ cout << "exec (get) returned " << r << std::endl;
+ if (bl2.length() > 0) {
+ cout << "attr=" << bl2.c_str() << std::endl;
+ }
+
+ int size = io_ctx.read(oid, bl2, 128, 0);
+ if (size <= 0) {
+ cout << "failed to read oid " << oid << "." << std::endl;
+ exit(1);
+ }
+ if (size > 4096) {
+ cout << "read too many bytes from oid " << oid << "." << std::endl;
+ exit(1);
+ }
+ char rbuf[size + 1];
+ memcpy(rbuf, bl2.c_str(), size);
+ rbuf[size] = '\0';
+ cout << "read result='" << rbuf << "'" << std::endl;
+ cout << "size=" << size << std::endl;
+
+ const char *oid2 = "jjj10.rbd";
+ r = io_ctx.exec(oid2, "rbd", "snap_list", bl, bl2);
+ cout << "snap_list result=" << r << std::endl;
+ r = io_ctx.exec(oid2, "rbd", "snap_add", bl, bl2);
+ cout << "snap_add result=" << r << std::endl;
+
+ if (r > 0) {
+ char *s = bl2.c_str();
+ for (int i=0; i<r; i++, s += strlen(s) + 1)
+ cout << s << std::endl;
+ }
+
+ cout << "compound operation..." << std::endl;
+ ObjectWriteOperation o;
+ o.write(0, bl);
+ o.setxattr("foo", bl2);
+ r = io_ctx.operate(oid, &o);
+ cout << "operate result=" << r << std::endl;
+
+ cout << "cmpxattr" << std::endl;
+ bufferlist val;
+ val.append("foo");
+ r = io_ctx.setxattr(oid, "foo", val);
+ assert(r >= 0);
+ {
+ ObjectReadOperation o;
+ o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
+ r = io_ctx.operate(oid, &o, &bl2);
+ cout << " got " << r << " wanted >= 0" << std::endl;
+ assert(r >= 0);
+ }
+ val.append("...");
+ {
+ ObjectReadOperation o;
+ o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
+ r = io_ctx.operate(oid, &o, &bl2);
+ cout << " got " << r << " wanted ECANCELED" << std::endl;
+ assert(r == -ECANCELED);
+ }
+
+ cout << "src_cmpxattr" << std::endl;
+ const char *oidb = "bar-clone";
+ {
+ ObjectWriteOperation o;
+ o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
+ io_ctx.locator_set_key(oid);
+ o.write_full(val);
+ r = io_ctx.operate(oidb, &o);
+ cout << " got " << r << " wanted ECANCELED" << std::endl;
+ assert(r == -ECANCELED);
+ }
+ {
+ ObjectWriteOperation o;
+ o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_NE, val);
+ io_ctx.locator_set_key(oid);
+ o.write_full(val);
+ r = io_ctx.operate(oidb, &o);
+ cout << " got " << r << " wanted >= 0" << std::endl;
+ assert(r >= 0);
+ }
+ io_ctx.locator_set_key(string());
+
+
+ cout << "iterating over objects..." << std::endl;
+ int num_objs = 0;
+ for (ObjectIterator iter = io_ctx.objects_begin();
+ iter != io_ctx.objects_end(); ++iter) {
+ num_objs++;
+ cout << "'" << *iter << "'" << std::endl;
+ }
+ cout << "iterated over " << num_objs << " objects." << std::endl;
+ map<string, bufferlist> attrset;
+ io_ctx.getxattrs(oid, attrset);
+
+ map<string, bufferlist>::iterator it;
+ for (it = attrset.begin(); it != attrset.end(); ++it) {
+ cout << "xattr: " << it->first << std::endl;
+ }
+
+ r = io_ctx.remove(oid);
+ cout << "remove result=" << r << std::endl;
+ rados.shutdown();
+
+ return 0;
+}
+