]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: add new "tell" infrastructure.
authorGreg Farnum <gregory.farnum@dreamhost.com>
Fri, 10 Jun 2011 00:21:33 +0000 (17:21 -0700)
committerGreg Farnum <gregory.farnum@dreamhost.com>
Fri, 10 Jun 2011 00:22:37 +0000 (17:22 -0700)
This lets you issue commands
like "ceph mon tell 0 heap start_profiler". Hurray!

Signed-off-by: Greg Farnum <gregory.farnum@dreamhost.com>
src/mon/Monitor.cc
src/mon/Monitor.h

index f7347aa10e20f0fbcd102ce26c507e9499d07ed6..1cb4872da7aa2d1e60545f73aac20a14718bcb93 100644 (file)
@@ -316,7 +316,8 @@ void Monitor::handle_command(MMonCommand *m)
       pgmon()->dispatch(m);
       return;
     }
-    if (m->cmd[0] == "mon") {
+    if (m->cmd[0] == "mon" &&
+        ((m->cmd.size() < 3 ) || m->cmd[1] != "tell")) {
       monmon()->dispatch(m);
       return;
     }
@@ -378,6 +379,46 @@ void Monitor::handle_command(MMonCommand *m)
        ss << " " << combined;
       rs = ss.str();
       r = 0;
+    } else if (m->cmd[0] == "mon" && m->cmd.size() >= 3 && m->cmd[1] == "tell") {
+      if (m->cmd[2] == "*") { // send to all mons and do myself
+        char *num = new char[8];
+        for (unsigned i = 0; i < monmap->size(); ++i) {
+          if (monmap->get_inst(i) != messenger->get_myinst()) {
+            sprintf(num, "%d", i);
+            m->cmd[2] = num;
+            messenger->send_message(m, monmap->get_inst(i));
+          }
+        }
+        handle_mon_tell(m);
+        rs = "delivered command to all mons";
+        r = 0;
+      } else {
+        // find target
+        int target = atoi(m->cmd[2].c_str());
+        stringstream ss;
+        if (target == 0 && m->cmd[2] != "0") {
+          ss << "could not parse target " << m->cmd[2];
+          rs = ss.str();
+        } else {
+          // send to target, or handle if it's me
+          if (monmap->get_inst(target) != messenger->get_myinst()) {
+            messenger->send_message(m, monmap->get_inst(target));
+            ss << "forwarded to target mon" << m->cmd[2];
+            rs = ss.str();
+            r = 0;
+          }
+          else {
+            handle_mon_tell(m);
+            rs = "interpreting...(see clog for more information)";
+            r = 0;
+          }
+        }
+        if (m->get_source().is_mon()) {
+          // don't respond directly to sender, just put in log and back out
+          m->put();
+          return;
+        }
+      }
     }
   } else 
     rs = "no command";
@@ -385,6 +426,34 @@ void Monitor::handle_command(MMonCommand *m)
   reply_command(m, r, rs, rdata, 0);
 }
 
+/**
+ * Handle commands of the format "ceph mon tell x", where x
+ * is a mon number. This function presumes it's supposed
+ * to execute the actual command; delivery is handled by
+ */
+void Monitor::handle_mon_tell(MMonCommand *m)
+{
+  dout(0) << "handle_command " << *m << dendl;
+  stringstream ss;
+
+  // remove monitor direction instructions
+  m->cmd.erase(m->cmd.begin());
+  m->cmd.erase(m->cmd.begin());
+  m->cmd.erase(m->cmd.begin());
+
+  if ((m->cmd.size()) && (m->cmd[0] == "heap")) {
+    if (!ceph_using_tcmalloc())
+      ss << "tcmalloc not enabled, can't use heap profiler commands\n";
+    else
+      ceph_heap_profiler_handle_command(m->cmd, clog);
+  } else {
+    ss << "unrecognized command " << m->cmd;
+  }
+
+  if (!ss.eof())
+    clog.error(ss);
+}
+
 void Monitor::reply_command(MMonCommand *m, int rc, const string &rs, version_t version)
 {
   bufferlist rdata;
index a780e004e01092d79260c2e8da8a6216a2cf9dd2..b792fd6beb114f30720338ec025838f83f9b9c58 100644 (file)
@@ -39,6 +39,8 @@
 
 #include "auth/cephx/CephxKeyServer.h"
 
+#include "perfglue/heap_profiler.h"
+
 #include <memory>
 
 class MonitorStore;
@@ -147,6 +149,7 @@ public:
   void handle_subscribe(MMonSubscribe *m);
   void handle_mon_get_map(MMonGetMap *m);
   void handle_command(class MMonCommand *m);
+  void handle_mon_tell(MMonCommand *m);
   void handle_observe(MMonObserve *m);
   void handle_route(MRoute *m);