mirror of
https://github.com/ceph/ceph
synced 2025-03-07 08:49:15 +00:00
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:
parent
53c1c4827e
commit
a3751d1f42
@ -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\
|
||||
|
72
src/messages/MMonQuorumService.h
Normal file
72
src/messages/MMonQuorumService.h
Normal 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
142
src/mon/QuorumService.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user