127
* The state we are in.
136
* Check if we are recovering.
138
* @return 'true' if we are on the Recovering state; 'false' otherwise.
102
140
bool is_recovering() const { return state == STATE_RECOVERING; }
142
* Check if we are active.
144
* @return 'true' if we are on the Active state; 'false' otherwise.
103
146
bool is_active() const { return state == STATE_ACTIVE; }
148
* Check if we are updating.
150
* @return 'true' if we are on the Updating state; 'false' otherwise.
104
152
bool is_updating() const { return state == STATE_UPDATING; }
107
// recovery (phase 1)
156
* @defgroup Paxos_h_recovery_vars Common recovery-related member variables
157
* @note These variables are common to both the Leader and the Peons.
108
163
version_t first_committed;
165
* Last Proposal Number
167
* @todo Expand description
109
169
version_t last_pn;
171
* Last committed value's version.
173
* On both the Leader and the Peons, this is the last value's version that
174
* was accepted by a given quorum and thus committed, that this instance
177
* @note It may not be the last committed value's version throughout the
178
* system. If we are a Peon, we may have not been part of the quorum
179
* that accepted the value, and for this very same reason we may still
180
* be a (couple of) version(s) behind, until we learn about the most
181
* recent version. This should only happen if we are not active (i.e.,
182
* part of the quorum), which should not happen if we are up, running
183
* and able to communicate with others -- thus able to be part of the
184
* monmap and trigger new elections.
110
186
version_t last_committed;
188
* Last committed value's time.
190
* When the commit happened.
111
192
utime_t last_commit_time;
194
* The last Proposal Number we have accepted.
196
* On the Leader, it will be the Proposal Number picked by the Leader
197
* itself. On the Peon, however, it will be the proposal sent by the Leader
198
* and it will only be updated iif its value is higher than the one
199
* already known by the Peon.
112
201
version_t accepted_pn;
203
* @todo This has something to do with the last_committed version. Not sure
204
* about what it entails, tbh.
113
206
version_t accepted_pn_from;
114
map<int,version_t> peer_first_committed, peer_last_committed;
208
* @todo Check out if this map has any purpose at all. So far, we have only
209
* seen it being read, although it is never affected.
211
map<int,version_t> peer_first_committed;
213
* Map holding the last committed version by each quorum member.
215
* The versions kept in this map are updated during the collect phase.
216
* When the Leader starts the collect phase, each Peon will reply with its
217
* last committed version, which will then be kept in this map.
219
map<int,version_t> peer_last_committed;
221
* @todo Check out what 'slurping' is.
117
228
// active (phase 2)
230
* @defgroup Paxos_h_active_vars Common active-related member variables
234
* When does our read lease expires.
236
* Instead of performing a full commit each time a read is requested, we
237
* keep leases. Each lease will have an expiration date, which may or may
238
* not be extended. This member variable will keep when is the lease
118
241
utime_t lease_expire;
243
* List of callbacks waiting for our state to change into STATE_ACTIVE.
119
245
list<Context*> waiting_for_active;
247
* List of callbacks waiting for the chance to read a version from us.
249
* Each entry on the list may result from an attempt to read a version that
250
* wasn't available at the time, or an attempt made during a period during
251
* which we could not satisfy the read request. The first case happens if
252
* the requested version is greater than our last committed version. The
253
* second scenario may happen if we are recovering, or if we don't have a
256
* The list will be woken up once we change to STATE_ACTIVE with an extended
257
* lease -- which can be achieved if we have everyone on the quorum on board
258
* with the latest proposal, or if we don't really care about the remaining
259
* uncommitted values --, or if we're on a quorum of one.
120
261
list<Context*> waiting_for_readable;
264
* Latest version written to the store after the latest commit.
122
266
version_t latest_stashed;
125
272
// recovery (paxos phase 1)
274
* @defgroup Paxos_h_leader_recovery Leader-specific Recovery-related vars
278
* Number of replies to the collect phase we've received so far.
280
* This variable is reset to 1 each time we start a collect phase; it is
281
* incremented each time we receive a reply to the collect message, and
282
* is used to determine whether or not we have received replies from the
126
285
unsigned num_last;
287
* Uncommitted value's version.
289
* If we have, or end up knowing about, an uncommitted value, then its
290
* version will be kept in this variable.
292
* @note If this version equals @p last_committed+1 when we reach the final
293
* steps of recovery, then the algorithm will assume this is a value
294
* the Leader does not know about, and trustingly the Leader will
295
* propose this version's value.
127
297
version_t uncommitted_v;
299
* Uncommitted value's Proposal Number.
301
* We use this variable to assess if the Leader should take into consideration
302
* an uncommitted value sent by a Peon. Given that the Peon will send back to
303
* the Leader the last Proposal Number he accepted, the Leader will be able
304
* to infer if this value is more recent than the one the Leader has, thus
128
307
version_t uncommitted_pn;
311
* If the system fails in-between the accept replies from the Peons and the
312
* instruction to commit from the Leader, then we may end up with accepted
313
* but yet-uncommitted values. During the Leader's recovery, he will attempt
314
* to bring the whole system to the latest state, and that means committing
315
* past accepted but uncommitted values.
317
* This variable will hold an uncommitted value, which may originate either
318
* on the Leader, or learnt by the Leader from a Peon during the collect
129
321
bufferlist uncommitted_value;
323
* Used to specify when an on-going collect phase times out.
131
325
Context *collect_timeout_event;
332
* @defgroup Paxos_h_leader_active Leader-specific Active-related vars
336
* Set of participants (Leader & Peons) that have acked a lease extension.
338
* Each Peon that acknowledges a lease extension will have its place in this
339
* set, which will be used to account for all the acks from all the quorum
340
* members, guaranteeing that we trigger new elections if some don't ack in
341
* the expected timeframe.
134
343
set<int> acked_lease;
345
* Callback responsible for extending the lease periodically.
135
347
Context *lease_renew_event;
349
* Callback to trigger new elections once the time for acks is out.
136
351
Context *lease_ack_timeout_event;
356
* @defgroup Paxos_h_peon_active Peon-specific Active-related vars
360
* Callback to trigger new elections when the Peon's lease times out.
362
* If the Peon's lease is extended, this callback will be reset (i.e.,
363
* we cancel the event and reschedule a new one with starting from the
137
366
Context *lease_timeout_event;
139
371
// updating (paxos phase 2)
373
* @defgroup Paxos_h_leader_updating Leader-specific Updating-related vars
377
* New Value being proposed to the Peons.
379
* This bufferlist holds the value the Leader is proposing to the Peons, and
380
* that will be committed if the Peons do accept the proposal.
140
382
bufferlist new_value;
384
* Set of participants (Leader & Peons) that accepted the new proposed value.
386
* This set is used to keep track of those who have accepted the proposed
387
* value, so the leader may know when to issue a commit (when a majority of
388
* participants has accepted the proposal), and when to extend the lease
389
* (when all the quorum members have accepted the proposal).
141
391
set<int> accepted;
393
* Callback to trigger a new election if the proposal is not accepted by the
394
* full quorum within a given timeframe.
396
* If the full quorum does not accept the proposal, then it means that the
397
* Leader may no longer be recognized as the leader, or that the quorum has
398
* changed, and the value may have not reached all the participants. Thus,
399
* the leader must call new elections, and go through a recovery phase in
400
* order to propagate the new value throughout the system.
402
* This does not mean that we won't commit. We will commit as soon as we
403
* have a majority of acceptances. But if we do not have full acceptance
404
* from the quorum, then we cannot extend the lease, as some participants
405
* may not have the latest committed value.
143
407
Context *accept_timeout_event;
410
* List of callbacks waiting for it to be possible to write again.
412
* @remarks It is not possible to write if we are not the Leader, or we are
413
* not on the active state, or if the lease has expired.
145
415
list<Context*> waiting_for_writeable;
417
* List of callbacks waiting for a commit to finish.
419
* @remarks This may be used to a) wait for an on-going commit to finish
420
* before we proceed with, say, a new proposal; or b) wait for the
421
* next commit to be finished so we are sure that our value was
146
424
list<Context*> waiting_for_commit;
151
version_t last_version;
153
Observer(entity_inst_t& ei, version_t v) : inst(ei), last_version(v) { }
155
map<entity_inst_t, Observer *> observers;
157
//synchronization warnings
430
* @defgroup Paxos_h_sync_warns Synchronization warnings
431
* @todo Describe these variables
158
434
utime_t last_clock_drift_warn;
159
435
int clock_drift_warned;
442
* @defgroup Paxos_h_callbacks Callback classes.
446
* Callback class responsible for handling a Collect Timeout.
162
448
class C_CollectTimeout : public Context {
203
501
paxos->lease_renew_timeout();
509
* @defgroup Paxos_h_election_triggered Steps triggered by an election.
511
* @note All these functions play a significant role in the Recovery Phase,
512
* which is triggered right after an election once someone becomes
517
* Create a new Proposal Number and propose it to the Peons.
519
* This function starts the Recovery Phase, which can be directly mapped
520
* onto the original Paxos' Prepare phase. Basically, we'll generate a
521
* Proposal Number, taking @p oldpn into consideration, and we will send
522
* it to a quorum, along with our first and last committed versions. By
523
* sending these informations in a message to the quorum, we expect to
524
* obtain acceptances from a majority, allowing us to commit, or be
525
* informed of a higher Proposal Number known by one or more of the Peons
528
* @pre We are the Leader.
529
* @post Recovery Phase initiated by sending messages to the quorum.
531
* @param oldpn A proposal number taken as the highest known so far, that
532
* should be taken into consideration when generating a new
533
* Proposal Number for the Recovery Phase.
208
535
void collect(version_t oldpn);
209
void handle_collect(MMonPaxos*);
210
void handle_last(MMonPaxos*);
537
* Handle the reception of a collect message from the Leader and reply
540
* Once a Peon receives a collect message from the Leader it will reply
541
* with its first and last committed versions, as well as informations so
542
* the Leader may know if his Proposal Number was, or was not, accepted by
543
* the Peon. The Peon will accept the Leader's Proposal Number iif it is
544
* higher than the Peon's currently accepted Proposal Number. The Peon may
545
* also inform the Leader of accepted but uncommitted values.
547
* @invariant The message is an operation of type OP_COLLECT.
548
* @pre We are a Peon.
549
* @post Replied to the Leader, accepting or not accepting his PN.
551
* @param collect The collect message sent by the Leader to the Peon.
553
void handle_collect(MMonPaxos *collect);
555
* Handle a response from a Peon to the Leader's collect phase.
557
* The received message will state the Peon's last committed version, as
558
* well as its last proposal number. This will lead to one of the following
559
* scenarios: if the replied Proposal Number is equal to the one we proposed,
560
* then the Peon has accepted our proposal, and if all the Peons do accept
561
* our Proposal Number, then we are allowed to proceed with the commit;
562
* however, if a Peon replies with a higher Proposal Number, we assume he
563
* knows something we don't and the Leader will have to abort the current
564
* proposal in order to retry with the Proposal Number specified by the Peon.
565
* It may also occur that the Peon replied with a lower Proposal Number, in
566
* which case we assume it is a reply to an an older value and we'll simply
568
* This function will also check if the Peon replied with an accepted but
569
* yet uncommitted value. In this case, if its version is higher than our
570
* last committed value by one, we assume that the Peon knows a value from a
571
* previous proposal that has never been committed, and we should try to
572
* commit that value by proposing it next. On the other hand, if that is
573
* not the case, we'll assume it is an old, uncommitted value, we do not
574
* care about and we'll consider the system active by extending the leases.
576
* @invariant The message is an operation of type OP_LAST.
577
* @pre We are the Leader.
578
* @post We initiate a commit, or we retry with a higher Proposal Number,
579
* or we drop the message.
580
* @post We move from STATE_RECOVERING to STATE_ACTIVE.
582
* @param last The message sent by the Peon to the Leader.
584
void handle_last(MMonPaxos *last);
586
* The Recovery Phase timed out, meaning that a significant part of the
587
* quorum does not believe we are the Leader, and we thus should trigger new
590
* @pre We believe to be the Leader.
591
* @post Trigger new elections.
211
593
void collect_timeout();
599
* @defgroup Paxos_h_updating_funcs Functions used during the Updating State
601
* These functions may easily be mapped to the original Paxos Algorithm's
604
* Taking into account the algorithm can be divided in 4 phases (Prepare,
605
* Promise, Accept Request and Accepted), we can easily map Paxos::begin to
606
* both the Prepare and Accept Request phases; the Paxos::handle_begin to
607
* the Promise phase; and the Paxos::handle_accept to the Accepted phase.
611
* Start a new proposal with the intent of committing @p value.
613
* If we are alone on the system (i.e., a quorum of one), then we will
614
* simply commit the value, but if we are not alone, then we need to propose
615
* the value to the quorum.
617
* @pre We are the Leader
618
* @pre We are on STATE_ACTIVE
619
* @post We commit, iif we are alone, or we send a message to each quorum
621
* @post We are on STATE_ACTIVE, iif we are alone, or on
622
* STATE_UPDATING otherwise
624
* @param value The value being proposed to the quorum
213
626
void begin(bufferlist& value);
214
void handle_begin(MMonPaxos*);
215
void handle_accept(MMonPaxos*);
628
* Accept or decline (by ignoring) a proposal from the Leader.
630
* We will decline the proposal (by ignoring it) if we have promised to
631
* accept a higher numbered proposal. If that is not the case, we will
632
* accept it and accordingly reply to the Leader.
635
* @pre We are on STATE_ACTIVE
636
* @post We are on STATE_UPDATING iif we accept the Leader's proposal
637
* @post We send a reply message to the Leader iif we accept his proposal
639
* @invariant The received message is an operation of type OP_BEGIN
641
* @param begin The message sent by the Leader to the Peon during the
642
* Paxos::begin function
645
void handle_begin(MMonPaxos *begin);
647
* Handle an Accept message sent by a Peon.
649
* In order to commit, the Leader has to receive accepts from a majority of
650
* the quorum. If that does happen, then the Leader may proceed with the
651
* commit. However, the Leader needs the accepts from all the quorum members
652
* in order to extend the lease and move on to STATE_ACTIVE.
654
* This function handles these two situations, accounting for the amount of
657
* @pre We are the Leader
658
* @pre We are on STATE_UPDATING
659
* @post We are on STATE_ACTIVE iif we received accepts from the full quorum
660
* @post We extended the lease iif we moved on to STATE_ACTIVE
661
* @post We are on STATE_UPDATING iif we didn't received accepts from the
663
* @post We have committed iif we received accepts from a majority
665
* @invariant The received message is an operation of type OP_ACCEPT
667
* @param accept The message sent by the Peons to the Leader during the
668
* Paxos::handle_begin function
670
void handle_accept(MMonPaxos *accept);
672
* Trigger a fresh election.
674
* During Paxos::begin we set a Callback of type Paxos::C_AcceptTimeout in
675
* order to limit the amount of time we spend waiting for Accept replies.
676
* This callback will call Paxos::accept_timeout when it is fired.
678
* This is essential to the algorithm because there may be the chance that
679
* we are no longer the Leader (i.e., others don't believe in us) and we
680
* are getting ignored, or we dropped out of the quorum and haven't realised
681
* it. So, our only option is to trigger fresh elections.
683
* @pre We are the Leader
684
* @pre We are on STATE_UPDATING
685
* @post Triggered fresh elections
216
687
void accept_timeout();
693
* Commit a value throughout the system.
695
* The Leader will cancel the current lease (as it was for the old value),
696
* and will store the committed value locally. It will then instruct every
697
* quorum member to do so as well.
699
* @pre We are the Leader
700
* @pre We are on STATE_UPDATING
701
* @pre A majority of quorum members accepted our proposal
702
* @post Value locally stored
703
* @post Quorum members instructed to commit the new value.
219
void handle_commit(MMonPaxos*);
707
* Commit the new value to stable storage as being the latest available
711
* @post The new value is locally stored
712
* @post Fire up the callbacks waiting on waiting_for_commit
714
* @invariant The received message is an operation of type OP_COMMIT
716
* @param commit The message sent by the Leader to the Peon during
719
void handle_commit(MMonPaxos *commit);
721
* Extend the system's lease.
723
* This means that the Leader considers that it should now safe to read from
724
* any node on the system, since every quorum member is now in possession of
725
* the latest version. Therefore, the Leader will send a message stating just
726
* this to each quorum member, and will impose a limited timeframe during
727
* which acks will be accepted. If there aren't as many acks as expected
728
* (i.e, if at least one quorum member does not ack the lease) during this
729
* timeframe, then we will force fresh elections.
731
* @pre We are the Leader
732
* @pre We are on STATE_ACTIVE
733
* @post A message extending the lease is sent to each quorum member
734
* @post A timeout callback is set to limit the amount of time we will wait
736
* @post A timer is set in order to renew the lease after a certain amount
220
739
void extend_lease();
221
void handle_lease(MMonPaxos*);
222
void handle_lease_ack(MMonPaxos*);
224
void lease_ack_timeout(); // on leader, if lease isn't acked by all peons
225
void lease_renew_timeout(); // on leader, to renew the lease
741
* Update the lease on the Peon's side of things.
743
* Once a Peon receives a Lease message, it will update its lease_expire
744
* variable, reply to the Leader acknowledging the lease update and set a
745
* timeout callback to be fired upon the lease's expiration. Finally, the
746
* Peon will fire up all the callbacks waiting for it to become active,
747
* which it just did, and all those waiting for it to become readable,
748
* which should be true if the Peon's lease didn't expire in the mean time.
751
* @post We update the lease accordingly
752
* @post A lease timeout callback is set
753
* @post Move to STATE_ACTIVE
754
* @post Fire up all the callbacks waiting for STATE_ACTIVE
755
* @post Fire up all the callbacks waiting for readable iif we are readable
756
* @post Ack the lease to the Leader
758
* @invariant The received message is an operation of type OP_LEASE
760
* @param The message sent by the Leader to the Peon during the
761
* Paxos::extend_lease function
763
void handle_lease(MMonPaxos *lease);
765
* Account for all the Lease Acks the Leader receives from the Peons.
767
* Once the Leader receives all the Lease Acks from the Peons, it will be
768
* able to cancel the Lease Ack timeout callback, thus avoiding calling
771
* @pre We are the Leader
772
* @post Cancel the Lease Ack timeout callback iif we receive acks from all
775
* @invariant The received message is an operation of type OP_LEASE_ACK
777
* @param ack The message sent by a Peon to the Leader during the
778
* Paxos::handle_lease function
780
void handle_lease_ack(MMonPaxos *ack);
782
* Call fresh elections because at least one Peon didn't acked our lease.
784
* @pre We are the Leader
785
* @pre We are on STATE_ACTIVE
786
* @post Trigger fresh elections
788
void lease_ack_timeout();
790
* Extend lease since we haven't had new committed values meanwhile.
792
* @pre We are the Leader
793
* @pre We are on STATE_ACTIVE
794
* @post Go through with Paxos::extend_lease
796
void lease_renew_timeout();
798
* Call fresh elections because the Peon's lease expired without being
799
* renewed or receiving a fresh lease.
801
* This means that the Peon is no longer assumed as being in the quorum
802
* (or there is no Leader to speak of), so just trigger fresh elections
803
* to circumvent this issue.
806
* @post Trigger fresh elections
226
808
void lease_timeout(); // on peon, if lease isn't extended
811
* Cancel all of Paxos' timeout/renew events.
228
813
void cancel_events();
816
* Generate a new Proposal Number based on @p gt
818
* @todo Check what @p gt actually means and what its usage entails
819
* @param gt A hint for the geration of the Proposal Number
820
* @return A globally unique, monotonically increasing Proposal Number
230
822
version_t get_new_proposal_number(version_t gt=0);
825
* @todo document sync function
232
827
void warn_on_future_time(utime_t t, entity_name_t from);
832
* @param mid A machine id
235
834
Paxos(Monitor *m,
236
835
int mid) : mon(m),
266
865
bool is_consistent();
869
* Initiate the Leader after it wins an election.
871
* Once an election is won, the Leader will be initiated and there are two
872
* possible outcomes of this method: the Leader directly jumps to the active
873
* state (STATE_ACTIVE) if it believes to be the only one in the quorum, or
874
* will start recovering (STATE_RECOVERING) by initiating the collect phase.
876
* @pre Our monitor is the Leader.
877
* @post We are either on STATE_ACTIVE if we're the only one in the quorum,
878
* or on STATE_RECOVERING otherwise.
269
880
void leader_init();
882
* Initiate a Peon after it loses an election.
884
* If we are a Peon, then there must be a Leader and we are not alone in the
885
* quorum, thus automatically assume we are on STATE_RECOVERING, which means
886
* we will soon be enrolled into the Leader's collect phase.
888
* @pre There is a Leader, and he's about to start the collect phase.
889
* @post We are on STATE_RECOVERING and will soon receive collect phase's
270
892
void peon_init();
272
void share_state(MMonPaxos *m, version_t first_committed, version_t last_committed);
895
* Include an incremental state of values, ranging from peer_first_committed
896
* to the last committed value, on the message m
899
* @param peer_first_committed Lowest version to take into account
900
* @param peer_last_committed Highest version to take into account
902
void share_state(MMonPaxos *m, version_t peer_first_committed,
903
version_t peer_last_committed);
905
* Store the state held on the message m into local, stable storage.
273
909
void store_state(MMonPaxos *m);
912
* @todo This appears to be used only by the OSDMonitor, and I would say
913
* its objective is to allow a third-party to have a "private"
275
916
void add_extra_state_dir(string s) {
276
917
extra_state_dirs.push_back(s);
279
920
// -- service interface --
922
* Add c to the list of callbacks waiting for us to become active.
924
* @param c A callback
280
926
void wait_for_active(Context *c) {
281
927
waiting_for_active.push_back(c);
931
* Erase old states from stable storage.
933
* @param first The version we are trimming to
934
* @param force If specified, we may even erase the latest stashed version
935
* iif @p first is higher than that version.
284
937
void trim_to(version_t first, bool force=false);
940
* @defgroup Paxos_h_slurping_funcs Slurping-related functions
941
* @todo Discover what slurping is
286
944
void start_slurping();
287
945
void end_slurping();
288
946
bool is_slurping() { return slurping == 1; }
953
* @defgroup Paxos_h_read_funcs Read-related functions
957
* Get latest committed version
959
* @return latest committed version
291
961
version_t get_version() { return last_committed; }
963
* Get first committed version
965
* @return the first committed version
967
version_t get_first_committed() { return first_committed; }
969
* Check if a given version is readable.
971
* A version may not be readable for a myriad of reasons:
972
* @li the version @v is higher that the last committed version
973
* @li we are not the Leader nor a Peon (election may be on-going)
974
* @li we do not have a committed value yet
975
* @li we do not have a valid lease
977
* @param seen The version we want to check if it is readable.
978
* @return 'true' if the version is readable; 'false' otherwise.
292
980
bool is_readable(version_t seen=0);
982
* Read version @v and store its value in @bl
984
* @param[in] v The version we want to read
985
* @param[out] bl The version's value
986
* @return 'true' if we successfully read the value; 'false' otherwise
293
988
bool read(version_t v, bufferlist &bl);
990
* Read the latest committed version
992
* @param[out] bl The version's value
993
* @return the latest committed version if we successfully read the value;
994
* or 0 (zero) otherwise.
294
996
version_t read_current(bufferlist &bl);
998
* Add onreadable to the list of callbacks waiting for us to become readable.
1000
* @param onreadable A callback
295
1002
void wait_for_readable(Context *onreadable) {
296
1003
//assert(!is_readable());
297
1004
waiting_for_readable.push_back(onreadable);
1011
* @warning This declaration is not implemented anywhere and appears to be
1012
* just some lingering code.
1017
* @defgroup Paxos_h_write_funcs Write-related functions
1021
* Check if we are writeable.
1023
* We are writeable if we are alone (i.e., a quorum of one), or if we match
1024
* all the following conditions:
1025
* @li We are the Leader
1026
* @li We are on STATE_ACTIVE
1027
* @li We have a valid lease
1029
* @return 'true' if we are writeable; 'false' otherwise.
302
1031
bool is_writeable();
1033
* Add c to the list of callbacks waiting for us to become writeable.
1035
* @param c A callback
303
1037
void wait_for_writeable(Context *c) {
304
1038
assert(!is_writeable());
305
1039
waiting_for_writeable.push_back(c);
1043
* Propose a new value to the Leader.
1045
* This function enables the submission of a new value to the Leader, which
1046
* will trigger a new proposal.
1048
* @param bl A bufferlist holding the value to be proposed
1049
* @param oncommit A callback to be fired up once we finish committing bl
308
1051
bool propose_new_value(bufferlist& bl, Context *oncommit=0);
1053
* Add oncommit to the back of the list of callbacks waiting for us to
1054
* finish committing.
1056
* @param oncommit A callback
309
1058
void wait_for_commit(Context *oncommit) {
310
1059
waiting_for_commit.push_back(oncommit);
1062
* Add oncommit to the front of the list of callbacks waiting for us to
1063
* finish committing.
1065
* @param oncommit A callback
312
1067
void wait_for_commit_front(Context *oncommit) {
313
1068
waiting_for_commit.push_front(oncommit);
316
// if state values are incrementals, it is usefult to keep
317
// the latest copy of the complete structure.
1075
* @defgroup Paxos_h_stash_funcs State values stashing-related functions
1077
* If the state values are incrementals, it is useful to keep the latest
1078
* copy of the complete structure.
1083
* Get the latest version onto stable storage.
1085
* Keeping the latest version on a predefined location makes it easier to
1086
* access, since we know we always have the latest version on the same
1089
* @param v the latest version
1090
* @param bl the latest version's value
318
1092
void stash_latest(version_t v, bufferlist& bl);
1094
* Get the latest stashed version's value
1096
* @param[out] bl the latest stashed version's value
1097
* @return the latest stashed version
319
1099
version_t get_stashed(bufferlist& bl);
1101
* Get the latest stashed version
1103
* @return the latest stashed version
320
1105
version_t get_stashed_version() { return latest_stashed; }
322
version_t get_first_committed() { return first_committed; }
324
void register_observer(entity_inst_t inst, version_t v);
325
void update_observers();