]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
automake cleanup: moving misc tools to tools subdir
authorRoald J. van Loon <roaldvanloon@gmail.com>
Sat, 7 Sep 2013 13:33:10 +0000 (15:33 +0200)
committerRoald J. van Loon <roaldvanloon@gmail.com>
Sat, 7 Sep 2013 20:41:10 +0000 (22:41 +0200)
Signed-off-by: Roald J. van Loon <roaldvanloon@gmail.com>
23 files changed:
src/Makefile.am
src/ceph_authtool.cc [deleted file]
src/ceph_conf.cc [deleted file]
src/crushtool.cc [deleted file]
src/dupstore.cc [deleted file]
src/mon_store_converter.cc [deleted file]
src/monmaptool.cc [deleted file]
src/osdmaptool.cc [deleted file]
src/psim.cc [deleted file]
src/radosacl.cc [deleted file]
src/scratchtool.c [deleted file]
src/scratchtoolpp.cc [deleted file]
src/tools/ceph_authtool.cc [new file with mode: 0644]
src/tools/ceph_conf.cc [new file with mode: 0644]
src/tools/crushtool.cc [new file with mode: 0644]
src/tools/dupstore.cc [new file with mode: 0644]
src/tools/mon_store_converter.cc [new file with mode: 0644]
src/tools/monmaptool.cc [new file with mode: 0644]
src/tools/osdmaptool.cc [new file with mode: 0644]
src/tools/psim.cc [new file with mode: 0644]
src/tools/radosacl.cc [new file with mode: 0644]
src/tools/scratchtool.c [new file with mode: 0644]
src/tools/scratchtoolpp.cc [new file with mode: 0644]

index 9a2317537cbc70fafffddb8bafcbc884ec824882..634d5245ac6d592aa84935ea79e5f6724ed53c27 100644 (file)
@@ -86,7 +86,7 @@ ceph_mon_LDADD = libmon.a $(LIBOS_LDA) $(LIBGLOBAL_LDA)
 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)
@@ -112,10 +112,10 @@ ceph_mds_CXXFLAGS = ${AM_CXXFLAGS}
 
 # 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
@@ -139,11 +139,11 @@ ceph_monstore_tool_LDADD =  $(LIBOS_LDA) $(LIBGLOBAL_LDA) -lboost_program_option
 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
 
@@ -227,7 +227,7 @@ ceph_mon_SOURCES += perfglue/disabled_heap_profiler.cc
 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
 
@@ -246,7 +246,7 @@ bin_DEBUGPROGRAMS += ceph_test_msgr
 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
@@ -500,11 +500,11 @@ endif
 
 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
 
diff --git a/src/ceph_authtool.cc b/src/ceph_authtool.cc
deleted file mode 100644 (file)
index f66a3c6..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-// -*- 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;
-}
diff --git a/src/ceph_conf.cc b/src/ceph_conf.cc
deleted file mode 100644 (file)
index b2286f4..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-// -*- 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> &sections,
-                 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);
-  }
-}
diff --git a/src/crushtool.cc b/src/crushtool.cc
deleted file mode 100644 (file)
index 75c26c0..0000000
+++ /dev/null
@@ -1,724 +0,0 @@
-// -*- 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;
-}
diff --git a/src/dupstore.cc b/src/dupstore.cc
deleted file mode 100644 (file)
index e17eb22..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// -*- 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);
-}
diff --git a/src/mon_store_converter.cc b/src/mon_store_converter.cc
deleted file mode 100644 (file)
index 1c0d3af..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-// -*- 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;
-}
diff --git a/src/monmaptool.cc b/src/monmaptool.cc
deleted file mode 100644 (file)
index 57843aa..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-// -*- 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;
-}
diff --git a/src/osdmaptool.cc b/src/osdmaptool.cc
deleted file mode 100644 (file)
index 2e55026..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-// -*- 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;
-}
diff --git a/src/psim.cc b/src/psim.cc
deleted file mode 100644 (file)
index c1adc75..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-
-#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;
-}
diff --git a/src/radosacl.cc b/src/radosacl.cc
deleted file mode 100644 (file)
index d2f7ca5..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-// -*- 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;
-}
-
diff --git a/src/scratchtool.c b/src/scratchtool.c
deleted file mode 100644 (file)
index 22cf2bd..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-// -*- 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();
-}
diff --git a/src/scratchtoolpp.cc b/src/scratchtoolpp.cc
deleted file mode 100644 (file)
index 6209692..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-// -*- 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;
-}
-
diff --git a/src/tools/ceph_authtool.cc b/src/tools/ceph_authtool.cc
new file mode 100644 (file)
index 0000000..f66a3c6
--- /dev/null
@@ -0,0 +1,277 @@
+// -*- 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;
+}
diff --git a/src/tools/ceph_conf.cc b/src/tools/ceph_conf.cc
new file mode 100644 (file)
index 0000000..b2286f4
--- /dev/null
@@ -0,0 +1,223 @@
+// -*- 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> &sections,
+                 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);
+  }
+}
diff --git a/src/tools/crushtool.cc b/src/tools/crushtool.cc
new file mode 100644 (file)
index 0000000..75c26c0
--- /dev/null
@@ -0,0 +1,724 @@
+// -*- 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;
+}
diff --git a/src/tools/dupstore.cc b/src/tools/dupstore.cc
new file mode 100644 (file)
index 0000000..e17eb22
--- /dev/null
@@ -0,0 +1,114 @@
+// -*- 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);
+}
diff --git a/src/tools/mon_store_converter.cc b/src/tools/mon_store_converter.cc
new file mode 100644 (file)
index 0000000..1c0d3af
--- /dev/null
@@ -0,0 +1,336 @@
+// -*- 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;
+}
diff --git a/src/tools/monmaptool.cc b/src/tools/monmaptool.cc
new file mode 100644 (file)
index 0000000..57843aa
--- /dev/null
@@ -0,0 +1,208 @@
+// -*- 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;
+}
diff --git a/src/tools/osdmaptool.cc b/src/tools/osdmaptool.cc
new file mode 100644 (file)
index 0000000..2e55026
--- /dev/null
@@ -0,0 +1,343 @@
+// -*- 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;
+}
diff --git a/src/tools/psim.cc b/src/tools/psim.cc
new file mode 100644 (file)
index 0000000..c1adc75
--- /dev/null
@@ -0,0 +1,96 @@
+
+#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;
+}
diff --git a/src/tools/radosacl.cc b/src/tools/radosacl.cc
new file mode 100644 (file)
index 0000000..d2f7ca5
--- /dev/null
@@ -0,0 +1,202 @@
+// -*- 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;
+}
+
diff --git a/src/tools/scratchtool.c b/src/tools/scratchtool.c
new file mode 100644 (file)
index 0000000..22cf2bd
--- /dev/null
@@ -0,0 +1,312 @@
+// -*- 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();
+}
diff --git a/src/tools/scratchtoolpp.cc b/src/tools/scratchtoolpp.cc
new file mode 100644 (file)
index 0000000..6209692
--- /dev/null
@@ -0,0 +1,315 @@
+// -*- 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;
+}
+