From 4c37719988cce601f584a9aead2d7e000445102c Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Tue, 14 Dec 2010 04:59:05 -0800 Subject: [PATCH] cephtool: rename tools files Rename tools files to be more consistent. For example, the main() function for ./ceph should be in ceph.cc. Signed-off-by: Colin McCabe --- src/Makefile.am | 27 +- src/tools/ceph.cc | 671 +++++++-------------------------- src/tools/cmd.cc | 200 ---------- src/tools/common.cc | 583 ++++++++++++++++++++++++++++ src/tools/{ceph.h => common.h} | 4 +- src/tools/gceph.cc | 2 +- src/tools/gui.cc | 2 +- 7 files changed, 745 insertions(+), 744 deletions(-) delete mode 100644 src/tools/cmd.cc create mode 100644 src/tools/common.cc rename src/tools/{ceph.h => common.h} (96%) diff --git a/src/Makefile.am b/src/Makefile.am index ec05a2bd26d22..07c12a0e3c89d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,7 +31,7 @@ cmds_CXXFLAGS = ${AM_CFLAGS} ceph_SOURCES = \ msg/SimpleMessenger.cc \ tools/ceph.cc \ - tools/cmd.cc + tools/common.cc ceph_LDADD = libcrush.a libcommon.a -ledit -lpthread -lm $(CRYPTOPP_LIBS) ceph_CXXFLAGS = ${AM_CFLAGS} @@ -57,7 +57,7 @@ ceph_tool_gui_DATA = \ tools/gui_resources/stopped_mds.svg gceph_SOURCES = \ msg/SimpleMessenger.cc \ - tools/ceph.cc \ + tools/common.cc \ tools/gceph.cc \ tools/gui.cc gceph_LDADD = libcrush.a libcommon.a -ledit -lpthread -lm $(CRYPTOPP_LIBS) \ @@ -564,18 +564,19 @@ noinst_HEADERS = \ cls_acl.cc\ cls_crypto.cc\ cm.txt\ - common/arch.h\ - common/armor.h\ + common/BackTrace.h\ + common/DoutStreambuf.h\ + common/LogClient.h\ + common/LogEntry.h\ + common/WorkQueue.h\ common/debug.h\ common/errno.h\ + common/likely.h\ common/lockdep.h\ - common/BackTrace.h\ + common/ClassHandler.h\ common/ClassVersion.h\ common/Clock.h\ - common/common_init.h\ common/Cond.h\ - common/dyn_snprintf.h\ - common/ClassHandler.h\ common/ConfUtils.h\ common/DecayCounter.h\ common/Finisher.h\ @@ -585,14 +586,14 @@ noinst_HEADERS = \ common/Mutex.h\ common/RWLock.h\ common/Semaphore.h\ - common/DoutStreambuf.h\ common/Thread.h\ common/Throttle.h\ common/Timer.h\ + common/arch.h\ + common/armor.h\ + common/common_init.h\ + common/dyn_snprintf.h\ common/tls.h\ - common/WorkQueue.h\ - common/LogEntry.h\ - common/LogClient.h\ config.h\ crush/CrushWrapper.h\ crush/CrushWrapper.i\ @@ -857,7 +858,7 @@ noinst_HEADERS = \ rgw/rgw_common.h\ rgw/rgw_user.h\ sample.ceph.conf\ - tools/ceph.h\ + tools/common.h\ tools/gui.h\ tools/gui_resources.h diff --git a/src/tools/ceph.cc b/src/tools/ceph.cc index 03e03caaa597f..6236fb92a3abf 100644 --- a/src/tools/ceph.cc +++ b/src/tools/ceph.cc @@ -1,583 +1,200 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// -*- 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 + * Copyright (C) 2004-2010 Sage Weil + * Copyright (C) 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 + * License version 2.1, as published by the Free Software * Foundation. See file COPYING. - * + * */ -#include -#include -#include -using namespace std; - -#include "acconfig.h" -#include "messages/MMonCommand.h" -#include "messages/MMonCommandAck.h" -#include "mon/MonClient.h" -#include "mon/MonMap.h" -#include "msg/SimpleMessenger.h" -#include "tools/ceph.h" - -#include "common/Cond.h" -#include "common/Mutex.h" -#include "common/Timer.h" #include "common/common_init.h" +#include "common/errno.h" +#include "config.h" +#include "tools/common.h" -#ifndef DARWIN -#include -#endif // DARWIN - -#include -#include -#include +#include +#include #include +#include +#include +#include +#include -extern "C" { -#include -} - -static enum ceph_tool_mode_t - ceph_tool_mode(CEPH_TOOL_MODE_CLI_INPUT); - -struct ceph_tool_data g; - -static Cond cmd_cond; -static SimpleMessenger *messenger = 0; -static Tokenizer *tok; - -// sync command -vector pending_cmd; -bufferlist pending_bl; -bool reply; -string reply_rs; -int reply_rc; -bufferlist reply_bl; -entity_inst_t reply_from; -Context *resend_event = 0; - - - -// observe (push) -#include "mon/PGMap.h" -#include "osd/OSDMap.h" -#include "mds/MDSMap.h" -#include "common/LogEntry.h" -#include "include/ClassLibrary.h" - -#include "mon/mon_types.h" - -#include "messages/MMonObserve.h" -#include "messages/MMonObserveNotify.h" - - -static set registered, seen; - -version_t map_ver[PAXOS_NUM]; +using std::cerr; +using std::vector; -static void handle_observe(MMonObserve *observe) +static void usage() { - dout(1) << observe->get_source() << " -> " << get_paxos_name(observe->machine_id) - << " registered" << dendl; - g.lock.Lock(); - registered.insert(observe->machine_id); - g.lock.Unlock(); - observe->put(); + cerr << "usage: ceph [options] [commands]" << std::endl; + cerr << "If no commands are specified, enter interactive mode.\n"; + cerr << "Commands:" << std::endl; + cerr << " stop -- cleanly shut down file system" << std::endl + << " (osd|pg|mds) stat -- get monitor subsystem status" << std::endl + << " ..." << std::endl; + cerr << "Options:" << std::endl; + cerr << " -i infile\n"; + cerr << " -o outfile\n"; + cerr << " specify input or output file (for certain commands)\n"; + cerr << " -s or --status\n"; + cerr << " print current system status\n"; + cerr << " -w or --watch\n"; + cerr << " watch system status changes in real time (push)\n"; + generic_client_usage(); // Will exit() } -static void handle_notify(MMonObserveNotify *notify) +static void parse_cmd_args(const vector &args, + const char **in_file, const char ** out_file, + ceph_tool_mode_t *mode, vector *nargs) { - utime_t now = g_clock.now(); - - dout(1) << notify->get_source() << " -> " << get_paxos_name(notify->machine_id) - << " v" << notify->ver - << (notify->is_latest ? " (latest)" : "") - << dendl; - - if (ceph_fsid_compare(¬ify->fsid, &g.mc.monmap.fsid)) { - dout(0) << notify->get_source_inst() << " notify fsid " << notify->fsid << " != " << g.mc.monmap.fsid << dendl; - notify->put(); - return; - } - - if (map_ver[notify->machine_id] >= notify->ver) - return; - - switch (notify->machine_id) { - case PAXOS_PGMAP: - { - bufferlist::iterator p = notify->bl.begin(); - if (notify->is_latest) { - g.pgmap.decode(p); - } else { - PGMap::Incremental inc; - inc.decode(p); - g.pgmap.apply_incremental(inc); - } - *g.log << now << " pg " << g.pgmap << std::endl; - g.updates |= PG_MON_UPDATE; - break; - } - - case PAXOS_MDSMAP: - g.mdsmap.decode(notify->bl); - *g.log << now << " mds " << g.mdsmap << std::endl; - g.updates |= MDS_MON_UPDATE; - break; - - case PAXOS_OSDMAP: - { - if (notify->is_latest) { - g.osdmap.decode(notify->bl); - } else { - OSDMap::Incremental inc(notify->bl); - g.osdmap.apply_incremental(inc); - } - *g.log << now << " osd " << g.osdmap << std::endl; - } - g.updates |= OSD_MON_UPDATE; - break; - - case PAXOS_LOG: - { - bufferlist::iterator p = notify->bl.begin(); - if (notify->is_latest) { - LogSummary summary; - ::decode(summary, p); - // show last log message - if (!summary.tail.empty()) - *g.log << now << " log " << summary.tail.back() << std::endl; - } else { - LogEntry le; - __u8 v; - ::decode(v, p); - while (!p.end()) { - le.decode(p); - *g.log << now << " log " << le << std::endl; - } - } - break; - } - - case PAXOS_CLASS: - { - bufferlist::iterator p = notify->bl.begin(); - if (notify->is_latest) { - ClassLibrary list; - ::decode(list, p); - // show the first class info - map::iterator mapiter = list.library_map.begin(); - if (mapiter != list.library_map.end()) { - ClassVersionMap& map = mapiter->second; - tClassVersionMap::iterator iter = map.begin(); - - if (iter != map.end()) - *g.log << now << " class " << iter->second << std::endl; - } - } else { - __u8 v; - ::decode(v, p); - while (!p.end()) { - ClassLibraryIncremental inc; - ::decode(inc, p); - ClassInfo info; - inc.decode_info(info); - *g.log << now << " class " << info << std::endl; - } - } - break; - } - - case PAXOS_AUTH: - { -#if 0 - bufferlist::iterator p = notify->bl.begin(); - if (notify->is_latest) { - KeyServerData data; - ::decode(data, p); - *g.log << now << " auth " << std::endl; - } else { - while (!p.end()) { - AuthMonitor::Incremental inc; - inc.decode(p); - *g.log << now << " auth " << inc.name.to_str() << std::endl; - } - } -#endif - /* ignoring auth incremental.. don't want to decode it */ - break; - } - - case PAXOS_MONMAP: - { - g.mc.monmap.decode(notify->bl); - *g.log << now << " mon " << g.mc.monmap << std::endl; + DEFINE_CONF_VARS(usage); + FOR_EACH_ARG(args) { + if (CONF_ARG_EQ("in_file", 'i')) { + CONF_SAFE_SET_ARG_VAL(in_file, OPT_STR); + } else if (CONF_ARG_EQ("out_file", 'o')) { + CONF_SAFE_SET_ARG_VAL(out_file, OPT_STR); + } else if (CONF_ARG_EQ("status", 's')) { + *mode = CEPH_TOOL_MODE_ONE_SHOT_OBSERVER; + } else if (CONF_ARG_EQ("watch", 'w')) { + *mode = CEPH_TOOL_MODE_OBSERVER; + } else if (CONF_ARG_EQ("help", 'h')) { + usage(); + } else if (args[i][0] == '-' && nargs->empty()) { + cerr << "unrecognized option " << args[i] << std::endl; + usage(); + } else { + nargs->push_back(args[i]); } - break; - - default: - *g.log << now << " ignoring unknown machine id " << notify->machine_id << std::endl; - } - - map_ver[notify->machine_id] = notify->ver; - - // have we seen them all? - seen.insert(notify->machine_id); - switch (ceph_tool_mode) { - case CEPH_TOOL_MODE_ONE_SHOT_OBSERVER: - if (seen.size() == PAXOS_NUM) { - messenger->shutdown(); - } - break; - case CEPH_TOOL_MODE_GUI: - g.gui_cond.Signal(); - break; - default: - // do nothing - break; - } - - notify->put(); -} - -class C_ObserverRefresh : public Context { -public: - bool newmon; - C_ObserverRefresh(bool n) : newmon(n) {} - void finish(int r) { - send_observe_requests(); - } -}; - -void send_observe_requests() -{ - dout(1) << "send_observe_requests " << dendl; - - bool sent = false; - for (int i=0; iget_source_inst(); - reply_rs = ack->rs; - reply_rc = ack->r; - reply_bl = ack->get_data(); - cmd_cond.Signal(); - if (resend_event) { - g.timer.cancel_event(resend_event); - resend_event = 0; + if (count > SSIZE_MAX) + return E2BIG; + while (1) { + int res; + res = read(fd, buf, count); + if (res < 0) { + int err = errno; + if (err == EINVAL) + continue; + return err; + } + count -= res; + buf += res; + if (count <= 0) + return 0; } - g.lock.Unlock(); - ack->put(); } -static void send_command() +static int get_indata(const char *in_file, bufferlist &indata) { - version_t last_seen_version = 0; - MMonCommand *m = new MMonCommand(g.mc.monmap.fsid, last_seen_version); - m->cmd = pending_cmd; - m->set_data(pending_bl); - - *g.log << g_clock.now() << " mon" << " <- " << pending_cmd << std::endl; - g.mc.send_mon_message(m); -} - -class Admin : public Dispatcher { - bool ms_dispatch(Message *m) { - switch (m->get_type()) { - case MSG_MON_COMMAND_ACK: - handle_ack((MMonCommandAck*)m); - break; - case MSG_MON_OBSERVE_NOTIFY: - handle_notify((MMonObserveNotify *)m); - break; - case MSG_MON_OBSERVE: - handle_observe((MMonObserve *)m); - break; - case CEPH_MSG_MON_MAP: - m->put(); - break; - default: - return false; - } - return true; - } - - void ms_handle_connect(Connection *con) { - if (con->get_peer_type() == CEPH_ENTITY_TYPE_MON) { - g.lock.Lock(); - if (ceph_tool_mode != CEPH_TOOL_MODE_CLI_INPUT) { - send_observe_requests(); - } - if (pending_cmd.size()) - send_command(); - g.lock.Unlock(); - } + int fd = TEMP_FAILURE_RETRY(::open(in_file, O_RDONLY)); + if (fd < 0) { + int err = errno; + cerr << "error opening in_file '" << in_file << "': " + << cpp_strerror(err); + return 1; } - bool ms_handle_reset(Connection *con) { return false; } - void ms_handle_remote_reset(Connection *con) {} - -} dispatcher; - -int do_command(vector& cmd, bufferlist& bl, string& rs, bufferlist& rbl) -{ - Mutex::Locker l(g.lock); - - pending_cmd = cmd; - pending_bl = bl; - reply = false; - - send_command(); - - while (!reply) - cmd_cond.Wait(g.lock); - - rs = rs; - rbl = reply_bl; - *g.log << g_clock.now() << " " - << reply_from.name << " -> '" - << reply_rs << "' (" << reply_rc << ")" - << std::endl; - - return reply_rc; -} - -static const char *cli_prompt(EditLine *e) -{ - return "ceph> "; -} - -int ceph_tool_do_cli() -{ - /* emacs style */ - EditLine *el = el_init("ceph", stdin, stdout, stderr); - el_set(el, EL_PROMPT, &cli_prompt); - el_set(el, EL_EDITOR, "emacs"); - - History *myhistory = history_init(); - if (myhistory == 0) { - fprintf(stderr, "history could not be initialized\n"); + struct stat st; + if (::fstat(fd, &st)) { + int err = errno; + cerr << "error getting size of in_file '" << in_file << "': " + << cpp_strerror(err); return 1; } - HistEvent ev; - - /* Set the size of the history */ - history(myhistory, &ev, H_SETSIZE, 800); - - /* This sets up the call back functions for history functionality */ - el_set(el, EL_HIST, history, myhistory); - - while (1) { - int chars_read; - const char *line = el_gets(el, &chars_read); - - //*g.log << "typed '" << line << "'" << std::endl; - - if (chars_read == 0) { - *g.log << "quit" << std::endl; - break; - } - - history(myhistory, &ev, H_ENTER, line); - - if (run_command(line)) - break; + indata.push_back(buffer::create(st.st_size)); + indata.zero(); + int ret = safe_read(fd, indata.c_str(), st.st_size); + if (ret) { + cerr << "error reading in_file '" << in_file << "': " + << cpp_strerror(ret); + return 1; } - history_end(myhistory); - el_end(el); - + TEMP_FAILURE_RETRY(::close(fd)); + cout << "read " << st.st_size << " bytes from " << in_file << std::endl; return 0; } -int run_command(const char *line) +int main(int argc, const char **argv) { - if (strcmp(line, "quit\n") == 0) - return 1; - - int argc; - const char **argv; - tok_str(tok, line, &argc, &argv); - tok_reset(tok); + vector args; + argv_to_vec(argc, argv, args); + env_to_vec(args); - vector cmd; - const char *infile = 0; - const char *outfile = 0; - for (int i=0; i") == 0 && i < argc-1) { - outfile = argv[++i]; - continue; - } - if (argv[i][0] == '>') { - outfile = argv[i] + 1; - while (*outfile == ' ') outfile++; - continue; - } - if (strcmp(argv[i], "<") == 0 && i < argc-1) { - infile = argv[++i]; - continue; - } - if (argv[i][0] == '<') { - infile = argv[i] + 1; - while (*infile == ' ') infile++; - continue; - } - cmd.push_back(argv[i]); - } - if (cmd.empty()) - return 0; + ceph_set_default_id("admin"); - bufferlist in; - if (cmd.size() == 1 && cmd[0] == "print") { - *g.log << "----" << std::endl; - write(1, in.c_str(), in.length()); - *g.log << "---- (" << in.length() << " bytes)" << std::endl; - return 0; - } + common_set_defaults(false); + common_init(args, "ceph", true); - //out << "cmd is " << cmd << std::endl; + vec_to_argv(args, argc, argv); - bufferlist out; - if (infile) { - if (out.read_file(infile) == 0) { - *g.log << "read " << out.length() << " from " << infile << std::endl; - } else { - char buf[80]; - *g.log << "couldn't read from " << infile << ": " << strerror_r(errno, buf, sizeof(buf)) << std::endl; - return 0; - } - } + const char *in_file = NULL; + const char *out_file = NULL; + enum ceph_tool_mode_t mode = CEPH_TOOL_MODE_CLI_INPUT; + vector nargs; - in.clear(); - string rs; - do_command(cmd, out, rs, in); + // parse user input + parse_cmd_args(args, &in_file, &out_file, &mode, &nargs); - if (in.length() == 0) - return 0; + bufferlist indata; - if (outfile) { - if (strcmp(outfile, "-") == 0) { - *g.log << "----" << std::endl; - write(1, in.c_str(), in.length()); - *g.log << "---- (" << in.length() << " bytes)" << std::endl; - } - else { - in.write_file(outfile); - *g.log << "wrote " << in.length() << " to " - << outfile << std::endl; + if (in_file) { + if (get_indata(in_file, indata)) { + cerr << "failed to get data from '" << in_file << "'" << std::endl; + return 1; } } - else { - *g.log << "got " << in.length() << " byte payload; 'print' " - << "to dump to terminal, or add '>-' to command." << std::endl; - } - return 0; -} - -int ceph_tool_cli_input(std::vector &cmd, const char *outfile, - bufferlist &indata) -{ - string rs; - bufferlist odata; - int ret = do_command(cmd, indata, rs, odata); - if (ret) - return ret; - - int len = odata.length(); - if (!len) { - // no output - return 0; - } - if (!outfile) { - // error: no output specified - cout << g_clock.now() << " got " << len << " byte payload, discarding (specify -o register_entity(entity_name_t::CLIENT()); - messenger->add_dispatcher_head(&dispatcher); - messenger->start(); - - g.lock.Lock(); - g.timer.init(); - g.lock.Unlock(); + int ret = 0; + switch (mode) { + case CEPH_TOOL_MODE_ONE_SHOT_OBSERVER: // fall through + case CEPH_TOOL_MODE_OBSERVER: { + g.lock.Lock(); + send_observe_requests(); + g.lock.Unlock(); + break; + } - g.mc.set_messenger(messenger); - g.mc.init(); + case CEPH_TOOL_MODE_CLI_INPUT: { + vector cmd; + for (unsigned int i = 0; i < nargs.size(); ++i) { + cmd.push_back(string(nargs[i])); + } + if (cmd.empty()) { + if (ceph_tool_do_cli()) + ret = 1; + } + else { + if (ceph_tool_cli_input(cmd, out_file, indata)) + ret = 1; + } + if (ceph_tool_messenger_shutdown()) + ret = 1; + break; + } - if (g.mc.authenticate() < 0) { - cerr << "unable to authenticate as " << *g_conf.entity_name << std::endl; - return 1; - } - if (g.mc.get_monmap() < 0) { - cerr << "unable to get monmap" << std::endl; - return 1; + default: { + cerr << "logic error: illegal ceph command mode " << mode << std::endl; + ret = 1; + break; + } } - return 0; -} -int ceph_tool_messenger_shutdown() -{ - return messenger->shutdown(); -} - -int ceph_tool_common_shutdown() -{ - // wait for messenger to finish - messenger->wait(); - messenger->destroy(); - tok_end(tok); - - g.lock.Lock(); - g.mc.shutdown(); - g.timer.shutdown(); - g.lock.Unlock(); - return 0; + if (ceph_tool_common_shutdown()) + ret = 1; + return ret; } diff --git a/src/tools/cmd.cc b/src/tools/cmd.cc deleted file mode 100644 index a380e6e09648a..0000000000000 --- a/src/tools/cmd.cc +++ /dev/null @@ -1,200 +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 Sage Weil - * Copyright (C) 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 "ceph.h" -#include "common/common_init.h" -#include "common/errno.h" -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -using std::cerr; -using std::vector; - -static void usage() -{ - cerr << "usage: ceph [options] [commands]" << std::endl; - cerr << "If no commands are specified, enter interactive mode.\n"; - cerr << "Commands:" << std::endl; - cerr << " stop -- cleanly shut down file system" << std::endl - << " (osd|pg|mds) stat -- get monitor subsystem status" << std::endl - << " ..." << std::endl; - cerr << "Options:" << std::endl; - cerr << " -i infile\n"; - cerr << " -o outfile\n"; - cerr << " specify input or output file (for certain commands)\n"; - cerr << " -s or --status\n"; - cerr << " print current system status\n"; - cerr << " -w or --watch\n"; - cerr << " watch system status changes in real time (push)\n"; - generic_client_usage(); // Will exit() -} - -static void parse_cmd_args(const vector &args, - const char **in_file, const char ** out_file, - ceph_tool_mode_t *mode, vector *nargs) -{ - DEFINE_CONF_VARS(usage); - FOR_EACH_ARG(args) { - if (CONF_ARG_EQ("in_file", 'i')) { - CONF_SAFE_SET_ARG_VAL(in_file, OPT_STR); - } else if (CONF_ARG_EQ("out_file", 'o')) { - CONF_SAFE_SET_ARG_VAL(out_file, OPT_STR); - } else if (CONF_ARG_EQ("status", 's')) { - *mode = CEPH_TOOL_MODE_ONE_SHOT_OBSERVER; - } else if (CONF_ARG_EQ("watch", 'w')) { - *mode = CEPH_TOOL_MODE_OBSERVER; - } else if (CONF_ARG_EQ("help", 'h')) { - usage(); - } else if (args[i][0] == '-' && nargs->empty()) { - cerr << "unrecognized option " << args[i] << std::endl; - usage(); - } else { - nargs->push_back(args[i]); - } - } -} - -static int safe_read(int fd, char *buf, size_t count) -{ - if (count > SSIZE_MAX) - return E2BIG; - while (1) { - int res; - res = read(fd, buf, count); - if (res < 0) { - int err = errno; - if (err == EINVAL) - continue; - return err; - } - count -= res; - buf += res; - if (count <= 0) - return 0; - } -} - -static int get_indata(const char *in_file, bufferlist &indata) -{ - int fd = TEMP_FAILURE_RETRY(::open(in_file, O_RDONLY)); - if (fd < 0) { - int err = errno; - cerr << "error opening in_file '" << in_file << "': " - << cpp_strerror(err); - return 1; - } - struct stat st; - if (::fstat(fd, &st)) { - int err = errno; - cerr << "error getting size of in_file '" << in_file << "': " - << cpp_strerror(err); - return 1; - } - - indata.push_back(buffer::create(st.st_size)); - indata.zero(); - int ret = safe_read(fd, indata.c_str(), st.st_size); - if (ret) { - cerr << "error reading in_file '" << in_file << "': " - << cpp_strerror(ret); - return 1; - } - - TEMP_FAILURE_RETRY(::close(fd)); - cout << "read " << st.st_size << " bytes from " << in_file << std::endl; - return 0; -} - -int main(int argc, const char **argv) -{ - vector args; - argv_to_vec(argc, argv, args); - env_to_vec(args); - - ceph_set_default_id("admin"); - - common_set_defaults(false); - common_init(args, "ceph", true); - - vec_to_argv(args, argc, argv); - - const char *in_file = NULL; - const char *out_file = NULL; - enum ceph_tool_mode_t mode = CEPH_TOOL_MODE_CLI_INPUT; - vector nargs; - - // parse user input - parse_cmd_args(args, &in_file, &out_file, &mode, &nargs); - - bufferlist indata; - - if (in_file) { - if (get_indata(in_file, indata)) { - cerr << "failed to get data from '" << in_file << "'" << std::endl; - return 1; - } - } - - if (ceph_tool_common_init(mode)) { - cerr << "ceph_tool_common_init failed." << std::endl; - return 1; - } - - int ret = 0; - switch (mode) { - case CEPH_TOOL_MODE_ONE_SHOT_OBSERVER: // fall through - case CEPH_TOOL_MODE_OBSERVER: { - g.lock.Lock(); - send_observe_requests(); - g.lock.Unlock(); - break; - } - - case CEPH_TOOL_MODE_CLI_INPUT: { - vector cmd; - for (unsigned int i = 0; i < nargs.size(); ++i) { - cmd.push_back(string(nargs[i])); - } - if (cmd.empty()) { - if (ceph_tool_do_cli()) - ret = 1; - } - else { - if (ceph_tool_cli_input(cmd, out_file, indata)) - ret = 1; - } - if (ceph_tool_messenger_shutdown()) - ret = 1; - break; - } - - default: { - cerr << "logic error: illegal ceph command mode " << mode << std::endl; - ret = 1; - break; - } - } - - if (ceph_tool_common_shutdown()) - ret = 1; - return ret; -} diff --git a/src/tools/common.cc b/src/tools/common.cc new file mode 100644 index 0000000000000..5bbbca7bae38e --- /dev/null +++ b/src/tools/common.cc @@ -0,0 +1,583 @@ +// -*- 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 + * + * 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 +#include +using namespace std; + +#include "acconfig.h" +#include "messages/MMonCommand.h" +#include "messages/MMonCommandAck.h" +#include "mon/MonClient.h" +#include "mon/MonMap.h" +#include "msg/SimpleMessenger.h" +#include "tools/common.h" + +#include "common/Cond.h" +#include "common/Mutex.h" +#include "common/Timer.h" +#include "common/common_init.h" + +#ifndef DARWIN +#include +#endif // DARWIN + +#include +#include +#include +#include + +extern "C" { +#include +} + +static enum ceph_tool_mode_t + ceph_tool_mode(CEPH_TOOL_MODE_CLI_INPUT); + +struct ceph_tool_data g; + +static Cond cmd_cond; +static SimpleMessenger *messenger = 0; +static Tokenizer *tok; + +// sync command +vector pending_cmd; +bufferlist pending_bl; +bool reply; +string reply_rs; +int reply_rc; +bufferlist reply_bl; +entity_inst_t reply_from; +Context *resend_event = 0; + + + +// observe (push) +#include "mon/PGMap.h" +#include "osd/OSDMap.h" +#include "mds/MDSMap.h" +#include "common/LogEntry.h" +#include "include/ClassLibrary.h" + +#include "mon/mon_types.h" + +#include "messages/MMonObserve.h" +#include "messages/MMonObserveNotify.h" + + +static set registered, seen; + +version_t map_ver[PAXOS_NUM]; + +static void handle_observe(MMonObserve *observe) +{ + dout(1) << observe->get_source() << " -> " << get_paxos_name(observe->machine_id) + << " registered" << dendl; + g.lock.Lock(); + registered.insert(observe->machine_id); + g.lock.Unlock(); + observe->put(); +} + +static void handle_notify(MMonObserveNotify *notify) +{ + utime_t now = g_clock.now(); + + dout(1) << notify->get_source() << " -> " << get_paxos_name(notify->machine_id) + << " v" << notify->ver + << (notify->is_latest ? " (latest)" : "") + << dendl; + + if (ceph_fsid_compare(¬ify->fsid, &g.mc.monmap.fsid)) { + dout(0) << notify->get_source_inst() << " notify fsid " << notify->fsid << " != " << g.mc.monmap.fsid << dendl; + notify->put(); + return; + } + + if (map_ver[notify->machine_id] >= notify->ver) + return; + + switch (notify->machine_id) { + case PAXOS_PGMAP: + { + bufferlist::iterator p = notify->bl.begin(); + if (notify->is_latest) { + g.pgmap.decode(p); + } else { + PGMap::Incremental inc; + inc.decode(p); + g.pgmap.apply_incremental(inc); + } + *g.log << now << " pg " << g.pgmap << std::endl; + g.updates |= PG_MON_UPDATE; + break; + } + + case PAXOS_MDSMAP: + g.mdsmap.decode(notify->bl); + *g.log << now << " mds " << g.mdsmap << std::endl; + g.updates |= MDS_MON_UPDATE; + break; + + case PAXOS_OSDMAP: + { + if (notify->is_latest) { + g.osdmap.decode(notify->bl); + } else { + OSDMap::Incremental inc(notify->bl); + g.osdmap.apply_incremental(inc); + } + *g.log << now << " osd " << g.osdmap << std::endl; + } + g.updates |= OSD_MON_UPDATE; + break; + + case PAXOS_LOG: + { + bufferlist::iterator p = notify->bl.begin(); + if (notify->is_latest) { + LogSummary summary; + ::decode(summary, p); + // show last log message + if (!summary.tail.empty()) + *g.log << now << " log " << summary.tail.back() << std::endl; + } else { + LogEntry le; + __u8 v; + ::decode(v, p); + while (!p.end()) { + le.decode(p); + *g.log << now << " log " << le << std::endl; + } + } + break; + } + + case PAXOS_CLASS: + { + bufferlist::iterator p = notify->bl.begin(); + if (notify->is_latest) { + ClassLibrary list; + ::decode(list, p); + // show the first class info + map::iterator mapiter = list.library_map.begin(); + if (mapiter != list.library_map.end()) { + ClassVersionMap& map = mapiter->second; + tClassVersionMap::iterator iter = map.begin(); + + if (iter != map.end()) + *g.log << now << " class " << iter->second << std::endl; + } + } else { + __u8 v; + ::decode(v, p); + while (!p.end()) { + ClassLibraryIncremental inc; + ::decode(inc, p); + ClassInfo info; + inc.decode_info(info); + *g.log << now << " class " << info << std::endl; + } + } + break; + } + + case PAXOS_AUTH: + { +#if 0 + bufferlist::iterator p = notify->bl.begin(); + if (notify->is_latest) { + KeyServerData data; + ::decode(data, p); + *g.log << now << " auth " << std::endl; + } else { + while (!p.end()) { + AuthMonitor::Incremental inc; + inc.decode(p); + *g.log << now << " auth " << inc.name.to_str() << std::endl; + } + } +#endif + /* ignoring auth incremental.. don't want to decode it */ + break; + } + + case PAXOS_MONMAP: + { + g.mc.monmap.decode(notify->bl); + *g.log << now << " mon " << g.mc.monmap << std::endl; + } + break; + + default: + *g.log << now << " ignoring unknown machine id " << notify->machine_id << std::endl; + } + + map_ver[notify->machine_id] = notify->ver; + + // have we seen them all? + seen.insert(notify->machine_id); + switch (ceph_tool_mode) { + case CEPH_TOOL_MODE_ONE_SHOT_OBSERVER: + if (seen.size() == PAXOS_NUM) { + messenger->shutdown(); + } + break; + case CEPH_TOOL_MODE_GUI: + g.gui_cond.Signal(); + break; + default: + // do nothing + break; + } + + notify->put(); +} + +class C_ObserverRefresh : public Context { +public: + bool newmon; + C_ObserverRefresh(bool n) : newmon(n) {} + void finish(int r) { + send_observe_requests(); + } +}; + +void send_observe_requests() +{ + dout(1) << "send_observe_requests " << dendl; + + bool sent = false; + for (int i=0; iget_source_inst(); + reply_rs = ack->rs; + reply_rc = ack->r; + reply_bl = ack->get_data(); + cmd_cond.Signal(); + if (resend_event) { + g.timer.cancel_event(resend_event); + resend_event = 0; + } + g.lock.Unlock(); + ack->put(); +} + +static void send_command() +{ + version_t last_seen_version = 0; + MMonCommand *m = new MMonCommand(g.mc.monmap.fsid, last_seen_version); + m->cmd = pending_cmd; + m->set_data(pending_bl); + + *g.log << g_clock.now() << " mon" << " <- " << pending_cmd << std::endl; + g.mc.send_mon_message(m); +} + +class Admin : public Dispatcher { + bool ms_dispatch(Message *m) { + switch (m->get_type()) { + case MSG_MON_COMMAND_ACK: + handle_ack((MMonCommandAck*)m); + break; + case MSG_MON_OBSERVE_NOTIFY: + handle_notify((MMonObserveNotify *)m); + break; + case MSG_MON_OBSERVE: + handle_observe((MMonObserve *)m); + break; + case CEPH_MSG_MON_MAP: + m->put(); + break; + default: + return false; + } + return true; + } + + void ms_handle_connect(Connection *con) { + if (con->get_peer_type() == CEPH_ENTITY_TYPE_MON) { + g.lock.Lock(); + if (ceph_tool_mode != CEPH_TOOL_MODE_CLI_INPUT) { + send_observe_requests(); + } + if (pending_cmd.size()) + send_command(); + g.lock.Unlock(); + } + } + bool ms_handle_reset(Connection *con) { return false; } + void ms_handle_remote_reset(Connection *con) {} + +} dispatcher; + +int do_command(vector& cmd, bufferlist& bl, string& rs, bufferlist& rbl) +{ + Mutex::Locker l(g.lock); + + pending_cmd = cmd; + pending_bl = bl; + reply = false; + + send_command(); + + while (!reply) + cmd_cond.Wait(g.lock); + + rs = rs; + rbl = reply_bl; + *g.log << g_clock.now() << " " + << reply_from.name << " -> '" + << reply_rs << "' (" << reply_rc << ")" + << std::endl; + + return reply_rc; +} + +static const char *cli_prompt(EditLine *e) +{ + return "ceph> "; +} + +int ceph_tool_do_cli() +{ + /* emacs style */ + EditLine *el = el_init("ceph", stdin, stdout, stderr); + el_set(el, EL_PROMPT, &cli_prompt); + el_set(el, EL_EDITOR, "emacs"); + + History *myhistory = history_init(); + if (myhistory == 0) { + fprintf(stderr, "history could not be initialized\n"); + return 1; + } + + HistEvent ev; + + /* Set the size of the history */ + history(myhistory, &ev, H_SETSIZE, 800); + + /* This sets up the call back functions for history functionality */ + el_set(el, EL_HIST, history, myhistory); + + while (1) { + int chars_read; + const char *line = el_gets(el, &chars_read); + + //*g.log << "typed '" << line << "'" << std::endl; + + if (chars_read == 0) { + *g.log << "quit" << std::endl; + break; + } + + history(myhistory, &ev, H_ENTER, line); + + if (run_command(line)) + break; + } + + history_end(myhistory); + el_end(el); + + return 0; +} + +int run_command(const char *line) +{ + if (strcmp(line, "quit\n") == 0) + return 1; + + int argc; + const char **argv; + tok_str(tok, line, &argc, &argv); + tok_reset(tok); + + vector cmd; + const char *infile = 0; + const char *outfile = 0; + for (int i=0; i") == 0 && i < argc-1) { + outfile = argv[++i]; + continue; + } + if (argv[i][0] == '>') { + outfile = argv[i] + 1; + while (*outfile == ' ') outfile++; + continue; + } + if (strcmp(argv[i], "<") == 0 && i < argc-1) { + infile = argv[++i]; + continue; + } + if (argv[i][0] == '<') { + infile = argv[i] + 1; + while (*infile == ' ') infile++; + continue; + } + cmd.push_back(argv[i]); + } + if (cmd.empty()) + return 0; + + bufferlist in; + if (cmd.size() == 1 && cmd[0] == "print") { + *g.log << "----" << std::endl; + write(1, in.c_str(), in.length()); + *g.log << "---- (" << in.length() << " bytes)" << std::endl; + return 0; + } + + //out << "cmd is " << cmd << std::endl; + + bufferlist out; + if (infile) { + if (out.read_file(infile) == 0) { + *g.log << "read " << out.length() << " from " << infile << std::endl; + } else { + char buf[80]; + *g.log << "couldn't read from " << infile << ": " << strerror_r(errno, buf, sizeof(buf)) << std::endl; + return 0; + } + } + + in.clear(); + string rs; + do_command(cmd, out, rs, in); + + if (in.length() == 0) + return 0; + + if (outfile) { + if (strcmp(outfile, "-") == 0) { + *g.log << "----" << std::endl; + write(1, in.c_str(), in.length()); + *g.log << "---- (" << in.length() << " bytes)" << std::endl; + } + else { + in.write_file(outfile); + *g.log << "wrote " << in.length() << " to " + << outfile << std::endl; + } + } + else { + *g.log << "got " << in.length() << " byte payload; 'print' " + << "to dump to terminal, or add '>-' to command." << std::endl; + } + return 0; +} + +int ceph_tool_cli_input(std::vector &cmd, const char *outfile, + bufferlist &indata) +{ + string rs; + bufferlist odata; + int ret = do_command(cmd, indata, rs, odata); + if (ret) + return ret; + + int len = odata.length(); + if (!len) { + // no output + return 0; + } + + if (!outfile) { + // error: no output specified + cout << g_clock.now() << " got " << len << " byte payload, discarding (specify -o register_entity(entity_name_t::CLIENT()); + messenger->add_dispatcher_head(&dispatcher); + + messenger->start(); + + g.lock.Lock(); + g.timer.init(); + g.lock.Unlock(); + + g.mc.set_messenger(messenger); + g.mc.init(); + + if (g.mc.authenticate() < 0) { + cerr << "unable to authenticate as " << *g_conf.entity_name << std::endl; + return 1; + } + if (g.mc.get_monmap() < 0) { + cerr << "unable to get monmap" << std::endl; + return 1; + } + return 0; +} + +int ceph_tool_messenger_shutdown() +{ + return messenger->shutdown(); +} + +int ceph_tool_common_shutdown() +{ + // wait for messenger to finish + messenger->wait(); + messenger->destroy(); + tok_end(tok); + + g.lock.Lock(); + g.mc.shutdown(); + g.timer.shutdown(); + g.lock.Unlock(); + return 0; +} diff --git a/src/tools/ceph.h b/src/tools/common.h similarity index 96% rename from src/tools/ceph.h rename to src/tools/common.h index 7ea2782b0b06f..058eaad609ce2 100644 --- a/src/tools/ceph.h +++ b/src/tools/common.h @@ -1,5 +1,5 @@ -#ifndef CEPH_TOOL_H -#define CEPH_TOOL_H +#ifndef CEPH_TOOLS_COMMON_DOT_H +#define CEPH_TOOLS_COMMON_DOT_H #include "common/Cond.h" #include "common/Mutex.h" diff --git a/src/tools/gceph.cc b/src/tools/gceph.cc index cbc04c7084c66..6cc42061126e4 100644 --- a/src/tools/gceph.cc +++ b/src/tools/gceph.cc @@ -13,9 +13,9 @@ * */ -#include "ceph.h" #include "common/common_init.h" #include "config.h" +#include "tools/common.h" #include #include diff --git a/src/tools/gui.cc b/src/tools/gui.cc index 3ea6da9bfb343..eef4666c74bc4 100644 --- a/src/tools/gui.cc +++ b/src/tools/gui.cc @@ -25,7 +25,7 @@ #include "common/Thread.h" #include "mon/MonClient.h" #include "mon/MonMap.h" -#include "tools/ceph.h" +#include "tools/common.h" #include "tools/gui.h" #include "tools/gui_resources.h" -- 2.39.5