~ubuntu-branches/ubuntu/quantal/ceph/quantal

« back to all changes in this revision

Viewing changes to src/tools/ceph.cc

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum, Clint Byrum, Micah Gersten
  • Date: 2011-02-12 22:50:26 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110212225026-yyyw4tk0msgql3ul
Tags: 0.24.2-0ubuntu1
[ Clint Byrum <clint@ubuntu.com> ]
* New upstream release. (LP: #658670, LP: #684011)
* debian/patches/fix-mkcephfs.patch: dropped (applied upstream)
* Removed .la files from libceph1-dev, libcrush1-dev and 
  librados1-dev (per Debian policy v3.9.1 10.2).
* debian/control: adding pkg-config as a build dependency
* debian/control: depend on libcrypto++-dev instead of libssl-dev
* debian/watch: added watch file

[ Micah Gersten <micahg@ubuntu.com> ]
* debian/control: add Homepage

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
 
2
// vim: ts=8 sw=2 smarttab
 
3
/*
 
4
 * Ceph - scalable distributed file system
 
5
 *
 
6
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 
7
 *
 
8
 * This is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Lesser General Public
 
10
 * License version 2.1, as published by the Free Software 
 
11
 * Foundation.  See file COPYING.
 
12
 * 
 
13
 */
 
14
 
 
15
#include <sys/stat.h>
 
16
#include <iostream>
 
17
#include <string>
 
18
using namespace std;
 
19
 
 
20
#include "acconfig.h"
 
21
#include "messages/MMonCommand.h"
 
22
#include "messages/MMonCommandAck.h"
 
23
#include "mon/MonClient.h"
 
24
#include "mon/MonMap.h"
 
25
#include "msg/SimpleMessenger.h"
 
26
#include "tools/ceph.h"
 
27
 
 
28
#include "common/Cond.h"
 
29
#include "common/Mutex.h"
 
30
#include "common/Timer.h"
 
31
#include "common/common_init.h"
 
32
 
 
33
#ifndef DARWIN
 
34
#include <envz.h>
 
35
#endif // DARWIN
 
36
 
 
37
#include <memory>
 
38
#include <sys/types.h>
 
39
#include <sys/stat.h>
 
40
#include <fcntl.h>
 
41
 
 
42
extern "C" {
 
43
#include <histedit.h>
 
44
}
 
45
 
 
46
enum CephToolMode {
 
47
  CEPH_TOOL_MODE_CLI_INPUT = 0,
 
48
  CEPH_TOOL_MODE_OBSERVER = 1,
 
49
  CEPH_TOOL_MODE_ONE_SHOT_OBSERVER = 2,
 
50
  CEPH_TOOL_MODE_GUI = 3
 
51
};
 
52
 
 
53
static enum CephToolMode ceph_tool_mode(CEPH_TOOL_MODE_CLI_INPUT);
 
54
 
 
55
struct ceph_tool_data g;
 
56
 
 
57
static Cond cmd_cond;
 
58
static SimpleMessenger *messenger = 0;
 
59
static Tokenizer *tok;
 
60
 
 
61
static const char *outfile = 0;
 
62
 
 
63
 
 
64
 
 
65
// sync command
 
66
vector<string> pending_cmd;
 
67
bufferlist pending_bl;
 
68
bool reply;
 
69
string reply_rs;
 
70
int reply_rc;
 
71
bufferlist reply_bl;
 
72
entity_inst_t reply_from;
 
73
Context *resend_event = 0;
 
74
 
 
75
 
 
76
 
 
77
// observe (push)
 
78
#include "mon/PGMap.h"
 
79
#include "osd/OSDMap.h"
 
80
#include "mds/MDSMap.h"
 
81
#include "include/LogEntry.h"
 
82
#include "include/ClassLibrary.h"
 
83
 
 
84
#include "mon/mon_types.h"
 
85
 
 
86
#include "messages/MMonObserve.h"
 
87
#include "messages/MMonObserveNotify.h"
 
88
 
 
89
 
 
90
static set<int> registered, seen;
 
91
 
 
92
version_t map_ver[PAXOS_NUM];
 
93
 
 
94
static void handle_observe(MMonObserve *observe)
 
95
{
 
96
  dout(1) << observe->get_source() << " -> " << get_paxos_name(observe->machine_id)
 
97
          << " registered" << dendl;
 
98
  g.lock.Lock();
 
99
  registered.insert(observe->machine_id);  
 
100
  g.lock.Unlock();
 
101
  observe->put();
 
102
}
 
103
 
 
104
static void handle_notify(MMonObserveNotify *notify)
 
105
{
 
106
  utime_t now = g_clock.now();
 
107
 
 
108
  dout(1) << notify->get_source() << " -> " << get_paxos_name(notify->machine_id)
 
109
          << " v" << notify->ver
 
110
          << (notify->is_latest ? " (latest)" : "")
 
111
          << dendl;
 
112
  
 
113
  if (ceph_fsid_compare(&notify->fsid, &g.mc.monmap.fsid)) {
 
114
    dout(0) << notify->get_source_inst() << " notify fsid " << notify->fsid << " != " << g.mc.monmap.fsid << dendl;
 
115
    notify->put();
 
116
    return;
 
117
  }
 
118
 
 
119
  if (map_ver[notify->machine_id] >= notify->ver)
 
120
    return;
 
121
 
 
122
  switch (notify->machine_id) {
 
123
  case PAXOS_PGMAP:
 
124
    {
 
125
      bufferlist::iterator p = notify->bl.begin();
 
126
      if (notify->is_latest) {
 
127
        g.pgmap.decode(p);
 
128
      } else {
 
129
        PGMap::Incremental inc;
 
130
        inc.decode(p);
 
131
        g.pgmap.apply_incremental(inc);
 
132
      }
 
133
      *g.log << now << "    pg " << g.pgmap << std::endl;
 
134
      g.updates |= PG_MON_UPDATE;
 
135
      break;
 
136
    }
 
137
 
 
138
  case PAXOS_MDSMAP:
 
139
    g.mdsmap.decode(notify->bl);
 
140
    *g.log << now << "   mds " << g.mdsmap << std::endl;
 
141
    g.updates |= MDS_MON_UPDATE;
 
142
    break;
 
143
 
 
144
  case PAXOS_OSDMAP:
 
145
    {
 
146
      if (notify->is_latest) {
 
147
        g.osdmap.decode(notify->bl);
 
148
      } else {
 
149
        OSDMap::Incremental inc(notify->bl);
 
150
        g.osdmap.apply_incremental(inc);
 
151
      }
 
152
      *g.log << now << "   osd " << g.osdmap << std::endl;
 
153
    }
 
154
    g.updates |= OSD_MON_UPDATE;
 
155
    break;
 
156
 
 
157
  case PAXOS_LOG:
 
158
    {
 
159
      bufferlist::iterator p = notify->bl.begin();
 
160
      if (notify->is_latest) {
 
161
        LogSummary summary;
 
162
        ::decode(summary, p);
 
163
        // show last log message
 
164
        if (!summary.tail.empty())
 
165
          *g.log << now << "   log " << summary.tail.back() << std::endl;
 
166
      } else {
 
167
        LogEntry le;
 
168
        __u8 v;
 
169
        ::decode(v, p);
 
170
        while (!p.end()) {
 
171
          le.decode(p);
 
172
          *g.log << now << "   log " << le << std::endl;
 
173
        }
 
174
      }
 
175
      break;
 
176
    }
 
177
 
 
178
  case PAXOS_CLASS:
 
179
    {
 
180
      bufferlist::iterator p = notify->bl.begin();
 
181
      if (notify->is_latest) {
 
182
        ClassLibrary list;
 
183
        ::decode(list, p);
 
184
        // show the first class info
 
185
        map<string, ClassVersionMap>::iterator mapiter = list.library_map.begin();
 
186
        if (mapiter != list.library_map.end()) {
 
187
          ClassVersionMap& map = mapiter->second;
 
188
          tClassVersionMap::iterator iter = map.begin();
 
189
 
 
190
          if (iter != map.end())
 
191
            *g.log << now << "   class " <<  iter->second << std::endl;
 
192
        }
 
193
      } else {
 
194
        __u8 v;
 
195
        ::decode(v, p);
 
196
        while (!p.end()) {
 
197
          ClassLibraryIncremental inc;
 
198
          ::decode(inc, p);
 
199
          ClassInfo info;
 
200
          inc.decode_info(info);
 
201
          *g.log << now << "   class " << info << std::endl;
 
202
        }
 
203
      }
 
204
      break;
 
205
    }
 
206
 
 
207
  case PAXOS_AUTH:
 
208
    {
 
209
#if 0
 
210
      bufferlist::iterator p = notify->bl.begin();
 
211
      if (notify->is_latest) {
 
212
        KeyServerData data;
 
213
        ::decode(data, p);
 
214
        *g.log << now << "   auth " << std::endl;
 
215
      } else {
 
216
        while (!p.end()) {
 
217
          AuthMonitor::Incremental inc;
 
218
          inc.decode(p);
 
219
          *g.log << now << "   auth " << inc.name.to_str() << std::endl;
 
220
        }
 
221
      }
 
222
#endif
 
223
      /* ignoring auth incremental.. don't want to decode it */
 
224
      break;
 
225
    }
 
226
 
 
227
  case PAXOS_MONMAP:
 
228
    {
 
229
      g.mc.monmap.decode(notify->bl);
 
230
      *g.log << now << "   mon " << g.mc.monmap << std::endl;
 
231
    }
 
232
    break;
 
233
 
 
234
  default:
 
235
    *g.log << now << "  ignoring unknown machine id " << notify->machine_id << std::endl;
 
236
  }
 
237
 
 
238
  map_ver[notify->machine_id] = notify->ver;
 
239
 
 
240
  // have we seen them all?
 
241
  seen.insert(notify->machine_id);
 
242
  switch (ceph_tool_mode) {
 
243
    case CEPH_TOOL_MODE_ONE_SHOT_OBSERVER:
 
244
      if (seen.size() == PAXOS_NUM) {
 
245
        messenger->shutdown();
 
246
      }
 
247
      break;
 
248
    case CEPH_TOOL_MODE_GUI:
 
249
      g.gui_cond.Signal();
 
250
      break;
 
251
    default:
 
252
      // do nothing
 
253
      break;
 
254
  }
 
255
 
 
256
  notify->put();
 
257
}
 
258
 
 
259
static void send_observe_requests();
 
260
 
 
261
class C_ObserverRefresh : public Context {
 
262
public:
 
263
  bool newmon;
 
264
  C_ObserverRefresh(bool n) : newmon(n) {}
 
265
  void finish(int r) {
 
266
    send_observe_requests();
 
267
  }
 
268
};
 
269
 
 
270
static void send_observe_requests()
 
271
{
 
272
  dout(1) << "send_observe_requests " << dendl;
 
273
 
 
274
  bool sent = false;
 
275
  for (int i=0; i<PAXOS_NUM; i++) {
 
276
    MMonObserve *m = new MMonObserve(g.mc.monmap.fsid, i, map_ver[i]);
 
277
    dout(1) << "mon" << " <- observe " << get_paxos_name(i) << dendl;
 
278
    g.mc.send_mon_message(m);
 
279
    sent = true;
 
280
  }
 
281
 
 
282
  registered.clear();
 
283
  float seconds = g_conf.paxos_observer_timeout/2;
 
284
  dout(1) << " refresh after " << seconds << " with same mon" << dendl;
 
285
  g.timer.add_event_after(seconds, new C_ObserverRefresh(false));
 
286
}
 
287
 
 
288
static void handle_ack(MMonCommandAck *ack)
 
289
{
 
290
  g.lock.Lock();
 
291
  reply = true;
 
292
  reply_from = ack->get_source_inst();
 
293
  reply_rs = ack->rs;
 
294
  reply_rc = ack->r;
 
295
  reply_bl = ack->get_data();
 
296
  cmd_cond.Signal();
 
297
  if (resend_event) {
 
298
    g.timer.cancel_event(resend_event);
 
299
    resend_event = 0;
 
300
  }
 
301
  g.lock.Unlock();
 
302
  ack->put();
 
303
}
 
304
 
 
305
static void send_command()
 
306
{
 
307
  version_t last_seen_version = 0;
 
308
  MMonCommand *m = new MMonCommand(g.mc.monmap.fsid, last_seen_version);
 
309
  m->cmd = pending_cmd;
 
310
  m->set_data(pending_bl);
 
311
 
 
312
  *g.log << g_clock.now() << " mon" << " <- " << pending_cmd << std::endl;
 
313
  g.mc.send_mon_message(m);
 
314
}
 
315
 
 
316
class Admin : public Dispatcher {
 
317
  bool ms_dispatch(Message *m) {
 
318
    switch (m->get_type()) {
 
319
    case MSG_MON_COMMAND_ACK:
 
320
      handle_ack((MMonCommandAck*)m);
 
321
      break;
 
322
    case MSG_MON_OBSERVE_NOTIFY:
 
323
      handle_notify((MMonObserveNotify *)m);
 
324
      break;
 
325
    case MSG_MON_OBSERVE:
 
326
      handle_observe((MMonObserve *)m);
 
327
      break;
 
328
    case CEPH_MSG_MON_MAP:
 
329
      m->put();
 
330
      break;
 
331
    default:
 
332
      return false;
 
333
    }
 
334
    return true;
 
335
  }
 
336
 
 
337
  void ms_handle_connect(Connection *con) {
 
338
    if (con->get_peer_type() == CEPH_ENTITY_TYPE_MON) {
 
339
      g.lock.Lock();
 
340
      if (ceph_tool_mode != CEPH_TOOL_MODE_CLI_INPUT) {
 
341
        send_observe_requests();
 
342
      }
 
343
      if (pending_cmd.size())
 
344
        send_command();
 
345
      g.lock.Unlock();
 
346
    }
 
347
  }
 
348
  bool ms_handle_reset(Connection *con) { return false; }
 
349
  void ms_handle_remote_reset(Connection *con) {}
 
350
 
 
351
} dispatcher;
 
352
 
 
353
int do_command(vector<string>& cmd, bufferlist& bl, string& rs, bufferlist& rbl)
 
354
{
 
355
  Mutex::Locker l(g.lock);
 
356
 
 
357
  pending_cmd = cmd;
 
358
  pending_bl = bl;
 
359
  reply = false;
 
360
  
 
361
  send_command();
 
362
 
 
363
  while (!reply)
 
364
    cmd_cond.Wait(g.lock);
 
365
 
 
366
  rs = rs;
 
367
  rbl = reply_bl;
 
368
  *g.log << g_clock.now() << " "
 
369
       << reply_from.name << " -> '"
 
370
       << reply_rs << "' (" << reply_rc << ")"
 
371
       << std::endl;
 
372
 
 
373
  return reply_rc;
 
374
}
 
375
 
 
376
static void usage() 
 
377
{
 
378
  cerr << "usage: ceph [options] [commands]" << std::endl;
 
379
  cerr << "If no commands are specified, enter interactive mode.\n";
 
380
  cerr << "Commands:" << std::endl;
 
381
  cerr << "   stop              -- cleanly shut down file system" << std::endl
 
382
       << "   (osd|pg|mds) stat -- get monitor subsystem status" << std::endl
 
383
       << "   ..." << std::endl;
 
384
  cerr << "Options:" << std::endl;
 
385
  cerr << "   -i infile\n";
 
386
  cerr << "   -o outfile\n";
 
387
  cerr << "        specify input or output file (for certain commands)\n";
 
388
  cerr << "   -s or --status\n";
 
389
  cerr << "        print current system status\n";
 
390
  cerr << "   -w or --watch\n";
 
391
  cerr << "        watch system status changes in real time (push)\n";
 
392
  cerr << "   -g or --gui\n";
 
393
  cerr << "        watch system status changes graphically\n";
 
394
  generic_client_usage();
 
395
}
 
396
 
 
397
static const char *cli_prompt(EditLine *e)
 
398
{
 
399
  return "ceph> ";
 
400
}
 
401
 
 
402
int do_cli()
 
403
{
 
404
  /* emacs style */
 
405
  EditLine *el = el_init("ceph", stdin, stdout, stderr);
 
406
  el_set(el, EL_PROMPT, &cli_prompt);
 
407
  el_set(el, EL_EDITOR, "emacs");
 
408
 
 
409
  History *myhistory = history_init();
 
410
  if (myhistory == 0) {
 
411
    fprintf(stderr, "history could not be initialized\n");
 
412
    return 1;
 
413
  }
 
414
 
 
415
  HistEvent ev;
 
416
 
 
417
  /* Set the size of the history */
 
418
  history(myhistory, &ev, H_SETSIZE, 800);
 
419
 
 
420
  /* This sets up the call back functions for history functionality */
 
421
  el_set(el, EL_HIST, history, myhistory);
 
422
 
 
423
  while (1) {
 
424
    int chars_read;
 
425
    const char *line = el_gets(el, &chars_read);
 
426
 
 
427
    //*g.log << "typed '" << line << "'" << std::endl;
 
428
 
 
429
    if (chars_read == 0) {
 
430
      *g.log << "quit" << std::endl;
 
431
      break;
 
432
    }
 
433
 
 
434
    history(myhistory, &ev, H_ENTER, line);
 
435
 
 
436
    if (run_command(line))
 
437
      break;
 
438
  }
 
439
 
 
440
  history_end(myhistory);
 
441
  el_end(el);
 
442
 
 
443
  return 0;
 
444
}
 
445
 
 
446
int run_command(const char *line)
 
447
{
 
448
  if (strcmp(line, "quit\n") == 0)
 
449
    return 1;
 
450
 
 
451
  int argc;
 
452
  const char **argv;
 
453
  tok_str(tok, line, &argc, &argv);
 
454
  tok_reset(tok);
 
455
 
 
456
  vector<string> cmd;
 
457
  const char *infile = 0;
 
458
  const char *outfile = 0;
 
459
  for (int i=0; i<argc; i++) {
 
460
    if (strcmp(argv[i], ">") == 0 && i < argc-1) {
 
461
      outfile = argv[++i];
 
462
      continue;
 
463
    }
 
464
    if (argv[i][0] == '>') {
 
465
      outfile = argv[i] + 1;
 
466
      while (*outfile == ' ') outfile++;
 
467
      continue;
 
468
    }
 
469
    if (strcmp(argv[i], "<") == 0 && i < argc-1) {
 
470
      infile = argv[++i];
 
471
      continue;
 
472
    }
 
473
    if (argv[i][0] == '<') {
 
474
      infile = argv[i] + 1;
 
475
      while (*infile == ' ') infile++;
 
476
      continue;
 
477
    }
 
478
    cmd.push_back(argv[i]);
 
479
  }
 
480
  if (cmd.empty())
 
481
    return 0;
 
482
 
 
483
  bufferlist in;
 
484
  if (cmd.size() == 1 && cmd[0] == "print") {
 
485
    *g.log << "----" << std::endl;
 
486
    write(1, in.c_str(), in.length());
 
487
    *g.log << "---- (" << in.length() << " bytes)" << std::endl;
 
488
    return 0;
 
489
  }
 
490
 
 
491
  //out << "cmd is " << cmd << std::endl;
 
492
 
 
493
  bufferlist out;
 
494
  if (infile) {
 
495
    if (out.read_file(infile) == 0) {
 
496
      *g.log << "read " << out.length() << " from " << infile << std::endl;
 
497
    } else {
 
498
      char buf[80];
 
499
      *g.log << "couldn't read from " << infile << ": " << strerror_r(errno, buf, sizeof(buf)) << std::endl;
 
500
      return 0;
 
501
    }
 
502
  }
 
503
 
 
504
  in.clear();
 
505
  string rs;
 
506
  do_command(cmd, out, rs, in);
 
507
 
 
508
  if (in.length() == 0)
 
509
    return 0;
 
510
 
 
511
  if (outfile) {
 
512
    if (strcmp(outfile, "-") == 0) {
 
513
      *g.log << "----" << std::endl;
 
514
      write(1, in.c_str(), in.length());
 
515
      *g.log << "---- (" << in.length() << " bytes)" << std::endl;
 
516
    }
 
517
    else {
 
518
      in.write_file(outfile);
 
519
      *g.log << "wrote " << in.length() << " to "
 
520
             << outfile << std::endl;
 
521
    }
 
522
  }
 
523
  else {
 
524
    *g.log << "got " << in.length() << " byte payload; 'print' "
 
525
      << "to dump to terminal, or add '>-' to command." << std::endl;
 
526
  }
 
527
  return 0;
 
528
}
 
529
 
 
530
int main(int argc, const char **argv)
 
531
{
 
532
  ostringstream gss;
 
533
  DEFINE_CONF_VARS(usage);
 
534
  vector<const char*> args;
 
535
  argv_to_vec(argc, argv, args);
 
536
  env_to_vec(args);
 
537
 
 
538
  ceph_set_default_id("admin");
 
539
  
 
540
  common_set_defaults(false);
 
541
  common_init(args, "ceph", true);
 
542
 
 
543
  vec_to_argv(args, argc, argv);
 
544
 
 
545
  srand(getpid());
 
546
 
 
547
  // default to 'admin' user
 
548
  if (!g_conf.id || !g_conf.id[0])
 
549
    g_conf.id = strdup("admin");
 
550
 
 
551
  char *fname;
 
552
  bufferlist indata;
 
553
  vector<const char*> nargs;
 
554
 
 
555
  FOR_EACH_ARG(args) {
 
556
    if (CONF_ARG_EQ("out_file", 'o')) {
 
557
      CONF_SAFE_SET_ARG_VAL(&outfile, OPT_STR);
 
558
    } else if (CONF_ARG_EQ("in_file", 'i')) {
 
559
      CONF_SAFE_SET_ARG_VAL(&fname, OPT_STR);
 
560
      int fd = ::open(fname, O_RDONLY);
 
561
      struct stat st;
 
562
      if (::fstat(fd, &st) == 0) {
 
563
        indata.push_back(buffer::create(st.st_size));
 
564
        indata.zero();
 
565
        ::read(fd, indata.c_str(), st.st_size);
 
566
        ::close(fd);
 
567
        cout << "read " << st.st_size << " bytes from " << args[i] << std::endl;
 
568
      }
 
569
    } else if (CONF_ARG_EQ("status", 's')) {
 
570
      ceph_tool_mode = CEPH_TOOL_MODE_ONE_SHOT_OBSERVER;
 
571
    } else if (CONF_ARG_EQ("watch", 'w')) {
 
572
      ceph_tool_mode = CEPH_TOOL_MODE_OBSERVER;
 
573
    } else if (CONF_ARG_EQ("help", 'h')) {
 
574
      usage();
 
575
    } else if (CONF_ARG_EQ("gui", 'g')) {
 
576
      ceph_tool_mode = CEPH_TOOL_MODE_GUI;
 
577
    } else if (args[i][0] == '-' && nargs.empty()) {
 
578
      cerr << "unrecognized option " << args[i] << std::endl;
 
579
      usage();
 
580
    } else
 
581
      nargs.push_back(args[i]);
 
582
  }
 
583
 
 
584
  // build command
 
585
  vector<string> vcmd;
 
586
  string cmd;
 
587
  for (unsigned i=0; i<nargs.size(); i++) {
 
588
    if (i) cmd += " ";
 
589
    cmd += nargs[i];
 
590
    vcmd.push_back(string(nargs[i]));
 
591
  }
 
592
 
 
593
  // get monmap
 
594
  if (g.mc.build_initial_monmap() < 0)
 
595
    return -1;
 
596
  
 
597
  // initialize tokenizer
 
598
  tok = tok_init(NULL);
 
599
 
 
600
  // start up network
 
601
  messenger = new SimpleMessenger();
 
602
  messenger->register_entity(entity_name_t::CLIENT());
 
603
  messenger->add_dispatcher_head(&dispatcher);
 
604
 
 
605
  messenger->start();
 
606
 
 
607
  g.lock.Lock();
 
608
  g.timer.init();
 
609
  g.lock.Unlock();
 
610
 
 
611
  g.mc.set_messenger(messenger);
 
612
  g.mc.init();
 
613
 
 
614
  int ret = -1;
 
615
 
 
616
  if (g.mc.authenticate() < 0) {
 
617
    cerr << "unable to authenticate as " << *g_conf.entity_name << std::endl;
 
618
    goto out;
 
619
  }
 
620
  if (g.mc.get_monmap() < 0) {
 
621
    cerr << "unable to get monmap" << std::endl;
 
622
    goto out;
 
623
  }
 
624
 
 
625
  switch (ceph_tool_mode)
 
626
  {
 
627
    case CEPH_TOOL_MODE_OBSERVER:
 
628
    case CEPH_TOOL_MODE_ONE_SHOT_OBSERVER:
 
629
      g.lock.Lock();
 
630
      send_observe_requests();
 
631
      g.lock.Unlock();
 
632
      break;
 
633
 
 
634
    case CEPH_TOOL_MODE_CLI_INPUT: {
 
635
      if (vcmd.empty()) {
 
636
        // interactive mode
 
637
        do_cli();
 
638
        messenger->shutdown();
 
639
        break;
 
640
      }
 
641
      string rs;
 
642
      bufferlist odata;
 
643
      ret = do_command(vcmd, indata, rs, odata);
 
644
      int len = odata.length();
 
645
      if (len) {
 
646
        if (outfile) {
 
647
          if (strcmp(outfile, "-") == 0) {
 
648
            ::write(1, odata.c_str(), len);
 
649
          } else {
 
650
            odata.write_file(outfile);
 
651
          }
 
652
          cout << g_clock.now() << " wrote " << len << " byte payload to " << outfile << std::endl;
 
653
        } else {
 
654
          cout << g_clock.now() << " got " << len << " byte payload, discarding (specify -o <outfile)" << std::endl;
 
655
        }
 
656
      }
 
657
      messenger->shutdown();
 
658
      break;
 
659
    }
 
660
 
 
661
    case CEPH_TOOL_MODE_GUI: {
 
662
#ifdef HAVE_GTK2
 
663
      g.log = &gss;
 
664
      g.slog = &gss;
 
665
 
 
666
      // TODO: make sure that we capture the log this generates in the GUI
 
667
      g.lock.Lock();
 
668
      send_observe_requests();
 
669
      g.lock.Unlock();
 
670
 
 
671
      run_gui(argc, (char **)argv);
 
672
#else
 
673
      cerr << "I'm sorry. This tool was not compiled with support for  "
 
674
           << "GTK2." << std::endl;
 
675
      ret = EXIT_FAILURE;
 
676
#endif
 
677
      messenger->shutdown();
 
678
      break;
 
679
    }
 
680
 
 
681
    default:
 
682
      assert(0);
 
683
      break;
 
684
  }
 
685
 
 
686
  ret = 0;
 
687
 out:
 
688
 
 
689
  // wait for messenger to finish
 
690
  messenger->wait();
 
691
  messenger->destroy();
 
692
  tok_end(tok);
 
693
  
 
694
  g.lock.Lock();
 
695
  g.mc.shutdown();
 
696
  g.timer.shutdown();
 
697
  g.lock.Unlock();
 
698
  return ret;
 
699
}