@@ -52,7 +52,8 @@ CheckpointManager::CheckpointManager(EPStats& st,
5252 // when the checkpointList is empty.
5353 // Only in CheckpointManager::clear_UNLOCKED, the checkpointList
5454 // is temporarily cleared and a new open checkpoint added immediately.
55- addOpenCheckpoint (1 , lastSnapStart, lastSnapEnd, CheckpointType::Memory);
55+ addOpenCheckpoint (
56+ 1 , lastSnapStart, lastSnapEnd, {}, CheckpointType::Memory);
5657
5758 if (checkpointConfig.isPersistenceEnabled ()) {
5859 // Register the persistence cursor
@@ -137,13 +138,14 @@ Checkpoint& CheckpointManager::getOpenCheckpoint_UNLOCKED(
137138
138139void CheckpointManager::addNewCheckpoint_UNLOCKED (uint64_t id) {
139140 addNewCheckpoint_UNLOCKED (
140- id, lastBySeqno, lastBySeqno, CheckpointType::Memory);
141+ id, lastBySeqno, lastBySeqno, {}, CheckpointType::Memory);
141142}
142143
143144void CheckpointManager::addNewCheckpoint_UNLOCKED (
144145 uint64_t id,
145146 uint64_t snapStartSeqno,
146147 uint64_t snapEndSeqno,
148+ boost::optional<uint64_t > highCompletedSeqno,
147149 CheckpointType checkpointType) {
148150 // First, we must close the open checkpoint.
149151 auto & oldOpenCkpt = *checkpointList.back ();
@@ -169,7 +171,11 @@ void CheckpointManager::addNewCheckpoint_UNLOCKED(
169171 id,
170172 snapStartSeqno,
171173 snapEndSeqno);
172- addOpenCheckpoint (id, snapStartSeqno, snapEndSeqno, checkpointType);
174+ addOpenCheckpoint (id,
175+ snapStartSeqno,
176+ snapEndSeqno,
177+ highCompletedSeqno,
178+ checkpointType);
173179
174180 /* If cursors reached to the end of its current checkpoint, move it to the
175181 next checkpoint. DCP and Persistence cursors can skip a "checkpoint end"
@@ -202,16 +208,23 @@ void CheckpointManager::addNewCheckpoint_UNLOCKED(
202208 }
203209}
204210
205- void CheckpointManager::addOpenCheckpoint (uint64_t id,
206- uint64_t snapStart,
207- uint64_t snapEnd,
208- CheckpointType checkpointType) {
211+ void CheckpointManager::addOpenCheckpoint (
212+ uint64_t id,
213+ uint64_t snapStart,
214+ uint64_t snapEnd,
215+ boost::optional<uint64_t > highCompletedSeqno,
216+ CheckpointType checkpointType) {
209217 Expects (checkpointList.empty () ||
210218 checkpointList.back ()->getState () ==
211219 checkpoint_state::CHECKPOINT_CLOSED);
212220
213- auto ckpt = std::make_unique<Checkpoint>(
214- stats, id, snapStart, snapEnd, vbucketId, checkpointType);
221+ auto ckpt = std::make_unique<Checkpoint>(stats,
222+ id,
223+ snapStart,
224+ snapEnd,
225+ highCompletedSeqno,
226+ vbucketId,
227+ checkpointType);
215228 // Add an empty-item into the new checkpoint.
216229 // We need this because every CheckpointCursor will point to this empty-item
217230 // at creation. So, the cursor will point at the first actual non-meta item
@@ -842,6 +855,7 @@ CheckpointManager::ItemsForCursor CheckpointManager::getItemsForCursor(
842855 // limit.
843856 ItemsForCursor result ((*cursor.currentCheckpoint )->getSnapshotStartSeqno (),
844857 (*cursor.currentCheckpoint )->getSnapshotEndSeqno (),
858+ (*cursor.currentCheckpoint )->getHighCompletedSeqno (),
845859 (*cursor.currentCheckpoint )->getCheckpointType ());
846860
847861 size_t itemCount = 0 ;
@@ -868,6 +882,11 @@ CheckpointManager::ItemsForCursor CheckpointManager::getItemsForCursor(
868882 result.range .setEnd (
869883 (*cursor.currentCheckpoint )->getSnapshotEndSeqno ());
870884
885+ // Only move the HCS at checkpoint end (don't want to flush a
886+ // HCS mid-checkpoint).
887+ result.highCompletedSeqno =
888+ (*cursor.currentCheckpoint )->getHighCompletedSeqno ();
889+
871890 // However, we *do* want to move the cursor into the next
872891 // checkpoint if possible; as that means the checkpoint we just
873892 // completed has one less cursor in it (and could potentially be
@@ -952,6 +971,7 @@ void CheckpointManager::clear_UNLOCKED(vbucket_state_t vbState, uint64_t seqno)
952971 addOpenCheckpoint (vbucket_state_active ? 1 : 0 /* id */ ,
953972 lastBySeqno,
954973 lastBySeqno,
974+ {},
955975 CheckpointType::Memory);
956976 resetCursors ();
957977}
@@ -1077,9 +1097,11 @@ void CheckpointManager::setBackfillPhase(uint64_t start, uint64_t end) {
10771097 openCkpt.setSnapshotEndSeqno (end);
10781098}
10791099
1080- void CheckpointManager::createSnapshot (uint64_t snapStartSeqno,
1081- uint64_t snapEndSeqno,
1082- CheckpointType checkpointType) {
1100+ void CheckpointManager::createSnapshot (
1101+ uint64_t snapStartSeqno,
1102+ uint64_t snapEndSeqno,
1103+ boost::optional<uint64_t > highCompletedSeqno,
1104+ CheckpointType checkpointType) {
10831105 LockHolder lh (queueLock);
10841106
10851107 auto & openCkpt = getOpenCheckpoint_UNLOCKED (lh);
@@ -1093,11 +1115,15 @@ void CheckpointManager::createSnapshot(uint64_t snapStartSeqno,
10931115 openCkpt.setSnapshotStartSeqno (snapStartSeqno);
10941116 openCkpt.setSnapshotEndSeqno (snapEndSeqno);
10951117 openCkpt.setCheckpointType (checkpointType);
1118+ openCkpt.setHighCompletedSeqno (highCompletedSeqno);
10961119 return ;
10971120 }
10981121
1099- addNewCheckpoint_UNLOCKED (
1100- openCkptId + 1 , snapStartSeqno, snapEndSeqno, checkpointType);
1122+ addNewCheckpoint_UNLOCKED (openCkptId + 1 ,
1123+ snapStartSeqno,
1124+ snapEndSeqno,
1125+ highCompletedSeqno,
1126+ checkpointType);
11011127}
11021128
11031129void CheckpointManager::resetSnapshotRange () {
0 commit comments