summaryrefslogtreecommitdiffstats
path: root/src/mon/MonClient.cc
blob: b30aa32dc73a9bfeb0820076b96413596653338c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "msg/SimpleMessenger.h"
#include "messages/MMonGetMap.h"
#include "messages/MMonMap.h"
#include "common/ConfUtils.h"

#include "MonClient.h"
#include "MonMap.h"

#include "config.h"

#undef dout_prefix
#define dout_prefix *_dout << dbeginl << " monclient "

Mutex monmap_lock("monmap_lock");
Cond monmap_cond;
bufferlist monmap_bl;

int MonClient::probe_mon(MonMap *pmonmap) 
{
  vector<entity_addr_t> monaddrs;

  const char *p = g_conf.mon_host;
  const char *end = p + strlen(p);
  while (p < end) {
    entity_addr_t a;
    if (parse_ip_port(p, a, &p)) {
      monaddrs.push_back(a);
    } else {
      break;
    }
  }
  if (monaddrs.empty()) {
    cerr << "couldn't parse ip:port(s) from '" << g_conf.mon_host << "'" << std::endl;
    return -1;
  }
  
  rank.bind();
  dout(1) << " connecting to monitor(s) at " << monaddrs << " ..." << dendl;
  
  Messenger *msgr = rank.register_entity(entity_name_t::CLIENT(-1));
  msgr->set_dispatcher(this);

  rank.start(true);  // do not daemonize!
  
  int attempt = 10;
  int i = 0;
  monmap_lock.Lock();
  srand(getpid());
  while (monmap_bl.length() == 0) {
    i = rand() % monaddrs.size();
    dout(10) << "querying " << monaddrs[i] << dendl;
    entity_inst_t mi;
    mi.addr = monaddrs[i];
    mi.name = entity_name_t::MON(0);  // FIXME HRM!
    msgr->send_message(new MMonGetMap, mi);
    
    if (--attempt == 0)
      break;

    utime_t interval(1, 0);
    monmap_cond.WaitInterval(monmap_lock, interval);
  }
  monmap_lock.Unlock();

  if (monmap_bl.length()) {
    pmonmap->decode(monmap_bl);
    dout(1) << "[got monmap from " << monaddrs[i] << " fsid " << pmonmap->fsid << "]" << dendl;
  }
  msgr->shutdown();
  msgr->destroy();
  rank.wait();

  if (monmap_bl.length())
    return 0;

  cerr << "unable to fetch monmap from " << monaddrs << std::endl;
  return -1; // failed
}

int MonClient::get_monmap(MonMap *pmonmap)
{
  static string monstr;

  if (g_conf.monmap) {
    // file?
    const char *monmap_fn = g_conf.monmap;
    int r = pmonmap->read(monmap_fn);
    if (r >= 0) {
      dout(1) << "[opened monmap at " << monmap_fn << " fsid " << pmonmap->fsid << "]" << dendl;
      return 0;
    }

    cerr << "unable to read monmap from " << monmap_fn << ": " << strerror(errno) << std::endl;
  }

  if (!g_conf.mon_host) {
    // cluster conf?
    ConfFile a(g_conf.conf);
    ConfFile b("ceph.conf");
    ConfFile *c = 0;

    if (a.parse())
      c = &a;
    else if (b.parse())
      c = &b;
    if (c) {
      for (int i=0; i<15; i++) {
	char *val = 0;
	char monname[10];
	sprintf(monname, "mon%d", i);
	c->read(monname, "mon addr", &val, 0);
	if (!val || !val[0])
	  break;
	
	if (monstr.length())
	  monstr += ",";
	monstr += val;
      }
      g_conf.mon_host = monstr.c_str();
    }
  }

  // probe?
  if (g_conf.mon_host &&
      probe_mon(pmonmap) == 0)  
    return 0;

  cerr << "must specify monitor address (-m monaddr) or cluster conf (-C cluster.conf) or monmap file (-M monmap)" << std::endl;
  return -1;
}

void MonClient::handle_monmap(MMonMap *m)
{
  dout(10) << "handle_monmap " << *m << dendl;
  monmap_lock.Lock();
  monmap_bl = m->monmapbl;
  monmap_cond.Signal();
  monmap_lock.Unlock();
}

bool MonClient::dispatch_impl(Message *m)
{
  dout(10) << "dispatch " << *m << dendl;

  switch (m->get_type()) {
  case CEPH_MSG_MON_MAP:
    handle_monmap((MMonMap*)m);
    break;
  default:
    return false;
  }

  delete m;
  return true;
}