]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/PaxosService.h
update sources to v12.1.1
[ceph.git] / ceph / src / mon / PaxosService.h
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 #ifndef CEPH_PAXOSSERVICE_H
16 #define CEPH_PAXOSSERVICE_H
17
18 #include "include/Context.h"
19 #include "Paxos.h"
20 #include "Monitor.h"
21 #include "MonitorDBStore.h"
22
23 class Monitor;
24 class Paxos;
25
26 /**
27 * A Paxos Service is an abstraction that easily allows one to obtain an
28 * association between a Monitor and a Paxos class, in order to implement any
29 * service.
30 */
31 class PaxosService {
32 /**
33 * @defgroup PaxosService_h_class Paxos Service
34 * @{
35 */
36 public:
37 /**
38 * The Monitor to which this class is associated with
39 */
40 Monitor *mon;
41 /**
42 * The Paxos instance to which this class is associated with
43 */
44 Paxos *paxos;
45 /**
46 * Our name. This will be associated with the class implementing us, and will
47 * be used mainly for store-related operations.
48 */
49 string service_name;
50 /**
51 * If we are or have queued anything for proposal, this variable will be true
52 * until our proposal has been finished.
53 */
54 bool proposing;
55
56 bool need_immediate_propose = false;
57
58 protected:
59 /**
60 * Services implementing us used to depend on the Paxos version, back when
61 * each service would have a Paxos instance for itself. However, now we only
62 * have a single Paxos instance, shared by all the services. Each service now
63 * must keep its own version, if so they wish. This variable should be used
64 * for that purpose.
65 */
66 version_t service_version;
67
68 private:
69 /**
70 * Event callback responsible for proposing our pending value once a timer
71 * runs out and fires.
72 */
73 Context *proposal_timer;
74 /**
75 * If the implementation class has anything pending to be proposed to Paxos,
76 * then have_pending should be true; otherwise, false.
77 */
78 bool have_pending;
79
80 /**
81 * health checks for this service
82 *
83 * Child must populate this during encode_pending() by calling encode_health().
84 */
85 health_check_map_t health_checks;
86 public:
87 const health_check_map_t& get_health_checks() {
88 return health_checks;
89 }
90
91 protected:
92 /**
93 * format of our state in leveldb, 0 for default
94 */
95 version_t format_version;
96
97 /**
98 * @defgroup PaxosService_h_callbacks Callback classes
99 * @{
100 */
101 /**
102 * Retry dispatching a given service message
103 *
104 * This callback class is used when we had to wait for some condition to
105 * become true while we were dispatching it.
106 *
107 * For instance, if the message's version isn't readable, according to Paxos,
108 * then we must wait for it to become readable. So, we just queue an
109 * instance of this class onto the Paxos::wait_for_readable function, and
110 * we will retry the whole dispatch again once the callback is fired.
111 */
112 class C_RetryMessage : public C_MonOp {
113 PaxosService *svc;
114 public:
115 C_RetryMessage(PaxosService *s, MonOpRequestRef op_) :
116 C_MonOp(op_), svc(s) { }
117 void _finish(int r) override {
118 if (r == -EAGAIN || r >= 0)
119 svc->dispatch(op);
120 else if (r == -ECANCELED)
121 return;
122 else
123 assert(0 == "bad C_RetryMessage return value");
124 }
125 };
126
127 /**
128 * @}
129 */
130
131 public:
132 /**
133 * @param mn A Monitor instance
134 * @param p A Paxos instance
135 * @param name Our service's name.
136 */
137 PaxosService(Monitor *mn, Paxos *p, string name)
138 : mon(mn), paxos(p), service_name(name),
139 proposing(false),
140 service_version(0), proposal_timer(0), have_pending(false),
141 format_version(0),
142 last_committed_name("last_committed"),
143 first_committed_name("first_committed"),
144 full_prefix_name("full"), full_latest_name("latest"),
145 cached_first_committed(0), cached_last_committed(0)
146 {
147 }
148
149 virtual ~PaxosService() {}
150
151 /**
152 * Get the service's name.
153 *
154 * @returns The service's name.
155 */
156 string get_service_name() { return service_name; }
157
158 /**
159 * Get the store prefixes we utilize
160 */
161 virtual void get_store_prefixes(set<string>& s) {
162 s.insert(service_name);
163 }
164
165 // i implement and you ignore
166 /**
167 * Informs this instance that it should consider itself restarted.
168 *
169 * This means that we will cancel our proposal_timer event, if any exists.
170 */
171 void restart();
172 /**
173 * Informs this instance that an election has finished.
174 *
175 * This means that we will invoke a PaxosService::discard_pending while
176 * setting have_pending to false (basically, ignore our pending state) and
177 * we will then make sure we obtain a new state.
178 *
179 * Our state shall be updated by PaxosService::_active if the Paxos is
180 * active; otherwise, we will wait for it to become active by adding a
181 * PaxosService::C_Active callback to it.
182 */
183 void election_finished();
184 /**
185 * Informs this instance that it is supposed to shutdown.
186 *
187 * Basically, it will instruct Paxos to cancel all events/callbacks and then
188 * will cancel the proposal_timer event if any exists.
189 */
190 void shutdown();
191
192 private:
193 /**
194 * Update our state by updating it from Paxos, and then creating a new
195 * pending state if need be.
196 *
197 * @remarks We only create a pending state we our Monitor is the Leader.
198 *
199 * @pre Paxos is active
200 * @post have_pending is true if our Monitor is the Leader and Paxos is
201 * active
202 */
203 void _active();
204
205 public:
206 /**
207 * Propose a new value through Paxos.
208 *
209 * This function should be called by the classes implementing
210 * PaxosService, in order to propose a new value through Paxos.
211 *
212 * @pre The implementation class implements the encode_pending function.
213 * @pre have_pending is true
214 * @pre Our monitor is the Leader
215 * @pre Paxos is active
216 * @post Cancel the proposal timer, if any
217 * @post have_pending is false
218 * @post propose pending value through Paxos
219 *
220 * @note This function depends on the implementation of encode_pending on
221 * the class that is implementing PaxosService
222 */
223 void propose_pending();
224
225 /**
226 * Let others request us to propose.
227 *
228 * At the moment, this is just a wrapper to propose_pending() with an
229 * extra check for is_writeable(), but it's a good practice to dissociate
230 * requests for proposals from direct usage of propose_pending() for
231 * future use -- we might want to perform additional checks or put a
232 * request on hold, for instance.
233 */
234 void request_proposal() {
235 assert(is_writeable());
236
237 propose_pending();
238 }
239 /**
240 * Request service @p other to perform a proposal.
241 *
242 * We could simply use the function above, requesting @p other directly,
243 * but we might eventually want to do something to the request -- say,
244 * set a flag stating we're waiting on a cross-proposal to be finished.
245 */
246 void request_proposal(PaxosService *other) {
247 assert(other != NULL);
248 assert(other->is_writeable());
249
250 other->request_proposal();
251 }
252
253 /**
254 * Dispatch a message by passing it to several different functions that are
255 * either implemented directly by this service, or that should be implemented
256 * by the class implementing this service.
257 *
258 * @param m A message
259 * @returns 'true' on successful dispatch; 'false' otherwise.
260 */
261 bool dispatch(MonOpRequestRef op);
262
263 void refresh(bool *need_bootstrap);
264 void post_refresh();
265
266 /**
267 * @defgroup PaxosService_h_override_funcs Functions that should be
268 * overridden.
269 *
270 * These functions should be overridden at will by the class implementing
271 * this service.
272 * @{
273 */
274 /**
275 * Create the initial state for your system.
276 *
277 * In some of ours the state is actually set up elsewhere so this does
278 * nothing.
279 */
280 virtual void create_initial() = 0;
281
282 /**
283 * Query the Paxos system for the latest state and apply it if it's newer
284 * than the current Monitor state.
285 */
286 virtual void update_from_paxos(bool *need_bootstrap) = 0;
287
288 /**
289 * Hook called after all services have refreshed their state from paxos
290 *
291 * This is useful for doing any update work that depends on other
292 * service's having up-to-date state.
293 */
294 virtual void post_paxos_update() {}
295
296 /**
297 * Init on startup
298 *
299 * This is called on mon startup, after all of the PaxosService instances'
300 * update_from_paxos() methods have been called
301 */
302 virtual void init() {}
303
304 /**
305 * Create the pending state.
306 *
307 * @invariant This function is only called on a Leader.
308 * @remarks This created state is then modified by incoming messages.
309 * @remarks Called at startup and after every Paxos ratification round.
310 */
311 virtual void create_pending() = 0;
312
313 /**
314 * Encode the pending state into a bufferlist for ratification and
315 * transmission as the next state.
316 *
317 * @invariant This function is only called on a Leader.
318 *
319 * @param t The transaction to hold all changes.
320 */
321 virtual void encode_pending(MonitorDBStore::TransactionRef t) = 0;
322
323 /**
324 * Discard the pending state
325 *
326 * @invariant This function is only called on a Leader.
327 *
328 * @remarks This function is NOT overridden in any of our code, but it is
329 * called in PaxosService::election_finished if have_pending is
330 * true.
331 */
332 virtual void discard_pending() { }
333
334 /**
335 * Look at the query; if the query can be handled without changing state,
336 * do so.
337 *
338 * @param m A query message
339 * @returns 'true' if the query was handled (e.g., was a read that got
340 * answered, was a state change that has no effect); 'false'
341 * otherwise.
342 */
343 virtual bool preprocess_query(MonOpRequestRef op) = 0;
344
345 /**
346 * Apply the message to the pending state.
347 *
348 * @invariant This function is only called on a Leader.
349 *
350 * @param m An update message
351 * @returns 'true' if the update message was handled (e.g., a command that
352 * went through); 'false' otherwise.
353 */
354 virtual bool prepare_update(MonOpRequestRef op) = 0;
355 /**
356 * @}
357 */
358
359 /**
360 * Determine if the Paxos system should vote on pending, and if so how long
361 * it should wait to vote.
362 *
363 * @param[out] delay The wait time, used so we can limit the update traffic
364 * spamming.
365 * @returns 'true' if the Paxos system should propose; 'false' otherwise.
366 */
367 virtual bool should_propose(double &delay);
368
369 /**
370 * force an immediate propose.
371 *
372 * This is meant to be called from prepare_update(op).
373 */
374 void force_immediate_propose() {
375 need_immediate_propose = true;
376 }
377
378 /**
379 * @defgroup PaxosService_h_courtesy Courtesy functions
380 *
381 * Courtesy functions, in case the class implementing this service has
382 * anything it wants/needs to do at these times.
383 * @{
384 */
385 /**
386 * This is called when the Paxos state goes to active.
387 *
388 * On the peon, this is after each election.
389 * On the leader, this is after each election, *and* after each completed
390 * proposal.
391 *
392 * @note This function may get called twice in certain recovery cases.
393 */
394 virtual void on_active() { }
395
396 /**
397 * This is called when we are shutting down
398 */
399 virtual void on_shutdown() {}
400
401 /**
402 * this is called when activating on the leader
403 *
404 * it should conditionally upgrade the on-disk format by proposing a transaction
405 */
406 virtual void upgrade_format() { }
407
408 /**
409 * this is called when we detect the store has just upgraded underneath us
410 */
411 virtual void on_upgrade() {}
412
413 /**
414 * Called when the Paxos system enters a Leader election.
415 *
416 * @remarks It's a courtesy method, in case the class implementing this
417 * service has anything it wants/needs to do at that time.
418 */
419 virtual void on_restart() { }
420 /**
421 * @}
422 */
423
424 /**
425 * Tick.
426 */
427 virtual void tick() {}
428
429 /**
430 * Get health information
431 *
432 * @param summary list of summary strings and associated severity
433 * @param detail optional list of detailed problem reports; may be NULL
434 */
435 virtual void get_health(list<pair<health_status_t,string> >& summary,
436 list<pair<health_status_t,string> > *detail,
437 CephContext *cct) const { }
438
439 void encode_health(const health_check_map_t& next,
440 MonitorDBStore::TransactionRef t) {
441 bufferlist bl;
442 ::encode(next, bl);
443 t->put("health", service_name, bl);
444 mon->log_health(next, health_checks, t);
445 }
446 void load_health();
447
448 private:
449 /**
450 * @defgroup PaxosService_h_store_keys Set of keys that are usually used on
451 * all the services implementing this
452 * class, and, being almost the only keys
453 * used, should be standardized to avoid
454 * mistakes.
455 * @{
456 */
457 const string last_committed_name;
458 const string first_committed_name;
459 const string full_prefix_name;
460 const string full_latest_name;
461 /**
462 * @}
463 */
464
465 /**
466 * @defgroup PaxosService_h_version_cache Variables holding cached values
467 * for the most used versions (first
468 * and last committed); we only have
469 * to read them when the store is
470 * updated, so in-between updates we
471 * may very well use cached versions
472 * and avoid the overhead.
473 * @{
474 */
475 version_t cached_first_committed;
476 version_t cached_last_committed;
477 /**
478 * @}
479 */
480
481 /**
482 * Callback list to be used whenever we are running a proposal through
483 * Paxos. These callbacks will be awaken whenever the said proposal
484 * finishes.
485 */
486 list<Context*> waiting_for_finished_proposal;
487
488 public:
489
490 /**
491 * Check if we are proposing a value through Paxos
492 *
493 * @returns true if we are proposing; false otherwise.
494 */
495 bool is_proposing() {
496 return proposing;
497 }
498
499 /**
500 * Check if we are in the Paxos ACTIVE state.
501 *
502 * @note This function is a wrapper for Paxos::is_active
503 *
504 * @returns true if in state ACTIVE; false otherwise.
505 */
506 bool is_active() {
507 return
508 !is_proposing() &&
509 (paxos->is_active() || paxos->is_updating() || paxos->is_writing());
510 }
511
512 /**
513 * Check if we are readable.
514 *
515 * This mirrors on the paxos check, except that we also verify that
516 *
517 * - the client hasn't seen the future relative to this PaxosService
518 * - this service isn't proposing.
519 * - we have committed our initial state (last_committed > 0)
520 *
521 * @param ver The version we want to check if is readable
522 * @returns true if it is readable; false otherwise
523 */
524 bool is_readable(version_t ver = 0) {
525 if (ver > get_last_committed() ||
526 !paxos->is_readable(0) ||
527 get_last_committed() == 0)
528 return false;
529 return true;
530 }
531
532 /**
533 * Check if we are writeable.
534 *
535 * We consider to be writeable iff:
536 *
537 * - we are not proposing a new version;
538 * - we are ready to be written to -- i.e., we have a pending value.
539 * - paxos is (active or updating or writing or refresh)
540 *
541 * @returns true if writeable; false otherwise
542 */
543 bool is_writeable() {
544 return is_write_ready();
545 }
546
547 /**
548 * Check if we are ready to be written to. This means we must have a
549 * pending value and be active.
550 *
551 * @returns true if we are ready to be written to; false otherwise.
552 */
553 bool is_write_ready() {
554 return is_active() && have_pending;
555 }
556
557 /**
558 * Wait for a proposal to finish.
559 *
560 * Add a callback to be awaken whenever our current proposal finishes being
561 * proposed through Paxos.
562 *
563 * @param c The callback to be awaken once the proposal is finished.
564 */
565 void wait_for_finished_proposal(MonOpRequestRef op, Context *c) {
566 if (op)
567 op->mark_event_string(service_name + ":wait_for_finished_proposal");
568 waiting_for_finished_proposal.push_back(c);
569 }
570 void wait_for_finished_proposal_ctx(Context *c) {
571 MonOpRequestRef o;
572 wait_for_finished_proposal(o, c);
573 }
574
575 /**
576 * Wait for us to become active
577 *
578 * @param c The callback to be awaken once we become active.
579 */
580 void wait_for_active(MonOpRequestRef op, Context *c) {
581 if (op)
582 op->mark_event_string(service_name + ":wait_for_active");
583
584 if (!is_proposing()) {
585 paxos->wait_for_active(op, c);
586 return;
587 }
588 wait_for_finished_proposal(op, c);
589 }
590 void wait_for_active_ctx(Context *c) {
591 MonOpRequestRef o;
592 wait_for_active(o, c);
593 }
594
595 /**
596 * Wait for us to become readable
597 *
598 * @param c The callback to be awaken once we become active.
599 * @param ver The version we want to wait on.
600 */
601 void wait_for_readable(MonOpRequestRef op, Context *c, version_t ver = 0) {
602 /* This is somewhat of a hack. We only do check if a version is readable on
603 * PaxosService::dispatch(), but, nonetheless, we must make sure that if that
604 * is why we are not readable, then we must wait on PaxosService and not on
605 * Paxos; otherwise, we may assert on Paxos::wait_for_readable() if it
606 * happens to be readable at that specific point in time.
607 */
608 if (op)
609 op->mark_event_string(service_name + ":wait_for_readable");
610
611 if (is_proposing() ||
612 ver > get_last_committed() ||
613 get_last_committed() == 0)
614 wait_for_finished_proposal(op, c);
615 else {
616 if (op)
617 op->mark_event_string(service_name + ":wait_for_readable/paxos");
618
619 paxos->wait_for_readable(op, c);
620 }
621 }
622
623 void wait_for_readable_ctx(Context *c, version_t ver = 0) {
624 MonOpRequestRef o; // will initialize the shared_ptr to NULL
625 wait_for_readable(o, c, ver);
626 }
627
628 /**
629 * Wait for us to become writeable
630 *
631 * @param c The callback to be awaken once we become writeable.
632 */
633 void wait_for_writeable(MonOpRequestRef op, Context *c) {
634 if (op)
635 op->mark_event_string(service_name + ":wait_for_writeable");
636
637 if (is_proposing())
638 wait_for_finished_proposal(op, c);
639 else if (!is_write_ready())
640 wait_for_active(op, c);
641 else
642 paxos->wait_for_writeable(op, c);
643 }
644 void wait_for_writeable_ctx(Context *c) {
645 MonOpRequestRef o;
646 wait_for_writeable(o, c);
647 }
648
649
650 /**
651 * @defgroup PaxosService_h_Trim Functions for trimming states
652 * @{
653 */
654 /**
655 * trim service states if appropriate
656 *
657 * Called at same interval as tick()
658 */
659 void maybe_trim();
660
661 /**
662 * Auxiliary function to trim our state from version @p from to version
663 * @p to, not including; i.e., the interval [from, to[
664 *
665 * @param t The transaction to which we will add the trim operations.
666 * @param from the lower limit of the interval to be trimmed
667 * @param to the upper limit of the interval to be trimmed (not including)
668 */
669 void trim(MonitorDBStore::TransactionRef t, version_t from, version_t to);
670
671 /**
672 * encode service-specific extra bits into trim transaction
673 *
674 * @param tx transaction
675 * @param first new first_committed value
676 */
677 virtual void encode_trim_extra(MonitorDBStore::TransactionRef tx,
678 version_t first) {}
679
680 /**
681 * Get the version we should trim to.
682 *
683 * Should be overloaded by service if it wants to trim states.
684 *
685 * @returns the version we should trim to; if we return zero, it should be
686 * assumed that there's no version to trim to.
687 */
688 virtual version_t get_trim_to() {
689 return 0;
690 }
691
692 /**
693 * @}
694 */
695 /**
696 * @defgroup PaxosService_h_Stash_Full
697 * @{
698 */
699 virtual bool should_stash_full();
700 /**
701 * Encode a full version on @p t
702 *
703 * @note We force every service to implement this function, since we strongly
704 * desire the encoding of full versions.
705 * @note Services that do not trim their state, will be bound to only create
706 * one full version. Full version stashing is determined/controled by
707 * trimming: we stash a version each time a trim is bound to erase the
708 * latest full version.
709 *
710 * @param t Transaction on which the full version shall be encoded.
711 */
712 virtual void encode_full(MonitorDBStore::TransactionRef t) = 0;
713
714 /**
715 * @}
716 */
717
718 /**
719 * Cancel events.
720 *
721 * @note This function is a wrapper for Paxos::cancel_events
722 */
723 void cancel_events() {
724 paxos->cancel_events();
725 }
726
727 /**
728 * @defgroup PaxosService_h_store_funcs Back storage interface functions
729 * @{
730 */
731 /**
732 * @defgroup PaxosService_h_store_modify Wrapper function interface to access
733 * the back store for modification
734 * purposes
735 * @{
736 */
737 void put_first_committed(MonitorDBStore::TransactionRef t, version_t ver) {
738 t->put(get_service_name(), first_committed_name, ver);
739 }
740 /**
741 * Set the last committed version to @p ver
742 *
743 * @param t A transaction to which we add this put operation
744 * @param ver The last committed version number being put
745 */
746 void put_last_committed(MonitorDBStore::TransactionRef t, version_t ver) {
747 t->put(get_service_name(), last_committed_name, ver);
748
749 /* We only need to do this once, and that is when we are about to make our
750 * first proposal. There are some services that rely on first_committed
751 * being set -- and it should! -- so we need to guarantee that it is,
752 * specially because the services itself do not do it themselves. They do
753 * rely on it, but they expect us to deal with it, and so we shall.
754 */
755 if (!get_first_committed())
756 put_first_committed(t, ver);
757 }
758 /**
759 * Put the contents of @p bl into version @p ver
760 *
761 * @param t A transaction to which we will add this put operation
762 * @param ver The version to which we will add the value
763 * @param bl A bufferlist containing the version's value
764 */
765 void put_version(MonitorDBStore::TransactionRef t, version_t ver,
766 bufferlist& bl) {
767 t->put(get_service_name(), ver, bl);
768 }
769 /**
770 * Put the contents of @p bl into a full version key for this service, that
771 * will be created with @p ver in mind.
772 *
773 * @param t The transaction to which we will add this put operation
774 * @param ver A version number
775 * @param bl A bufferlist containing the version's value
776 */
777 void put_version_full(MonitorDBStore::TransactionRef t,
778 version_t ver, bufferlist& bl) {
779 string key = mon->store->combine_strings(full_prefix_name, ver);
780 t->put(get_service_name(), key, bl);
781 }
782 /**
783 * Put the version number in @p ver into the key pointing to the latest full
784 * version of this service.
785 *
786 * @param t The transaction to which we will add this put operation
787 * @param ver A version number
788 */
789 void put_version_latest_full(MonitorDBStore::TransactionRef t, version_t ver) {
790 string key = mon->store->combine_strings(full_prefix_name, full_latest_name);
791 t->put(get_service_name(), key, ver);
792 }
793 /**
794 * Put the contents of @p bl into the key @p key.
795 *
796 * @param t A transaction to which we will add this put operation
797 * @param key The key to which we will add the value
798 * @param bl A bufferlist containing the value
799 */
800 void put_value(MonitorDBStore::TransactionRef t,
801 const string& key, bufferlist& bl) {
802 t->put(get_service_name(), key, bl);
803 }
804
805 /**
806 * Put integer value @v into the key @p key.
807 *
808 * @param t A transaction to which we will add this put operation
809 * @param key The key to which we will add the value
810 * @param v An integer
811 */
812 void put_value(MonitorDBStore::TransactionRef t,
813 const string& key, version_t v) {
814 t->put(get_service_name(), key, v);
815 }
816
817 /**
818 * @}
819 */
820
821 /**
822 * @defgroup PaxosService_h_store_get Wrapper function interface to access
823 * the back store for reading purposes
824 * @{
825 */
826
827 /**
828 * @defgroup PaxosService_h_version_cache Obtain cached versions for this
829 * service.
830 * @{
831 */
832 /**
833 * Get the first committed version
834 *
835 * @returns Our first committed version (that is available)
836 */
837 version_t get_first_committed() const{
838 return cached_first_committed;
839 }
840 /**
841 * Get the last committed version
842 *
843 * @returns Our last committed version
844 */
845 version_t get_last_committed() const{
846 return cached_last_committed;
847 }
848
849 /**
850 * @}
851 */
852
853 /**
854 * Get the contents of a given version @p ver
855 *
856 * @param ver The version being obtained
857 * @param bl The bufferlist to be populated
858 * @return 0 on success; <0 otherwise
859 */
860 virtual int get_version(version_t ver, bufferlist& bl) {
861 return mon->store->get(get_service_name(), ver, bl);
862 }
863 /**
864 * Get the contents of a given full version of this service.
865 *
866 * @param ver A version number
867 * @param bl The bufferlist to be populated
868 * @returns 0 on success; <0 otherwise
869 */
870 virtual int get_version_full(version_t ver, bufferlist& bl) {
871 string key = mon->store->combine_strings(full_prefix_name, ver);
872 return mon->store->get(get_service_name(), key, bl);
873 }
874 /**
875 * Get the latest full version number
876 *
877 * @returns A version number
878 */
879 version_t get_version_latest_full() {
880 string key = mon->store->combine_strings(full_prefix_name, full_latest_name);
881 return mon->store->get(get_service_name(), key);
882 }
883
884 /**
885 * Get a value from a given key.
886 *
887 * @param[in] key The key
888 * @param[out] bl The bufferlist to be populated with the value
889 */
890 int get_value(const string& key, bufferlist& bl) {
891 return mon->store->get(get_service_name(), key, bl);
892 }
893 /**
894 * Get an integer value from a given key.
895 *
896 * @param[in] key The key
897 */
898 version_t get_value(const string& key) {
899 return mon->store->get(get_service_name(), key);
900 }
901
902 /**
903 * @}
904 */
905 /**
906 * @}
907 */
908 };
909
910 #endif
911