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}
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) \
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\
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\
rgw/rgw_common.h\
rgw/rgw_user.h\
sample.ceph.conf\
- tools/ceph.h\
+ tools/common.h\
tools/gui.h\
tools/gui_resources.h
-// -*- 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 <sage@newdream.net>
+ * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
+ * 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 <sys/stat.h>
-#include <iostream>
-#include <string>
-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 <envz.h>
-#endif // DARWIN
-
-#include <memory>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <limits.h>
+#include <errno.h>
#include <fcntl.h>
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <vector>
-extern "C" {
-#include <histedit.h>
-}
-
-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<string> 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<int> 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<const char*> &args,
+ const char **in_file, const char ** out_file,
+ ceph_tool_mode_t *mode, vector<const char*> *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<string, ClassVersionMap>::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; i<PAXOS_NUM; i++) {
- MMonObserve *m = new MMonObserve(g.mc.monmap.fsid, i, map_ver[i]);
- dout(1) << "mon" << " <- observe " << get_paxos_name(i) << dendl;
- g.mc.send_mon_message(m);
- sent = true;
}
-
- registered.clear();
- float seconds = g_conf.paxos_observer_timeout/2;
- dout(1) << " refresh after " << seconds << " with same mon" << dendl;
- g.timer.add_event_after(seconds, new C_ObserverRefresh(false));
}
-static void handle_ack(MMonCommandAck *ack)
+static int safe_read(int fd, char *buf, size_t count)
{
- g.lock.Lock();
- reply = true;
- reply_from = ack->get_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<string>& 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<const char*> args;
+ argv_to_vec(argc, argv, args);
+ env_to_vec(args);
- vector<string> cmd;
- const char *infile = 0;
- const char *outfile = 0;
- for (int i=0; i<argc; i++) {
- if (strcmp(argv[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<const char*> 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<std::string> &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 <outfile)" << std::endl;
+ if (ceph_tool_common_init(mode)) {
+ cerr << "ceph_tool_common_init failed." << std::endl;
return 1;
}
- if (strcmp(outfile, "-") == 0) {
- // write to stdout
- fwrite(odata.c_str(), len, 1, stdout);
- return 0;
- }
-
- // write to file
- odata.write_file(outfile);
- cout << g_clock.now() << " wrote " << len << " byte payload to "
- << outfile << std::endl;
- return 0;
-}
-
-int ceph_tool_common_init(ceph_tool_mode_t mode)
-{
- ceph_tool_mode = mode;
-
- // get monmap
- if (g.mc.build_initial_monmap() < 0)
- return -1;
-
- // initialize tokenizer
- tok = tok_init(NULL);
-
- // start up network
- messenger = new SimpleMessenger();
- messenger->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<string> 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;
}
+++ /dev/null
-#ifndef CEPH_TOOL_H
-#define CEPH_TOOL_H
-
-#include "common/Cond.h"
-#include "common/Mutex.h"
-#include "mon/MonClient.h"
-#include "mon/PGMap.h"
-#include "mds/MDSMap.h"
-#include "osd/OSDMap.h"
-#include "common/Timer.h"
-
-#include <iosfwd>
-#include <stdint.h>
-
-#define OSD_MON_UPDATE (1<<0)
-#define MDS_MON_UPDATE (1<<1)
-#define PG_MON_UPDATE (1<<2)
-#define MON_MON_UPDATE (1<<3)
-#define EVERYTHING_UPDATE 0xffffffff
-
-enum ceph_tool_mode_t {
- CEPH_TOOL_MODE_CLI_INPUT = 0,
- CEPH_TOOL_MODE_OBSERVER = 1,
- CEPH_TOOL_MODE_ONE_SHOT_OBSERVER = 2,
- CEPH_TOOL_MODE_GUI = 3
-};
-
-// tool/ceph.cc
-struct ceph_tool_data
-{
- PGMap pgmap;
- MDSMap mdsmap;
- OSDMap osdmap;
- MonClient mc;
-
- // Which aspects of the cluster have been updated recently?
- uint32_t updates;
-
- // The main log for ceph-tool
- std::ostream *log;
-
- // Used by the GUI to read from the log.
- // NULL if there is no GUI active.
- std::ostringstream *slog;
-
- // The ceph-tool lock
- Mutex lock;
- SafeTimer timer;
-
- // A condition variable used to wake up the GUI thread
- Cond gui_cond;
-
- ceph_tool_data() :
- updates(EVERYTHING_UPDATE),
- log(&std::cout),
- slog(NULL),
- lock("ceph.cc lock"), timer(lock)
- {
- }
-};
-
-// tool/ceph.cc
-extern struct ceph_tool_data g;
-int ceph_tool_do_cli();
-int run_command(const char *line);
-void send_observe_requests();
-int ceph_tool_common_init(ceph_tool_mode_t mode);
-int ceph_tool_cli_input(std::vector<std::string> &cmd, const char *outfile,
- bufferlist &indata);
-int ceph_tool_messenger_shutdown();
-int ceph_tool_common_shutdown();
-
-#endif
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
- * 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 <limits.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <iostream>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <vector>
-
-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<const char*> &args,
- const char **in_file, const char ** out_file,
- ceph_tool_mode_t *mode, vector<const char*> *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<const char*> 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<const char*> 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<string> 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;
-}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <sys/stat.h>
+#include <iostream>
+#include <string>
+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 <envz.h>
+#endif // DARWIN
+
+#include <memory>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+extern "C" {
+#include <histedit.h>
+}
+
+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<string> 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<int> 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<string, ClassVersionMap>::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; i<PAXOS_NUM; i++) {
+ MMonObserve *m = new MMonObserve(g.mc.monmap.fsid, i, map_ver[i]);
+ dout(1) << "mon" << " <- observe " << get_paxos_name(i) << dendl;
+ g.mc.send_mon_message(m);
+ sent = true;
+ }
+
+ registered.clear();
+ float seconds = g_conf.paxos_observer_timeout/2;
+ dout(1) << " refresh after " << seconds << " with same mon" << dendl;
+ g.timer.add_event_after(seconds, new C_ObserverRefresh(false));
+}
+
+static void handle_ack(MMonCommandAck *ack)
+{
+ g.lock.Lock();
+ reply = true;
+ reply_from = ack->get_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<string>& 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<string> cmd;
+ const char *infile = 0;
+ const char *outfile = 0;
+ for (int i=0; i<argc; i++) {
+ if (strcmp(argv[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<std::string> &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 <outfile)" << std::endl;
+ return 1;
+ }
+ if (strcmp(outfile, "-") == 0) {
+ // write to stdout
+ fwrite(odata.c_str(), len, 1, stdout);
+ return 0;
+ }
+
+ // write to file
+ odata.write_file(outfile);
+ cout << g_clock.now() << " wrote " << len << " byte payload to "
+ << outfile << std::endl;
+ return 0;
+}
+
+int ceph_tool_common_init(ceph_tool_mode_t mode)
+{
+ ceph_tool_mode = mode;
+
+ // get monmap
+ if (g.mc.build_initial_monmap() < 0)
+ return -1;
+
+ // initialize tokenizer
+ tok = tok_init(NULL);
+
+ // start up network
+ messenger = new SimpleMessenger();
+ messenger->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;
+}
--- /dev/null
+#ifndef CEPH_TOOLS_COMMON_DOT_H
+#define CEPH_TOOLS_COMMON_DOT_H
+
+#include "common/Cond.h"
+#include "common/Mutex.h"
+#include "mon/MonClient.h"
+#include "mon/PGMap.h"
+#include "mds/MDSMap.h"
+#include "osd/OSDMap.h"
+#include "common/Timer.h"
+
+#include <iosfwd>
+#include <stdint.h>
+
+#define OSD_MON_UPDATE (1<<0)
+#define MDS_MON_UPDATE (1<<1)
+#define PG_MON_UPDATE (1<<2)
+#define MON_MON_UPDATE (1<<3)
+#define EVERYTHING_UPDATE 0xffffffff
+
+enum ceph_tool_mode_t {
+ CEPH_TOOL_MODE_CLI_INPUT = 0,
+ CEPH_TOOL_MODE_OBSERVER = 1,
+ CEPH_TOOL_MODE_ONE_SHOT_OBSERVER = 2,
+ CEPH_TOOL_MODE_GUI = 3
+};
+
+// tool/ceph.cc
+struct ceph_tool_data
+{
+ PGMap pgmap;
+ MDSMap mdsmap;
+ OSDMap osdmap;
+ MonClient mc;
+
+ // Which aspects of the cluster have been updated recently?
+ uint32_t updates;
+
+ // The main log for ceph-tool
+ std::ostream *log;
+
+ // Used by the GUI to read from the log.
+ // NULL if there is no GUI active.
+ std::ostringstream *slog;
+
+ // The ceph-tool lock
+ Mutex lock;
+ SafeTimer timer;
+
+ // A condition variable used to wake up the GUI thread
+ Cond gui_cond;
+
+ ceph_tool_data() :
+ updates(EVERYTHING_UPDATE),
+ log(&std::cout),
+ slog(NULL),
+ lock("ceph.cc lock"), timer(lock)
+ {
+ }
+};
+
+// tool/ceph.cc
+extern struct ceph_tool_data g;
+int ceph_tool_do_cli();
+int run_command(const char *line);
+void send_observe_requests();
+int ceph_tool_common_init(ceph_tool_mode_t mode);
+int ceph_tool_cli_input(std::vector<std::string> &cmd, const char *outfile,
+ bufferlist &indata);
+int ceph_tool_messenger_shutdown();
+int ceph_tool_common_shutdown();
+
+#endif
*
*/
-#include "ceph.h"
#include "common/common_init.h"
#include "config.h"
+#include "tools/common.h"
#include <iostream>
#include <sstream>
#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"