|
49 | 49 | import java.util.Collections;
|
50 | 50 | import java.util.List;
|
51 | 51 | import java.util.concurrent.TimeUnit;
|
| 52 | +import java.util.concurrent.atomic.AtomicBoolean; |
52 | 53 | import java.util.concurrent.atomic.AtomicReference;
|
53 | 54 |
|
54 | 55 | import static org.elasticsearch.test.NodeRoles.nonMasterNode;
|
55 | 56 | import static org.hamcrest.Matchers.equalTo;
|
56 | 57 | import static org.hamcrest.Matchers.instanceOf;
|
57 | 58 | import static org.hamcrest.Matchers.not;
|
| 59 | +import static org.mockito.Matchers.anyLong; |
58 | 60 | import static org.mockito.Mockito.mock;
|
59 | 61 | import static org.mockito.Mockito.when;
|
60 | 62 |
|
@@ -296,6 +298,8 @@ public void testStatePersistedOnLoad() throws IOException {
|
296 | 298 | new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), () -> 0L);
|
297 | 299 | final ClusterState state = createClusterState(randomNonNegativeLong(),
|
298 | 300 | Metadata.builder().clusterUUID(randomAlphaOfLength(10)).build());
|
| 301 | + |
| 302 | + //noinspection EmptyTryBlock |
299 | 303 | try (GatewayMetaState.LucenePersistedState ignored = new GatewayMetaState.LucenePersistedState(
|
300 | 304 | persistedClusterStateService, 42L, state)) {
|
301 | 305 |
|
@@ -470,7 +474,7 @@ Directory createDirectory(Path path) {
|
470 | 474 | wrapper.setRandomIOExceptionRateOnOpen(ioExceptionRate.get());
|
471 | 475 | }
|
472 | 476 |
|
473 |
| - for (int i = 0; i < randomIntBetween(1, 5); i++) { |
| 477 | + for (int i = between(1, 5); 0 <= i; i--) { |
474 | 478 | if (randomBoolean()) {
|
475 | 479 | final long version = randomNonNegativeLong();
|
476 | 480 | final String indexName = randomAlphaOfLength(10);
|
@@ -521,10 +525,89 @@ Directory createDirectory(Path path) {
|
521 | 525 | }
|
522 | 526 | }
|
523 | 527 |
|
| 528 | + public void testStatePersistenceWithFatalError() throws IOException { |
| 529 | + final AtomicBoolean throwError = new AtomicBoolean(); |
| 530 | + final BigArrays realBigArrays = getBigArrays(); |
| 531 | + final BigArrays mockBigArrays = mock(BigArrays.class); |
| 532 | + when(mockBigArrays.newByteArray(anyLong())).thenAnswer(invocationOnMock -> |
| 533 | + { |
| 534 | + if (throwError.get() && randomBoolean()) { |
| 535 | + throw new TestError(); |
| 536 | + } |
| 537 | + return realBigArrays.newByteArray((Long) invocationOnMock.getArguments()[0]); |
| 538 | + }); |
| 539 | + |
| 540 | + final PersistedClusterStateService persistedClusterStateService = |
| 541 | + new PersistedClusterStateService(nodeEnvironment, xContentRegistry(), mockBigArrays, |
| 542 | + new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), () -> 0L); |
| 543 | + ClusterState state = createClusterState(randomNonNegativeLong(), |
| 544 | + Metadata.builder().clusterUUID(randomAlphaOfLength(10)).build()); |
| 545 | + long currentTerm = 42L; |
| 546 | + try (GatewayMetaState.LucenePersistedState persistedState = new GatewayMetaState.LucenePersistedState( |
| 547 | + persistedClusterStateService, currentTerm, state)) { |
| 548 | + |
| 549 | + throwError.set(false); |
| 550 | + |
| 551 | + for (int i = between(1, 5); 0 <= i; i--) { |
| 552 | + if (randomBoolean()) { |
| 553 | + final ClusterState newState = createClusterState( |
| 554 | + randomNonNegativeLong(), |
| 555 | + Metadata.builder() |
| 556 | + .clusterUUID(randomAlphaOfLength(10)) |
| 557 | + .coordinationMetadata(CoordinationMetadata.builder().term(currentTerm).build()) |
| 558 | + .build()); |
| 559 | + try { |
| 560 | + persistedState.setLastAcceptedState(newState); |
| 561 | + state = newState; |
| 562 | + } catch (TestError e) { |
| 563 | + // ok |
| 564 | + } |
| 565 | + } else { |
| 566 | + final long newTerm = currentTerm + 1; |
| 567 | + try { |
| 568 | + persistedState.setCurrentTerm(newTerm); |
| 569 | + currentTerm = newTerm; |
| 570 | + } catch (TestError e) { |
| 571 | + // ok |
| 572 | + } |
| 573 | + } |
| 574 | + } |
| 575 | + |
| 576 | + assertEquals(state, persistedState.getLastAcceptedState()); |
| 577 | + assertEquals(currentTerm, persistedState.getCurrentTerm()); |
| 578 | + } |
| 579 | + |
| 580 | + nodeEnvironment.close(); |
| 581 | + |
| 582 | + for (Path path : nodeEnvironment.nodeDataPaths()) { |
| 583 | + Settings settings = Settings.builder() |
| 584 | + .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toAbsolutePath()) |
| 585 | + .put(Environment.PATH_DATA_SETTING.getKey(), path.getParent().getParent().toString()).build(); |
| 586 | + try (NodeEnvironment nodeEnvironment = new NodeEnvironment(settings, TestEnvironment.newEnvironment(settings))) { |
| 587 | + final PersistedClusterStateService newPersistedClusterStateService = |
| 588 | + new PersistedClusterStateService(nodeEnvironment, xContentRegistry(), getBigArrays(), |
| 589 | + new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), () -> 0L); |
| 590 | + final PersistedClusterStateService.OnDiskState onDiskState = newPersistedClusterStateService.loadBestOnDiskState(); |
| 591 | + assertFalse(onDiskState.empty()); |
| 592 | + assertThat(onDiskState.currentTerm, equalTo(currentTerm)); |
| 593 | + assertClusterStateEqual(state, |
| 594 | + ClusterState.builder(ClusterName.DEFAULT) |
| 595 | + .version(onDiskState.lastAcceptedVersion) |
| 596 | + .metadata(onDiskState.metadata).build()); |
| 597 | + } |
| 598 | + } |
| 599 | + } |
| 600 | + |
524 | 601 | private static BigArrays getBigArrays() {
|
525 | 602 | return usually()
|
526 | 603 | ? BigArrays.NON_RECYCLING_INSTANCE
|
527 | 604 | : new MockBigArrays(new MockPageCacheRecycler(Settings.EMPTY), new NoneCircuitBreakerService());
|
528 | 605 | }
|
529 | 606 |
|
| 607 | + private static final class TestError extends Error { |
| 608 | + TestError() { |
| 609 | + super("test error"); |
| 610 | + } |
| 611 | + } |
| 612 | + |
530 | 613 | }
|
0 commit comments