|
66 | 66 | import org.apache.ignite.internal.util.GridConcurrentMultiPairQueue;
|
67 | 67 | import org.apache.ignite.internal.util.GridMultiCollectionWrapper;
|
68 | 68 | import org.apache.ignite.internal.util.StripedExecutor;
|
| 69 | +import org.apache.ignite.internal.util.function.ThrowableSupplier; |
69 | 70 | import org.apache.ignite.internal.util.future.GridCompoundFuture;
|
70 |
| -import org.apache.ignite.internal.util.future.GridFinishedFuture; |
71 | 71 | import org.apache.ignite.internal.util.future.GridFutureAdapter;
|
72 | 72 | import org.apache.ignite.internal.util.typedef.T2;
|
73 | 73 | import org.apache.ignite.internal.util.typedef.internal.U;
|
@@ -216,14 +216,16 @@ private IgniteThreadPoolExecutor initializeCheckpointPool() {
|
216 | 216 | * @param curr Current checkpoint event info.
|
217 | 217 | * @param tracker Checkpoint metrics tracker.
|
218 | 218 | * @param workProgressDispatcher Work progress dispatcher.
|
| 219 | + * @param writeRecoveryData Write recovery data on checkpoint. |
219 | 220 | * @return Checkpoint collected info.
|
220 | 221 | * @throws IgniteCheckedException if fail.
|
221 | 222 | */
|
222 | 223 | public Checkpoint markCheckpointBegin(
|
223 | 224 | long cpTs,
|
224 | 225 | CheckpointProgressImpl curr,
|
225 | 226 | CheckpointMetricsTracker tracker,
|
226 |
| - WorkProgressDispatcher workProgressDispatcher |
| 227 | + WorkProgressDispatcher workProgressDispatcher, |
| 228 | + boolean writeRecoveryData |
227 | 229 | ) throws IgniteCheckedException {
|
228 | 230 | Collection<DataRegion> checkpointedRegions = dataRegions.get();
|
229 | 231 |
|
@@ -276,8 +278,26 @@ curr, new PartitionAllocationMap(), checkpointCollectPagesInfoPool, workProgress
|
276 | 278 |
|
277 | 279 | fillCacheGroupState(cpRec);
|
278 | 280 |
|
279 |
| - //There are allowable to replace pages only after checkpoint entry was stored to disk. |
280 |
| - cpPagesHolder = beginAllCheckpoints(checkpointedRegions, curr.futureFor(MARKER_STORED_TO_DISK)); |
| 281 | + IgniteInternalFuture<?> markerStoredToDiskFut = curr.futureFor(MARKER_STORED_TO_DISK); |
| 282 | + |
| 283 | + // There are allowable to replace pages only after checkpoint entry was stored to disk. |
| 284 | + ThrowableSupplier<Boolean, IgniteCheckedException> allowToReplace = writeRecoveryData ? |
| 285 | + () -> { |
| 286 | + // If we write recovery data on checkpoint it's not safe to wait for MARKER_STORED_TO_DISK future, |
| 287 | + // recovery data writers acquire page memory segments locks to write the pages, in the same time |
| 288 | + // another thread can lock page memory segment for writing during page replacement and wait for |
| 289 | + // marker stored to disk, so deadlock is possible. |
| 290 | + return curr.greaterOrEqualTo(MARKER_STORED_TO_DISK); |
| 291 | + } : |
| 292 | + () -> { |
| 293 | + // Uninterruptibly is important because otherwise in case of interrupt of client thread node |
| 294 | + // would be stopped. |
| 295 | + markerStoredToDiskFut.getUninterruptibly(); |
| 296 | + |
| 297 | + return true; |
| 298 | + }; |
| 299 | + |
| 300 | + cpPagesHolder = beginAllCheckpoints(checkpointedRegions, allowToReplace); |
281 | 301 |
|
282 | 302 | curr.currentCheckpointPagesCount(cpPagesHolder.pagesNum());
|
283 | 303 |
|
@@ -416,8 +436,10 @@ private void fillCacheGroupState(CheckpointRecord cpRec) throws IgniteCheckedExc
|
416 | 436 | * @return holder of FullPageIds obtained from each PageMemory, overall number of dirty pages, and flag defines at
|
417 | 437 | * least one user page became a dirty since last checkpoint.
|
418 | 438 | */
|
419 |
| - private CheckpointPagesInfoHolder beginAllCheckpoints(Collection<DataRegion> regions, |
420 |
| - IgniteInternalFuture<?> allowToReplace) { |
| 439 | + private CheckpointPagesInfoHolder beginAllCheckpoints( |
| 440 | + Collection<DataRegion> regions, |
| 441 | + ThrowableSupplier<Boolean, IgniteCheckedException> allowToReplace |
| 442 | + ) { |
421 | 443 | Collection<Map.Entry<PageMemoryEx, GridMultiCollectionWrapper<FullPageId>>> res =
|
422 | 444 | new ArrayList<>(regions.size());
|
423 | 445 |
|
@@ -611,7 +633,7 @@ public void finalizeCheckpointOnRecovery(
|
611 | 633 |
|
612 | 634 | Collection<DataRegion> regions = dataRegions.get();
|
613 | 635 |
|
614 |
| - CheckpointPagesInfoHolder cpPagesHolder = beginAllCheckpoints(regions, new GridFinishedFuture<>()); |
| 636 | + CheckpointPagesInfoHolder cpPagesHolder = beginAllCheckpoints(regions, () -> Boolean.TRUE); |
615 | 637 |
|
616 | 638 | // Sort and split all dirty pages set to several stripes.
|
617 | 639 | GridConcurrentMultiPairQueue<PageMemoryEx, FullPageId> pages =
|
|
0 commit comments