]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cephtool: rename tools files
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Tue, 14 Dec 2010 12:59:05 +0000 (04:59 -0800)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Tue, 14 Dec 2010 14:13:50 +0000 (06:13 -0800)
Rename tools files to be more consistent. For example, the main()
function for ./ceph should be in ceph.cc.

Signed-off-by: Colin McCabe <colinm@hq.newdream.net>
src/Makefile.am
src/tools/ceph.cc
src/tools/ceph.h [deleted file]
src/tools/cmd.cc [deleted file]
src/tools/common.cc [new file with mode: 0644]
src/tools/common.h [new file with mode: 0644]
src/tools/gceph.cc
src/tools/gui.cc

index ec05a2bd26d22d6aced71ee9cb3a97ba411cdd32..07c12a0e3c89d284edef898b387a23d969b3f20c 100644 (file)
@@ -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
 
index 03e03caaa597f15a05a055c70c475657fe4dd6e0..6236fb92a3abf91ecff3041062f6acde639b3abf 100644 (file)
-// -*- 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(&notify->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;
 }
diff --git a/src/tools/ceph.h b/src/tools/ceph.h
deleted file mode 100644 (file)
index 7ea2782..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#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
diff --git a/src/tools/cmd.cc b/src/tools/cmd.cc
deleted file mode 100644 (file)
index a380e6e..0000000
+++ /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 <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;
-}
diff --git a/src/tools/common.cc b/src/tools/common.cc
new file mode 100644 (file)
index 0000000..5bbbca7
--- /dev/null
@@ -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 <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(&notify->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;
+}
diff --git a/src/tools/common.h b/src/tools/common.h
new file mode 100644 (file)
index 0000000..058eaad
--- /dev/null
@@ -0,0 +1,73 @@
+#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
index cbc04c7084c6614a7be493ce460c18586b5bce27..6cc42061126e43c494d7719a653436b7f649be02 100644 (file)
@@ -13,9 +13,9 @@
  *
  */
 
-#include "ceph.h"
 #include "common/common_init.h"
 #include "config.h"
+#include "tools/common.h"
 
 #include <iostream>
 #include <sstream>
index 3ea6da9bfb343ed602dc8de7c5dd34be65631b37..eef4666c74bc40cacff9bb0a2b1a090dd368e0fb 100644 (file)
@@ -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"