Merge branch 'wip_4836' into next

Fixes: #4836
Reviewed-by: Sage Weil <sage@inktank.com>
This commit is contained in:
Samuel Just 2013-04-29 10:45:20 -07:00
commit f8f762a281
5 changed files with 174 additions and 24 deletions

View File

@ -128,6 +128,13 @@ ceph_filestore_dump_LDADD += -ldl
endif
bin_PROGRAMS += ceph ceph-conf ceph-authtool ceph_filestore_dump
ceph_monstore_tool_SOURCES = tools/ceph-monstore-tool.cc \
os/LevelDBStore.cc
ceph_monstore_tool_LDFLAGS = ${AM_LDFLAGS}
ceph_monstore_tool_LDADD = $(LIBOS_LDA) $(LIBGLOBAL_LDA) -lboost_program_options
ceph_monstore_tool_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
bin_PROGRAMS += ceph_monstore_tool
monmaptool_SOURCES = monmaptool.cc
monmaptool_LDADD = $(LIBGLOBAL_LDA)
crushtool_SOURCES = crushtool.cc

View File

@ -58,6 +58,15 @@ static ostream& _prefix(std::ostream *_dout, Monitor *mon, OSDMap& osdmap) {
<< ").osd e" << osdmap.get_epoch() << " ";
}
bool OSDMonitor::_have_pending_crush()
{
return pending_inc.crush.length();
}
CrushWrapper &OSDMonitor::_get_stable_crush()
{
return *osdmap.crush;
}
void OSDMonitor::_get_pending_crush(CrushWrapper& newcrush)
{
@ -2534,27 +2543,33 @@ bool OSDMonitor::prepare_command(MMonCommand *m)
else if (m->cmd.size() == 5 && m->cmd[1] == "crush" && (m->cmd[2] == "add-bucket")) {
do {
// osd crush add-bucket <name> <type>
CrushWrapper newcrush;
_get_pending_crush(newcrush);
if (newcrush.name_exists(m->cmd[3])) {
if (!_have_pending_crush() &&
_get_stable_crush().name_exists(m->cmd[3])) {
ss << "bucket '" << m->cmd[3] << "' already exists";
err = 0;
break;
}
int type = newcrush.get_type_id(m->cmd[4]);
if (type <= 0) {
ss << "type '" << m->cmd[4] << "' does not exist";
err = -EINVAL;
break;
}
int bucketno = newcrush.add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_DEFAULT,
type, 0, NULL, NULL);
newcrush.set_item_name(bucketno, m->cmd[3]);
pending_inc.crush.clear();
newcrush.encode(pending_inc.crush);
ss << "added bucket " << m->cmd[3] << " type " << m->cmd[4] << " to crush map";
CrushWrapper newcrush;
_get_pending_crush(newcrush);
if (newcrush.name_exists(m->cmd[3])) {
ss << "bucket '" << m->cmd[3] << "' already exists";
err = 0;
} else {
int type = newcrush.get_type_id(m->cmd[4]);
if (type <= 0) {
ss << "type '" << m->cmd[4] << "' does not exist";
err = -EINVAL;
break;
}
int bucketno = newcrush.add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_DEFAULT,
type, 0, NULL, NULL);
newcrush.set_item_name(bucketno, m->cmd[3]);
pending_inc.crush.clear();
newcrush.encode(pending_inc.crush);
ss << "added bucket " << m->cmd[3] << " type " << m->cmd[4] << " to crush map";
}
getline(ss, rs);
wait_for_finished_proposal(new Monitor::C_Command(mon, m, 0, rs, get_version()));
return true;

View File

@ -137,6 +137,8 @@ private:
int thrash_last_up_osd;
bool thrash();
bool _have_pending_crush();
CrushWrapper &_get_stable_crush();
void _get_pending_crush(CrushWrapper& newcrush);
// svc

View File

@ -294,19 +294,13 @@ void PaxosService::put_version(MonitorDBStore::Transaction *t,
const string& prefix, version_t ver,
bufferlist& bl)
{
ostringstream os;
os << ver;
string key = mon->store->combine_strings(prefix, os.str());
t->put(get_service_name(), key, bl);
t->put(get_service_name(), ver, bl);
}
int PaxosService::get_version(const string& prefix, version_t ver,
bufferlist& bl)
{
ostringstream os;
os << ver;
string key = mon->store->combine_strings(prefix, os.str());
return mon->store->get(get_service_name(), key, bl);
return mon->store->get(get_service_name(), ver, bl);
}
void PaxosService::trim(MonitorDBStore::Transaction *t,

View File

@ -0,0 +1,132 @@
// -*- 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 <boost/scoped_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options/option.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/parsers.hpp>
#include <iostream>
#include <set>
#include <sstream>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <sstream>
#include <map>
#include <set>
#include <boost/scoped_ptr.hpp>
#include "global/global_init.h"
#include "os/LevelDBStore.h"
#include "mon/MonitorDBStore.h"
namespace po = boost::program_options;
using namespace std;
int main(int argc, char **argv) {
po::options_description desc("Allowed options");
int version = -1;
string store_path, cmd, out_path;
desc.add_options()
("help", "produce help message")
("mon-store-path", po::value<string>(&store_path),
"path to mon directory, mandatory")
("out", po::value<string>(&out_path),
"out path")
("version", po::value<int>(&version),
"version requested")
("command", po::value<string>(&cmd),
"command")
;
po::positional_options_description p;
p.add("command", 1);
p.add("version", 1);
po::variables_map vm;
po::parsed_options parsed =
po::command_line_parser(argc, argv).options(desc).positional(p).run();
po::store(
parsed,
vm);
try {
po::notify(vm);
} catch (...) {
cout << desc << std::endl;
return 1;
}
vector<const char *> ceph_options, def_args;
vector<string> ceph_option_strings = po::collect_unrecognized(
parsed.options, po::include_positional);
ceph_options.reserve(ceph_option_strings.size());
for (vector<string>::iterator i = ceph_option_strings.begin();
i != ceph_option_strings.end();
++i) {
ceph_options.push_back(i->c_str());
}
global_init(
&def_args, ceph_options, CEPH_ENTITY_TYPE_OSD,
CODE_ENVIRONMENT_UTILITY, 0);
common_init_finish(g_ceph_context);
g_ceph_context->_conf->apply_changes(NULL);
g_conf = g_ceph_context->_conf;
if (vm.count("help")) {
std::cerr << desc << std::endl;
return 1;
}
int fd;
if (vm.count("out")) {
fd = open(out_path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
} else {
fd = STDOUT_FILENO;
}
MonitorDBStore st(store_path);
stringstream ss;
int r = st.open(ss);
if (r < 0) {
std::cerr << ss.str() << std::endl;
goto done;
}
if (cmd == "getosdmap") {
version_t v;
if (version == -1) {
v = st.get("osdmap", "last_committed");
} else {
v = version;
}
bufferlist bl;
/// XXX: this is not ok, osdmap and full should be abstracted somewhere
int r = st.get("osdmap", st.combine_strings("full", v), bl);
if (r < 0) {
std::cerr << "Error getting map: " << cpp_strerror(r) << std::endl;
goto done;
}
bl.write_fd(fd);
} else {
std::cerr << "Unrecognized command: " << cmd << std::endl;
goto done;
}
done:
if (vm.count("out")) {
::close(fd);
}
return 0;
}