mon: QuorumService: Allow for services quorum-bound to be easily created

As the monitor grows in features, we have been dumping them in the Monitor
class as they don't really fit anywhere else.

Most of those latest features have been, and some of the future changes
will also be, quorum-bounded.  By that we mean that these features tend
to require a quorum to be present in order to work.

Although we already have the PaxosService interface, it really isn't
adequate for this kind of features, as they don't really require Paxos,
nor do they access the store.  Furthermore, they don't really need to
tick at the same rate as the monitor, and can be fairly independent.

Therefore we now introduce the concept of a QuorumService, a class to be
built upon, managing the tick and dispatch for any kind of service
basically requiring a quorum to function.

Among the already existing monitor features that could take advantage of
this new class we can find the Timecheck infrastructure, as it is by
nature quorum bounded.  The monitor store sync could also take advantage
of this service, although it doesn't really require a quorum to work,
and even the PaxosService-related classes could use this.

This patch also introduces the MMonQuorumService base class, to be used
by any message that should want to.

Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
This commit is contained in:
Joao Eduardo Luis 2013-03-17 18:33:15 +00:00
parent 53c1c4827e
commit a3751d1f42
3 changed files with 216 additions and 0 deletions

View File

@ -1826,6 +1826,7 @@ noinst_HEADERS = \
messages/MOSDPGScan.h\
messages/MBackfillReserve.h\
messages/MRecoveryReserve.h\
messages/MMonQuorumService.h\
messages/MOSDPGTemp.h\
messages/MOSDPGTrim.h\
messages/MOSDPing.h\
@ -1862,6 +1863,7 @@ noinst_HEADERS = \
mon/PGMonitor.h\
mon/Paxos.h\
mon/PaxosService.h\
mon/QuorumService.h\
mon/Session.h\
mon/mon_types.h\
mount/canonicalize.c\

View File

@ -0,0 +1,72 @@
// -*- 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) 2012 Inktank, Inc.
*
* 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.
*
*/
#ifndef CEPH_MMON_QUORUM_SERVICE_H
#define CEPH_MMON_QUORUM_SERVICE_H
#include "msg/Message.h"
struct MMonQuorumService : public Message
{
epoch_t epoch;
version_t round;
MMonQuorumService(int type, int head=1, int compat=1) :
Message(type, head, compat),
epoch(0),
round(0)
{ }
protected:
~MMonQuorumService() { }
public:
void set_epoch(epoch_t e) {
epoch = e;
}
void set_round(version_t r) {
round = r;
}
epoch_t get_epoch() const {
return epoch;
}
version_t get_round() const {
return round;
}
void service_encode() {
::encode(epoch, payload);
::encode(round, payload);
}
void service_decode(bufferlist::iterator &p) {
::decode(epoch, p);
::decode(round, p);
}
void encode_payload(uint64_t features) {
assert(0 == "MMonQuorumService message must always be a base class");
}
void decode_payload() {
assert(0 == "MMonQuorumService message must always be a base class");
}
const char *get_type_name() const { return "quorum_service"; }
};
#endif /* CEPH_MMON_QUORUM_SERVICE_H */

142
src/mon/QuorumService.h Normal file
View File

@ -0,0 +1,142 @@
// -*- 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) 2013 Inktank, Inc
*
* 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.
*
*/
#ifndef CEPH_MON_QUORUM_SERVICE_H
#define CEPH_MON_QUORUM_SERVICE_H
#include <boost/intrusive_ptr.hpp>
// Because intusive_ptr clobbers our assert...
#include "include/assert.h"
#include <errno.h>
#include "include/types.h"
#include "include/Context.h"
#include "common/RefCountedObj.h"
#include "common/config.h"
#include "mon/Monitor.h"
#include "messages/MMonQuorumService.h"
class QuorumService : public RefCountedObject
{
uint32_t flags;
Context *tick_event;
double tick_period;
struct C_Tick : public Context {
boost::intrusive_ptr<QuorumService> s;
C_Tick(boost::intrusive_ptr<QuorumService> qs) : s(qs) { }
void finish(int r) {
if (r < 0)
return;
s->tick();
}
};
public:
static const int SERVICE_HEALTH = 0x01;
static const int SERVICE_TIMECHECK = 0x02;
protected:
Monitor *mon;
epoch_t epoch;
QuorumService(Monitor *m) :
tick_event(NULL),
tick_period(g_conf->mon_tick_interval),
mon(m),
epoch(0)
{
}
void cancel_tick() {
if (tick_event)
mon->timer.cancel_event(tick_event);
tick_event = NULL;
}
void start_tick() {
generic_dout(10) << __func__ << dendl;
cancel_tick();
if (tick_period <= 0)
return;
tick_event = new C_Tick(
boost::intrusive_ptr<QuorumService>(this));
mon->timer.add_event_after(tick_period, tick_event);
}
void set_update_period(double t) {
tick_period = t;
}
bool in_quorum() {
return (mon->is_leader() || mon->is_peon());
}
virtual bool service_dispatch(Message *m) = 0;
virtual void service_tick() = 0;
virtual void service_shutdown() = 0;
virtual void start_epoch() = 0;
virtual void finish_epoch() = 0;
virtual void cleanup() = 0;
public:
virtual ~QuorumService() { }
QuorumService *get() {
return static_cast<QuorumService *>(RefCountedObject::get());
}
void start(epoch_t new_epoch) {
epoch = new_epoch;
start_epoch();
}
void finish() {
generic_dout(20) << "QuorumService::finish" << dendl;
finish_epoch();
}
epoch_t get_epoch() const {
return epoch;
}
bool dispatch(MMonQuorumService *m) {
return service_dispatch(m);
}
void tick() {
service_tick();
start_tick();
}
void shutdown() {
generic_dout(0) << "quorum service shutdown" << dendl;
cancel_tick();
service_shutdown();
}
virtual void init() { }
virtual void get_health(Formatter *f,
list<pair<health_status_t,string> > *detail) = 0;
virtual int get_type() = 0;
virtual string get_name() const = 0;
};
typedef boost::intrusive_ptr<QuorumService> QuorumServiceRef;
#endif /* CEPH_MON_QUORUM_SERVICE_H */