blob: 4ecba7d185c62689a4b25ea32982c134a128a1a6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.cache;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.same;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.apache.geode.internal.cache.entries.DiskEntry;
import org.apache.geode.internal.cache.entries.DiskEntry.Helper.ValueWrapper;
import org.apache.geode.internal.cache.persistence.DiskRecoveryStore;
import org.apache.geode.internal.cache.persistence.DiskRegionView;
public class PersistentOplogSetTest {
private DiskStoreImpl diskStore;
private DiskStoreStats diskStoreStats;
private InternalRegion region;
private DiskEntry entry;
private ValueWrapper value;
private Oplog oplog;
private PersistentOplogSet persistentOplogSet;
@Before
public void setUp() {
diskStore = mock(DiskStoreImpl.class);
diskStoreStats = mock(DiskStoreStats.class);
region = mock(InternalRegion.class);
entry = mock(DiskEntry.class);
value = mock(ValueWrapper.class);
oplog = mock(Oplog.class);
persistentOplogSet = new PersistentOplogSet(diskStore, System.out);
}
@Test
public void createDelegatesToChildOplog() {
persistentOplogSet.setChild(oplog);
persistentOplogSet.create(region, entry, value, true);
verify(oplog).create(same(region), same(entry), same(value), eq(true));
}
@Test
public void modifyDelegatesToChildOplog() {
persistentOplogSet.setChild(oplog);
persistentOplogSet.modify(region, entry, value, true);
verify(oplog).modify(same(region), same(entry), same(value), eq(true));
}
@Test
public void removeDelegatesToChildOplog() {
persistentOplogSet.setChild(oplog);
persistentOplogSet.remove(region, entry, false, true);
verify(oplog).remove(same(region), same(entry), eq(false), eq(true));
}
@Test
public void getChildReturnsChildOplogIfOplogIdMatches() {
persistentOplogSet.setChild(oplog);
when(oplog.getOplogId()).thenReturn(42L);
CompactableOplog value = persistentOplogSet.getChild(42L);
assertThat(value).isSameAs(oplog);
}
@Test
public void getChildReturnsNullIfOplogIdDoesNotMatch() {
persistentOplogSet.setChild(oplog);
when(oplog.getOplogId()).thenReturn(42L);
CompactableOplog value = persistentOplogSet.getChild(24L);
assertThat(value).isNull();
}
@Test
public void getChildReturnsMatchingEntryFromOplogIdToOplogMap() {
Oplog oplog = mock(Oplog.class);
persistentOplogSet.setChild(null);
persistentOplogSet.getOplogIdToOplog().put(24L, oplog);
CompactableOplog value = persistentOplogSet.getChild(24L);
assertThat(value).isSameAs(oplog);
}
@Test
public void getChildReturnsNullIfEntriesInOplogIdToOplogMapDoNotMatch() {
Oplog oplog = mock(Oplog.class);
persistentOplogSet.setChild(null);
persistentOplogSet.getOplogIdToOplog().put(42L, oplog);
CompactableOplog value = persistentOplogSet.getChild(24L);
assertThat(value).isNull();
}
@Test
public void getChildReturnsMatchingEntryFromInactiveOplogMap() {
Oplog oplog = mock(Oplog.class);
persistentOplogSet.setChild(null);
when(oplog.getOplogId()).thenReturn(24L);
when(diskStore.getStats()).thenReturn(diskStoreStats);
persistentOplogSet.addInactive(oplog);
CompactableOplog value = persistentOplogSet.getChild(24L);
assertThat(value).isSameAs(oplog);
}
@Test
public void getChildReturnsNullIfEntriesInInactiveOplogMapDoNotMatch() {
Oplog oplog = mock(Oplog.class);
persistentOplogSet.setChild(null);
when(oplog.getOplogId()).thenReturn(42L);
when(diskStore.getStats()).thenReturn(diskStoreStats);
persistentOplogSet.addInactive(oplog);
CompactableOplog value = persistentOplogSet.getChild(24L);
assertThat(value).isNull();
}
@Test
public void getCompactableOplogsGathersOnlyOplogsThatNeedCompaction() {
Oplog oplogNeedingCompaction1 = oplog(true);
Oplog oplogNeedingCompaction2 = oplog(true);
Map<Long, Oplog> oplogMap = persistentOplogSet.getOplogIdToOplog();
oplogMap.put(0L, oplog(false));
oplogMap.put(1L, oplogNeedingCompaction1);
oplogMap.put(2L, oplogNeedingCompaction2);
oplogMap.put(3L, oplog(false));
List<CompactableOplog> compactableOplogs = new ArrayList<>();
persistentOplogSet.getCompactableOplogs(compactableOplogs, 5);
assertThat(compactableOplogs)
.containsExactlyInAnyOrder(oplogNeedingCompaction1, oplogNeedingCompaction2);
}
@Test
public void getCompactableOplogsGathersOplogsInOrderUpToMax() {
Oplog oplogNeedingCompaction1 = oplog(true);
Oplog oplogNeedingCompaction2 = oplog(true);
Oplog oplogNeedingCompaction3 = oplog(true);
Map<Long, Oplog> oplogMap = persistentOplogSet.getOplogIdToOplog();
oplogMap.put(1L, oplogNeedingCompaction1);
oplogMap.put(2L, oplogNeedingCompaction2);
oplogMap.put(3L, oplogNeedingCompaction3);
List<CompactableOplog> compactableOplogs = new ArrayList<>();
persistentOplogSet.getCompactableOplogs(compactableOplogs, 2);
assertThat(compactableOplogs)
.containsExactly(oplogNeedingCompaction1, oplogNeedingCompaction2) // in order
.doesNotContain(oplogNeedingCompaction3);
}
@Test
public void getCompactableOplogsGathersAdditionalOplogsUpToMaxSize() {
Oplog oplogNeedingCompaction1 = oplog(true);
Oplog oplogNeedingCompaction2 = oplog(true);
Map<Long, Oplog> oplogMap = persistentOplogSet.getOplogIdToOplog();
oplogMap.put(1L, oplogNeedingCompaction1);
oplogMap.put(2L, oplogNeedingCompaction2);
List<CompactableOplog> compactableOplogs = new ArrayList<>();
Oplog existingOplogAlreadyInList = oplog(true);
compactableOplogs.add(existingOplogAlreadyInList);
persistentOplogSet.getCompactableOplogs(compactableOplogs, 2);
assertThat(compactableOplogs)
.containsExactly(existingOplogAlreadyInList, oplogNeedingCompaction1) // in order
.doesNotContain(oplogNeedingCompaction2);
}
@Test
public void getCompactableOplogsDoesNotAddToListOfMaxSize() {
Oplog oplogNeedingCompaction1 = oplog(true);
Map<Long, Oplog> oplogMap = persistentOplogSet.getOplogIdToOplog();
oplogMap.put(1L, oplogNeedingCompaction1);
List<CompactableOplog> compactableOplogs = new ArrayList<>();
Oplog existingOplogAlreadyInList1 = oplog(true);
Oplog existingOplogAlreadyInList2 = oplog(true);
compactableOplogs.add(existingOplogAlreadyInList1);
compactableOplogs.add(existingOplogAlreadyInList2);
persistentOplogSet.getCompactableOplogs(compactableOplogs, 2);
assertThat(compactableOplogs)
.containsExactly(existingOplogAlreadyInList1, existingOplogAlreadyInList2) // in order
.doesNotContain(oplogNeedingCompaction1);
}
@Test
public void recoverRegionsThatAreReadyPrintsBucketEntries() {
PrintStream outputStream = mock(PrintStream.class);
persistentOplogSet = new PersistentOplogSet(diskStore, outputStream);
when(diskStore.getDiskInitFile()).thenReturn(mock(DiskInitFile.class));
when(diskStore.isValidating()).thenReturn(true);
when(diskStore.getStats()).thenReturn(mock(DiskStoreStats.class));
String prName = "prName";
int entryCount = 9;
Map<Long, DiskRecoveryStore> currentRecoveryMap = persistentOplogSet.getPendingRecoveryMap();
ValidatingDiskRegion validatingDiskRegion = validatingDiskRegionForBucket(prName, entryCount);
currentRecoveryMap.put(0L, validatingDiskRegion);
persistentOplogSet.recoverRegionsThatAreReady();
ArgumentCaptor<String> printedString = ArgumentCaptor.forClass(String.class);
verify(outputStream).println(printedString.capture());
assertThat(printedString.getValue())
.startsWith(prName)
.contains("entryCount=" + 9)
.contains("bucketCount=" + 1);
}
@Test
public void recoverRegionsThatAreReadyPrintsRegionSize() {
PrintStream outputStream = mock(PrintStream.class);
persistentOplogSet = new PersistentOplogSet(diskStore, outputStream);
when(diskStore.getDiskInitFile()).thenReturn(mock(DiskInitFile.class));
when(diskStore.isValidating()).thenReturn(true);
when(diskStore.getStats()).thenReturn(mock(DiskStoreStats.class));
String regionName = "regionName";
int entryCount = 13;
Map<Long, DiskRecoveryStore> currentRecoveryMap = persistentOplogSet.getPendingRecoveryMap();
ValidatingDiskRegion validatingDiskRegion = validatingDiskRegion(regionName, entryCount);
currentRecoveryMap.put(0L, validatingDiskRegion);
persistentOplogSet.recoverRegionsThatAreReady();
ArgumentCaptor<String> printedString = ArgumentCaptor.forClass(String.class);
verify(outputStream).println(printedString.capture());
assertThat(printedString.getValue())
.startsWith(regionName)
.contains("entryCount=" + entryCount);
}
private ValidatingDiskRegion validatingDiskRegionForBucket(String prName, int entryCount) {
ValidatingDiskRegion validatingDiskRegion = mock(ValidatingDiskRegion.class);
when(validatingDiskRegion.isBucket()).thenReturn(true);
when(validatingDiskRegion.getDiskRegionView()).thenReturn(mock(DiskRegionView.class));
when(validatingDiskRegion.getPrName()).thenReturn(prName);
when(validatingDiskRegion.size()).thenReturn(entryCount);
return validatingDiskRegion;
}
private ValidatingDiskRegion validatingDiskRegion(String regionName, int entryCount) {
ValidatingDiskRegion validatingDiskRegion = mock(ValidatingDiskRegion.class);
when(validatingDiskRegion.getName()).thenReturn(regionName);
when(validatingDiskRegion.isBucket()).thenReturn(false);
when(validatingDiskRegion.getDiskRegionView()).thenReturn(mock(DiskRegionView.class));
when(validatingDiskRegion.size()).thenReturn(entryCount);
return validatingDiskRegion;
}
private Oplog oplog(boolean needsCompaction) {
Oplog oplog = mock(Oplog.class);
when(oplog.needsCompaction()).thenReturn(needsCompaction);
return oplog;
}
}