summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoao Eduardo Luis <joao.luis@inktank.com>2013-03-17 18:33:15 +0000
committerJoao Eduardo Luis <joao.luis@inktank.com>2013-03-18 22:43:55 +0000
commita3751d1f42e76fa7acdc4eda59ae0d6b4bd9195d (patch)
treee8927b53f7186ee2667995fe8149780a746f7017
parent53c1c4827e59ad3aa17969ca2ccdf4072e8ecb97 (diff)
downloadceph-a3751d1f42e76fa7acdc4eda59ae0d6b4bd9195d.tar.gz
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>
-rw-r--r--src/Makefile.am2
-rw-r--r--src/messages/MMonQuorumService.h72
-rw-r--r--src/mon/QuorumService.h142
3 files changed, 216 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b00fe03b0c5..7e8f2679e48 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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\
diff --git a/src/messages/MMonQuorumService.h b/src/messages/MMonQuorumService.h
new file mode 100644
index 00000000000..6a25ae1e203
--- /dev/null
+++ b/src/messages/MMonQuorumService.h
@@ -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 */
diff --git a/src/mon/QuorumService.h b/src/mon/QuorumService.h
new file mode 100644
index 00000000000..054fce67036
--- /dev/null
+++ b/src/mon/QuorumService.h
@@ -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 */