This is an automated email from the ASF dual-hosted git repository.
reddycharan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git
The following commit(s) were added to refs/heads/master by this push:
new 9540d84 Replicascheck comprehensive testcases.
9540d84 is described below
commit 9540d8473ebbe49425ece1088047cd544e8427f9
Author: Charan Reddy Guttapalem <[email protected]>
AuthorDate: Tue Aug 13 10:53:39 2019 -0700
Replicascheck comprehensive testcases.
Descriptions of the changes in this PR:
- adding comprehensive testcases for newly added
scrutiny - replicasCheck.
Reviewers: Enrico Olivelli <[email protected]>, Sijie Guo <None>
This closes #2141 from reddycharan/replicaschecktest
---
.../org/apache/bookkeeper/replication/Auditor.java | 35 +-
.../util/AvailabilityOfEntriesOfLedger.java | 7 +
.../replication/AuditorPeriodicCheckTest.java | 6 +
.../AuditorPlacementPolicyCheckTest.java | 1 +
.../replication/AuditorReplicasCheckTest.java | 810 +++++++++++++++++++++
5 files changed, 852 insertions(+), 7 deletions(-)
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/Auditor.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/Auditor.java
index 3b8219f..7e815de 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/Auditor.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/Auditor.java
@@ -136,7 +136,8 @@ public class Auditor implements AutoCloseable {
private final ServerConfiguration conf;
private final BookKeeper bkc;
private final boolean ownBkc;
- private BookKeeperAdmin admin;
+ private final BookKeeperAdmin admin;
+ private final boolean ownAdmin;
private BookieLedgerIndexer bookieLedgerIndexer;
private LedgerManager ledgerManager;
private LedgerUnderreplicationManager ledgerUnderreplicationManager;
@@ -297,10 +298,27 @@ public class Auditor implements AutoCloseable {
}
public Auditor(final String bookieIdentifier,
- ServerConfiguration conf,
- BookKeeper bkc,
- boolean ownBkc,
- StatsLogger statsLogger)
+ ServerConfiguration conf,
+ BookKeeper bkc,
+ boolean ownBkc,
+ StatsLogger statsLogger)
+ throws UnavailableException {
+ this(bookieIdentifier,
+ conf,
+ bkc,
+ ownBkc,
+ new BookKeeperAdmin(bkc, statsLogger),
+ true,
+ statsLogger);
+ }
+
+ public Auditor(final String bookieIdentifier,
+ ServerConfiguration conf,
+ BookKeeper bkc,
+ boolean ownBkc,
+ BookKeeperAdmin admin,
+ boolean ownAdmin,
+ StatsLogger statsLogger)
throws UnavailableException {
this.conf = conf;
this.underreplicatedLedgerRecoveryGracePeriod =
conf.getUnderreplicatedLedgerRecoveryGracePeriod();
@@ -419,6 +437,8 @@ public class Auditor implements AutoCloseable {
this.bkc = bkc;
this.ownBkc = ownBkc;
+ this.admin = admin;
+ this.ownAdmin = ownAdmin;
initialize(conf, bkc);
executor = Executors.newSingleThreadScheduledExecutor(new
ThreadFactory() {
@@ -443,7 +463,6 @@ public class Auditor implements AutoCloseable {
this.ledgerUnderreplicationManager = ledgerManagerFactory
.newLedgerUnderreplicationManager();
- this.admin = new BookKeeperAdmin(bkc, statsLogger);
LOG.info("AuthProvider used by the Auditor is {}",
admin.getConf().getClientAuthProviderFactoryClass());
if (this.ledgerUnderreplicationManager
@@ -1910,7 +1929,9 @@ public class Auditor implements AutoCloseable {
LOG.warn("Executor not shutting down, interrupting");
executor.shutdownNow();
}
- admin.close();
+ if (ownAdmin) {
+ admin.close();
+ }
if (ownBkc) {
bkc.close();
}
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/AvailabilityOfEntriesOfLedger.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/AvailabilityOfEntriesOfLedger.java
index b4987c8..4695d8c 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/AvailabilityOfEntriesOfLedger.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/AvailabilityOfEntriesOfLedger.java
@@ -184,6 +184,13 @@ public class AvailabilityOfEntriesOfLedger {
this.closeStateOfEntriesOfALedger();
}
+ public AvailabilityOfEntriesOfLedger(long[] entriesOfLedger) {
+ for (long entry : entriesOfLedger) {
+ this.addEntryToAvailabileEntriesOfLedger(entry);
+ }
+ this.closeStateOfEntriesOfALedger();
+ }
+
public AvailabilityOfEntriesOfLedger(byte[]
serializeStateOfEntriesOfLedger) {
byte[] header = new byte[HEADER_SIZE];
byte[] serializedSequenceGroupByteArray = new
byte[SequenceGroup.SEQUENCEGROUP_BYTES];
diff --git
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java
index 3999c3c..448913e 100644
---
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java
+++
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java
@@ -54,6 +54,7 @@ import org.apache.bookkeeper.client.AsyncCallback.AddCallback;
import org.apache.bookkeeper.client.BKException;
import org.apache.bookkeeper.client.BookKeeper;
import org.apache.bookkeeper.client.BookKeeper.DigestType;
+import org.apache.bookkeeper.client.BookKeeperAdmin;
import org.apache.bookkeeper.client.LedgerHandle;
import org.apache.bookkeeper.conf.ServerConfiguration;
import org.apache.bookkeeper.meta.LedgerManagerFactory;
@@ -663,6 +664,11 @@ public class AuditorPeriodicCheckTest extends
BookKeeperClusterTestCase {
super(bookieIdentifier, conf, bkc, ownBkc, statsLogger);
}
+ public TestAuditor(String bookieIdentifier, ServerConfiguration conf,
BookKeeper bkc, boolean ownBkc,
+ BookKeeperAdmin bkadmin, boolean ownadmin, StatsLogger
statsLogger) throws UnavailableException {
+ super(bookieIdentifier, conf, bkc, ownBkc, bkadmin, ownadmin,
statsLogger);
+ }
+
public TestAuditor(final String bookieIdentifier, ServerConfiguration
conf, StatsLogger statsLogger)
throws UnavailableException {
super(bookieIdentifier, conf, statsLogger);
diff --git
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java
index b8548e0..468a032 100644
---
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java
+++
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java
@@ -656,6 +656,7 @@ public class AuditorPlacementPolicyCheckTest extends
BookKeeperClusterTestCase {
servConf.setProperty(ClientConfiguration.ENSEMBLE_PLACEMENT_POLICY,
ensemblePlacementPolicyClass);
servConf.setAuditorPeriodicCheckInterval(0);
servConf.setAuditorPeriodicBookieCheckInterval(0);
+ servConf.setAuditorPeriodicReplicasCheckInterval(0);
servConf.setAuditorPeriodicPlacementPolicyCheckInterval(1000);
}
diff --git
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorReplicasCheckTest.java
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorReplicasCheckTest.java
new file mode 100644
index 0000000..a2d5f6b
--- /dev/null
+++
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorReplicasCheckTest.java
@@ -0,0 +1,810 @@
+/**
+ *
+ * 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.bookkeeper.replication;
+
+import static org.apache.bookkeeper.replication.ReplicationStats.AUDITOR_SCOPE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.bookkeeper.bookie.Bookie;
+import org.apache.bookkeeper.bookie.BookieException;
+import org.apache.bookkeeper.client.BKException;
+import org.apache.bookkeeper.client.BookKeeper;
+import org.apache.bookkeeper.client.BookKeeperAdmin;
+import org.apache.bookkeeper.client.LedgerMetadataBuilder;
+import org.apache.bookkeeper.client.api.DigestType;
+import org.apache.bookkeeper.client.api.LedgerMetadata;
+import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.bookkeeper.discover.RegistrationManager;
+import org.apache.bookkeeper.meta.LedgerManager;
+import org.apache.bookkeeper.meta.LedgerManagerFactory;
+import org.apache.bookkeeper.meta.LedgerUnderreplicationManager;
+import org.apache.bookkeeper.meta.MetadataBookieDriver;
+import org.apache.bookkeeper.meta.MetadataDrivers;
+import org.apache.bookkeeper.meta.exceptions.MetadataException;
+import org.apache.bookkeeper.net.BookieSocketAddress;
+import org.apache.bookkeeper.replication.AuditorPeriodicCheckTest.TestAuditor;
+import
org.apache.bookkeeper.replication.ReplicationException.CompatibilityException;
+import
org.apache.bookkeeper.replication.ReplicationException.UnavailableException;
+import org.apache.bookkeeper.stats.Gauge;
+import org.apache.bookkeeper.stats.NullStatsLogger;
+import org.apache.bookkeeper.stats.StatsLogger;
+import org.apache.bookkeeper.test.BookKeeperClusterTestCase;
+import org.apache.bookkeeper.test.TestStatsProvider;
+import org.apache.bookkeeper.test.TestStatsProvider.TestOpStatsLogger;
+import org.apache.bookkeeper.test.TestStatsProvider.TestStatsLogger;
+import org.apache.bookkeeper.util.AvailabilityOfEntriesOfLedger;
+import org.apache.bookkeeper.util.StaticDNSResolver;
+import org.apache.commons.collections4.map.MultiKeyMap;
+import org.apache.commons.lang3.mutable.MutableObject;
+import org.apache.zookeeper.KeeperException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests the logic of Auditor's ReplicasCheck.
+ */
+public class AuditorReplicasCheckTest extends BookKeeperClusterTestCase {
+ private MetadataBookieDriver driver;
+
+ public AuditorReplicasCheckTest() {
+ super(1);
+ baseConf.setPageLimit(1); // to make it easy to push ledger out of
cache
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ StaticDNSResolver.reset();
+ driver =
MetadataDrivers.getBookieDriver(URI.create(bsConfs.get(0).getMetadataServiceUri()));
+ driver.initialize(bsConfs.get(0), () -> {
+ }, NullStatsLogger.INSTANCE);
+ }
+
+ @After
+ @Override
+ public void tearDown() throws Exception {
+ if (null != driver) {
+ driver.close();
+ }
+ super.tearDown();
+ }
+
+ private class TestBookKeeperAdmin extends BookKeeperAdmin {
+
+ private final MultiKeyMap<String, AvailabilityOfEntriesOfLedger>
returnAvailabilityOfEntriesOfLedger;
+ private final MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger;
+
+ public TestBookKeeperAdmin(BookKeeper bkc, StatsLogger statsLogger,
+ MultiKeyMap<String, AvailabilityOfEntriesOfLedger>
returnAvailabilityOfEntriesOfLedger,
+ MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger) {
+ super(bkc, statsLogger);
+ this.returnAvailabilityOfEntriesOfLedger =
returnAvailabilityOfEntriesOfLedger;
+ this.errorReturnValueForGetAvailabilityOfEntriesOfLedger =
+ errorReturnValueForGetAvailabilityOfEntriesOfLedger;
+ }
+
+ @Override
+ public CompletableFuture<AvailabilityOfEntriesOfLedger>
asyncGetListOfEntriesOfLedger(
+ BookieSocketAddress address, long ledgerId) {
+ CompletableFuture<AvailabilityOfEntriesOfLedger> futureResult =
+ new CompletableFuture<AvailabilityOfEntriesOfLedger>();
+ Integer errorReturnValue =
errorReturnValueForGetAvailabilityOfEntriesOfLedger.get(address.toString(),
+ Long.toString(ledgerId));
+ if (errorReturnValue != null) {
+
futureResult.completeExceptionally(BKException.create(errorReturnValue).fillInStackTrace());
+ } else {
+ AvailabilityOfEntriesOfLedger availabilityOfEntriesOfLedger =
returnAvailabilityOfEntriesOfLedger
+ .get(address.toString(), Long.toString(ledgerId));
+ futureResult.complete(availabilityOfEntriesOfLedger);
+ }
+ return futureResult;
+ }
+ }
+
+ private TestStatsLogger
startAuditorAndWaitForReplicasCheck(ServerConfiguration servConf,
+ MutableObject<Auditor> auditorRef,
+ MultiKeyMap<String, AvailabilityOfEntriesOfLedger>
expectedReturnAvailabilityOfEntriesOfLedger,
+ MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger)
+ throws MetadataException, CompatibilityException, KeeperException,
InterruptedException,
+ UnavailableException, UnknownHostException {
+ LedgerManagerFactory mFactory = driver.getLedgerManagerFactory();
+ LedgerUnderreplicationManager urm =
mFactory.newLedgerUnderreplicationManager();
+ TestStatsProvider statsProvider = new TestStatsProvider();
+ TestStatsLogger statsLogger =
statsProvider.getStatsLogger(AUDITOR_SCOPE);
+ TestOpStatsLogger replicasCheckStatsLogger = (TestOpStatsLogger)
statsLogger
+ .getOpStatsLogger(ReplicationStats.REPLICAS_CHECK_TIME);
+
+ final TestAuditor auditor = new
TestAuditor(Bookie.getBookieAddress(servConf).toString(), servConf, bkc, true,
+ new TestBookKeeperAdmin(bkc, statsLogger,
expectedReturnAvailabilityOfEntriesOfLedger,
+ errorReturnValueForGetAvailabilityOfEntriesOfLedger),
+ true, statsLogger);
+ auditorRef.setValue(auditor);
+ CountDownLatch latch = auditor.getLatch();
+ assertEquals("REPLICAS_CHECK_TIME SuccessCount", 0,
replicasCheckStatsLogger.getSuccessCount());
+ urm.setReplicasCheckCTime(-1);
+ auditor.start();
+ /*
+ * since replicasCheckCTime is set to -1, replicasCheck should be
+ * scheduled to run with no initialdelay
+ */
+ assertTrue("replicasCheck should have executed", latch.await(20,
TimeUnit.SECONDS));
+ for (int i = 0; i < 200; i++) {
+ Thread.sleep(100);
+ if (replicasCheckStatsLogger.getSuccessCount() >= 1) {
+ break;
+ }
+ }
+ assertEquals("REPLICAS_CHECK_TIME SuccessCount", 1,
replicasCheckStatsLogger.getSuccessCount());
+ return statsLogger;
+ }
+
+ private void setServerConfigProperties(ServerConfiguration servConf) {
+ servConf.setAuditorPeriodicCheckInterval(0);
+ servConf.setAuditorPeriodicBookieCheckInterval(0);
+ servConf.setAuditorPeriodicPlacementPolicyCheckInterval(0);
+ servConf.setAuditorPeriodicReplicasCheckInterval(1000);
+ }
+
+ List<BookieSocketAddress> addAndRegisterBookies(RegistrationManager
regManager, int numOfBookies)
+ throws BookieException {
+ BookieSocketAddress bookieAddress;
+ List<BookieSocketAddress> bookieAddresses = new
ArrayList<BookieSocketAddress>();
+ for (int i = 0; i < numOfBookies; i++) {
+ bookieAddress = new BookieSocketAddress("98.98.98." + i, 2181);
+ bookieAddresses.add(bookieAddress);
+ regManager.registerBookie(bookieAddress.toString(), false);
+ }
+ return bookieAddresses;
+ }
+
+ private void createClosedLedgerMetadata(LedgerManager lm, long ledgerId,
int ensembleSize, int writeQuorumSize,
+ int ackQuorumSize, Map<Long, List<BookieSocketAddress>>
segmentEnsembles, long lastEntryId, int length,
+ DigestType digestType, byte[] password) throws
InterruptedException, ExecutionException {
+ LedgerMetadataBuilder ledgerMetadataBuilder =
LedgerMetadataBuilder.create();
+
ledgerMetadataBuilder.withEnsembleSize(ensembleSize).withWriteQuorumSize(writeQuorumSize)
+
.withAckQuorumSize(ackQuorumSize).withClosedState().withLastEntryId(lastEntryId).withLength(length)
+ .withDigestType(digestType).withPassword(password);
+ for (Map.Entry<Long, List<BookieSocketAddress>> mapEntry :
segmentEnsembles.entrySet()) {
+ ledgerMetadataBuilder.newEnsembleEntry(mapEntry.getKey(),
mapEntry.getValue());
+ }
+ LedgerMetadata initMeta = ledgerMetadataBuilder.build();
+ lm.createLedgerMetadata(ledgerId, initMeta).get();
+ }
+
+ private void createNonClosedLedgerMetadata(LedgerManager lm, long
ledgerId, int ensembleSize, int writeQuorumSize,
+ int ackQuorumSize, Map<Long, List<BookieSocketAddress>>
segmentEnsembles, DigestType digestType,
+ byte[] password) throws InterruptedException, ExecutionException {
+ LedgerMetadataBuilder ledgerMetadataBuilder =
LedgerMetadataBuilder.create();
+
ledgerMetadataBuilder.withEnsembleSize(ensembleSize).withWriteQuorumSize(writeQuorumSize)
+
.withAckQuorumSize(ackQuorumSize).withDigestType(digestType).withPassword(password);
+ for (Map.Entry<Long, List<BookieSocketAddress>> mapEntry :
segmentEnsembles.entrySet()) {
+ ledgerMetadataBuilder.newEnsembleEntry(mapEntry.getKey(),
mapEntry.getValue());
+ }
+ LedgerMetadata initMeta = ledgerMetadataBuilder.build();
+ lm.createLedgerMetadata(ledgerId, initMeta).get();
+ }
+
+ private void runTestScenario(MultiKeyMap<String,
AvailabilityOfEntriesOfLedger> returnAvailabilityOfEntriesOfLedger,
+ MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger,
+ int expectedNumLedgersFoundHavingNoReplicaOfAnEntry,
+ int expectedNumLedgersHavingLessThanAQReplicasOfAnEntry,
+ int expectedNumLedgersHavingLessThanWQReplicasOfAnEntry) throws
CompatibilityException,
+ UnavailableException, UnknownHostException, MetadataException,
KeeperException, InterruptedException {
+ ServerConfiguration servConf = new ServerConfiguration(bsConfs.get(0));
+ setServerConfigProperties(servConf);
+ MutableObject<Auditor> auditorRef = new MutableObject<Auditor>();
+ try {
+ TestStatsLogger statsLogger =
startAuditorAndWaitForReplicasCheck(servConf, auditorRef,
+ returnAvailabilityOfEntriesOfLedger,
errorReturnValueForGetAvailabilityOfEntriesOfLedger);
+ checkReplicasCheckStats(statsLogger,
expectedNumLedgersFoundHavingNoReplicaOfAnEntry,
+ expectedNumLedgersHavingLessThanAQReplicasOfAnEntry,
+ expectedNumLedgersHavingLessThanWQReplicasOfAnEntry);
+ } finally {
+ Auditor auditor = auditorRef.getValue();
+ if (auditor != null) {
+ auditor.close();
+ }
+ }
+ }
+
+ private void checkReplicasCheckStats(TestStatsLogger statsLogger,
+ int expectedNumLedgersFoundHavingNoReplicaOfAnEntry,
+ int expectedNumLedgersHavingLessThanAQReplicasOfAnEntry,
+ int expectedNumLedgersHavingLessThanWQReplicasOfAnEntry) {
+ Gauge<? extends Number> numLedgersFoundHavingNoReplicaOfAnEntryGuage =
statsLogger
+
.getGauge(ReplicationStats.NUM_LEDGERS_HAVING_NO_REPLICA_OF_AN_ENTRY);
+ Gauge<? extends Number>
numLedgersHavingLessThanAQReplicasOfAnEntryGuage = statsLogger
+
.getGauge(ReplicationStats.NUM_LEDGERS_HAVING_LESS_THAN_AQ_REPLICAS_OF_AN_ENTRY);
+ Gauge<? extends Number>
numLedgersHavingLessThanWQReplicasOfAnEntryGuage = statsLogger
+
.getGauge(ReplicationStats.NUM_LEDGERS_HAVING_LESS_THAN_WQ_REPLICAS_OF_AN_ENTRY);
+
+ assertEquals("NUM_LEDGERS_HAVING_NO_REPLICA_OF_AN_ENTRY guage value",
+ expectedNumLedgersFoundHavingNoReplicaOfAnEntry,
+ numLedgersFoundHavingNoReplicaOfAnEntryGuage.getSample());
+ assertEquals("NUM_LEDGERS_HAVING_LESS_THAN_AQ_REPLICAS_OF_AN_ENTRY
guage value",
+ expectedNumLedgersHavingLessThanAQReplicasOfAnEntry,
+ numLedgersHavingLessThanAQReplicasOfAnEntryGuage.getSample());
+ assertEquals("NUM_LEDGERS_HAVING_LESS_THAN_WQ_REPLICAS_OF_AN_ENTRY
guage value",
+ expectedNumLedgersHavingLessThanWQReplicasOfAnEntry,
+ numLedgersHavingLessThanWQReplicasOfAnEntryGuage.getSample());
+ }
+
+ /*
+ * For all the ledgers and for all the bookies,
+ * asyncGetListOfEntriesOfLedger would return
+ * BookieHandleNotAvailableException, so these ledgers wouldn't be counted
+ * against expectedNumLedgersFoundHavingNoReplicaOfAnEntry /
+ * LessThanAQReplicasOfAnEntry / LessThanWQReplicasOfAnEntry.
+ */
+ @Test
+ public void testReplicasCheckForBookieHandleNotAvailable() throws
Exception {
+ int numOfBookies = 5;
+ RegistrationManager regManager = driver.getRegistrationManager();
+ MultiKeyMap<String, AvailabilityOfEntriesOfLedger>
returnAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, AvailabilityOfEntriesOfLedger>();
+ MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, Integer>();
+ List<BookieSocketAddress> bookieAddresses =
addAndRegisterBookies(regManager, numOfBookies);
+
+ LedgerManagerFactory mFactory = driver.getLedgerManagerFactory();
+ LedgerManager lm = mFactory.newLedgerManager();
+ int ensembleSize = 5;
+ int writeQuorumSize = 4;
+ int ackQuorumSize = 2;
+ long lastEntryId = 100;
+ int length = 10000;
+ DigestType digestType = DigestType.DUMMY;
+ byte[] password = new byte[0];
+ Collections.shuffle(bookieAddresses);
+
+ /*
+ * closed ledger
+ *
+ * for this ledger, for all the bookies we are setting
+ * errorReturnValueForGetAvailabilityOfEntriesOfLedger to
+ * BookieHandleNotAvailableException so asyncGetListOfEntriesOfLedger
will
+ * return BookieHandleNotAvailableException.
+ */
+ Map<Long, List<BookieSocketAddress>> segmentEnsembles = new
HashMap<Long, List<BookieSocketAddress>>();
+ segmentEnsembles.put(0L, bookieAddresses);
+ long ledgerId = 1L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
+ Long.toString(ledgerId),
BKException.Code.BookieHandleNotAvailableException);
+ }
+
+ ensembleSize = 4;
+ /*
+ * closed ledger with multiple segments
+ *
+ * for this ledger, for all the bookies we are setting
+ * errorReturnValueForGetAvailabilityOfEntriesOfLedger to
+ * BookieHandleNotAvailableException so asyncGetListOfEntriesOfLedger
will
+ * return BookieHandleNotAvailableException.
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(20L, bookieAddresses.subList(1, 5));
+ segmentEnsembles.put(60L, bookieAddresses.subList(0, 4));
+ ledgerId = 2L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
+ Long.toString(ledgerId),
BKException.Code.BookieHandleNotAvailableException);
+ }
+
+ /*
+ * non-closed ledger
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ ledgerId = 3L;
+ createNonClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
+ Long.toString(ledgerId),
BKException.Code.BookieHandleNotAvailableException);
+ }
+
+ /*
+ * non-closed ledger with multiple segments
+ *
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(20L, bookieAddresses.subList(1, 5));
+ segmentEnsembles.put(60L, bookieAddresses.subList(0, 4));
+ ledgerId = 4L;
+ createNonClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
+ Long.toString(ledgerId),
BKException.Code.BookieHandleNotAvailableException);
+ }
+
+ runTestScenario(returnAvailabilityOfEntriesOfLedger,
errorReturnValueForGetAvailabilityOfEntriesOfLedger, 0, 0,
+ 0);
+ }
+
+ /*
+ * In this testscenario all the ledgers have a missing entry. So all closed
+ * ledgers should be counted towards
+ * numLedgersFoundHavingNoReplicaOfAnEntry.
+ */
+ @Test
+ public void testReplicasCheckForLedgersFoundHavingNoReplica() throws
Exception {
+ int numOfBookies = 5;
+ RegistrationManager regManager = driver.getRegistrationManager();
+ MultiKeyMap<String, AvailabilityOfEntriesOfLedger>
returnAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, AvailabilityOfEntriesOfLedger>();
+ MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, Integer>();
+ List<BookieSocketAddress> bookieAddresses =
addAndRegisterBookies(regManager, numOfBookies);
+
+ LedgerManagerFactory mFactory = driver.getLedgerManagerFactory();
+ LedgerManager lm = mFactory.newLedgerManager();
+ int ensembleSize = 5;
+ int writeQuorumSize = 4;
+ int ackQuorumSize = 2;
+ long lastEntryId = 100;
+ int length = 10000;
+ DigestType digestType = DigestType.DUMMY;
+ byte[] password = new byte[0];
+ Collections.shuffle(bookieAddresses);
+
+ int numLedgersFoundHavingNoReplicaOfAnEntry = 0;
+
+ /*
+ * closed ledger
+ *
+ * for this ledger we are setting returnAvailabilityOfEntriesOfLedger
to
+ * Empty one for all of the bookies, so this ledger would be counted in
+ * ledgersFoundHavingNoReplicaOfAnEntry .
+ */
+ Map<Long, List<BookieSocketAddress>> segmentEnsembles = new
HashMap<Long, List<BookieSocketAddress>>();
+ segmentEnsembles.put(0L, bookieAddresses);
+ long ledgerId = 1L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
returnAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
Long.toString(ledgerId),
+
AvailabilityOfEntriesOfLedger.EMPTY_AVAILABILITYOFENTRIESOFLEDGER);
+ }
+ numLedgersFoundHavingNoReplicaOfAnEntry++;
+
+ ensembleSize = 4;
+ /*
+ * closed ledger with multiple segments
+ *
+ * for this ledger we are setting
+ * errorReturnValueForGetAvailabilityOfEntriesOfLedger to
+ * NoSuchLedgerExistsException. This is equivalent to
+ * EMPTY_AVAILABILITYOFENTRIESOFLEDGER. So this ledger would be counted
+ * in ledgersFoundHavingNoReplicaOfAnEntry
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(20L, bookieAddresses.subList(1, 5));
+ segmentEnsembles.put(60L, bookieAddresses.subList(0, 4));
+ ledgerId = 2L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
+ Long.toString(ledgerId),
BKException.Code.NoSuchLedgerExistsException);
+ }
+ numLedgersFoundHavingNoReplicaOfAnEntry++;
+
+ /*
+ * non-closed ledger
+ *
+ * since this is non-closed ledger, it should not be counted in
+ * ledgersFoundHavingNoReplicaOfAnEntry
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ ledgerId = 3L;
+ createNonClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
returnAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
Long.toString(ledgerId),
+
AvailabilityOfEntriesOfLedger.EMPTY_AVAILABILITYOFENTRIESOFLEDGER);
+ }
+
+ ensembleSize = 3;
+ writeQuorumSize = 3;
+ ackQuorumSize = 2;
+ lastEntryId = 1;
+ length = 1000;
+ /*
+ * closed ledger
+ *
+ * for this ledger we are setting returnAvailabilityOfEntriesOfLedger
to
+ * just {0l} for all of the bookies and entry 1l is missing for all of
+ * the bookies, so this ledger would be counted in
+ * ledgersFoundHavingNoReplicaOfAnEntry
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 3));
+ ledgerId = 4L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+ for (BookieSocketAddress bookieSocketAddress : bookieAddresses) {
+
returnAvailabilityOfEntriesOfLedger.put(bookieSocketAddress.toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0L }));
+ }
+ numLedgersFoundHavingNoReplicaOfAnEntry++;
+
+ /*
+ * For this closed ledger, entry 1 is missing. So it should be counted
+ * towards numLedgersFoundHavingNoReplicaOfAnEntry.
+ */
+ ensembleSize = 4;
+ writeQuorumSize = 3;
+ ackQuorumSize = 2;
+ lastEntryId = 3;
+ length = 10000;
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ ledgerId = 5L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 2, 3 }));
+ numLedgersFoundHavingNoReplicaOfAnEntry++;
+
+ runTestScenario(returnAvailabilityOfEntriesOfLedger,
errorReturnValueForGetAvailabilityOfEntriesOfLedger,
+ numLedgersFoundHavingNoReplicaOfAnEntry, 0, 0);
+ }
+
+ /*
+ * In this testscenario all the ledgers have an entry with less than AQ
+ * number of copies. So all closed ledgers should be counted towards
+ * numLedgersFoundHavingLessThanAQReplicasOfAnEntry.
+ */
+ @Test
+ public void
testReplicasCheckForLedgersFoundHavingLessThanAQReplicasOfAnEntry() throws
Exception {
+ int numOfBookies = 5;
+ RegistrationManager regManager = driver.getRegistrationManager();
+ MultiKeyMap<String, AvailabilityOfEntriesOfLedger>
returnAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, AvailabilityOfEntriesOfLedger>();
+ MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, Integer>();
+ List<BookieSocketAddress> bookieAddresses =
addAndRegisterBookies(regManager, numOfBookies);
+
+ LedgerManagerFactory mFactory = driver.getLedgerManagerFactory();
+ LedgerManager lm = mFactory.newLedgerManager();
+ DigestType digestType = DigestType.DUMMY;
+ byte[] password = new byte[0];
+ Collections.shuffle(bookieAddresses);
+
+ int numLedgersFoundHavingLessThanAQReplicasOfAnEntry = 0;
+
+ /*
+ * closed ledger
+ *
+ * for this ledger there is only one copy of entry 2, so this ledger
+ * would be counted towards
+ * ledgersFoundHavingLessThanAQReplicasOfAnEntry.
+ */
+ Map<Long, List<BookieSocketAddress>> segmentEnsembles = new
HashMap<Long, List<BookieSocketAddress>>();
+ int ensembleSize = 4;
+ int writeQuorumSize = 3;
+ int ackQuorumSize = 2;
+ long lastEntryId = 3;
+ int length = 10000;
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ long ledgerId = 1L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1, 2, 3 }));
+ numLedgersFoundHavingLessThanAQReplicasOfAnEntry++;
+
+ /*
+ * closed ledger with multiple segments.
+ *
+ * for this ledger there is only one copy of entry 2, so this ledger
+ * would be counted towards
+ * ledgersFoundHavingLessThanAQReplicasOfAnEntry.
+ *
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(2L, bookieAddresses.subList(1, 5));
+ ledgerId = 2L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] {}));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 2, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(4).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 3 }));
+ numLedgersFoundHavingLessThanAQReplicasOfAnEntry++;
+
+ /*
+ * closed ledger with multiple segments
+ *
+ * for this ledger entry 2 is overrreplicated, but it has only one copy
+ * in the set of bookies it is supposed to be. So it should be counted
+ * towards ledgersFoundHavingLessThanAQReplicasOfAnEntry.
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(2L, bookieAddresses.subList(1, 5));
+ ledgerId = 3L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 2 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 2, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(4).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 3 }));
+ numLedgersFoundHavingLessThanAQReplicasOfAnEntry++;
+
+ /*
+ * non-closed ledger
+ *
+ * since this is non-closed ledger, it should not be counted towards
+ * ledgersFoundHavingLessThanAQReplicasOfAnEntry
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(2L, bookieAddresses.subList(1, 5));
+ ledgerId = 4L;
+ createNonClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] {}));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 2, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(4).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 3 }));
+
+ /*
+ * this is closed ledger.
+ *
+ * For third bookie, asyncGetListOfEntriesOfLedger will fail with
+ * BookieHandleNotAvailableException, so this should not be counted
+ * against missing copies of an entry. Other than that, for both
entries
+ * 0 and 1, two copies are missing. Hence this should be counted
towards
+ * numLedgersFoundHavingLessThanAQReplicasOfAnEntry.
+ */
+ ensembleSize = 3;
+ writeQuorumSize = 3;
+ ackQuorumSize = 2;
+ lastEntryId = 1;
+ length = 1000;
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 3));
+ ledgerId = 5L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+
AvailabilityOfEntriesOfLedger.EMPTY_AVAILABILITYOFENTRIESOFLEDGER);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+
AvailabilityOfEntriesOfLedger.EMPTY_AVAILABILITYOFENTRIESOFLEDGER);
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
+ Long.toString(ledgerId),
BKException.Code.BookieHandleNotAvailableException);
+ numLedgersFoundHavingLessThanAQReplicasOfAnEntry++;
+
+ runTestScenario(returnAvailabilityOfEntriesOfLedger,
errorReturnValueForGetAvailabilityOfEntriesOfLedger, 0,
+ numLedgersFoundHavingLessThanAQReplicasOfAnEntry, 0);
+ }
+
+ /*
+ * In this testscenario all the ledgers have an entry with less than WQ
+ * number of copies but greater than AQ. So all closed ledgers should be
+ * counted towards numLedgersFoundHavingLessThanWQReplicasOfAnEntry.
+ */
+ @Test
+ public void
testReplicasCheckForLedgersFoundHavingLessThanWQReplicasOfAnEntry() throws
Exception {
+ int numOfBookies = 5;
+ RegistrationManager regManager = driver.getRegistrationManager();
+ MultiKeyMap<String, AvailabilityOfEntriesOfLedger>
returnAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, AvailabilityOfEntriesOfLedger>();
+ MultiKeyMap<String, Integer>
errorReturnValueForGetAvailabilityOfEntriesOfLedger =
+ new MultiKeyMap<String, Integer>();
+ List<BookieSocketAddress> bookieAddresses =
addAndRegisterBookies(regManager, numOfBookies);
+
+ LedgerManagerFactory mFactory = driver.getLedgerManagerFactory();
+ LedgerManager lm = mFactory.newLedgerManager();
+ DigestType digestType = DigestType.DUMMY;
+ byte[] password = new byte[0];
+ Collections.shuffle(bookieAddresses);
+
+ int numLedgersFoundHavingLessThanWQReplicasOfAnEntry = 0;
+
+ /*
+ * closed ledger
+ *
+ * for this ledger a copy of entry 3, so this ledger would be counted
+ * towards ledgersFoundHavingLessThanWQReplicasOfAnEntry.
+ */
+ Map<Long, List<BookieSocketAddress>> segmentEnsembles = new
HashMap<Long, List<BookieSocketAddress>>();
+ int ensembleSize = 4;
+ int writeQuorumSize = 3;
+ int ackQuorumSize = 2;
+ long lastEntryId = 3;
+ int length = 10000;
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ long ledgerId = 1L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 2 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1, 2, 3 }));
+ numLedgersFoundHavingLessThanWQReplicasOfAnEntry++;
+
+ /*
+ * closed ledger with multiple segments
+ *
+ * for this ledger a copy of entry 0 and entry 2 are missing, so this
+ * ledger would be counted towards
+ * ledgersFoundHavingLessThanWQReplicasOfAnEntry.
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(2L, bookieAddresses.subList(1, 5));
+ ledgerId = 2L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] {}));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 2, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(4).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 2, 3 }));
+ numLedgersFoundHavingLessThanWQReplicasOfAnEntry++;
+
+ /*
+ * non-closed ledger with multiple segments
+ *
+ * since this is non-closed ledger, it should not be counted towards
+ * ledgersFoundHavingLessThanWQReplicasOfAnEntry
+ */
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ segmentEnsembles.put(2L, bookieAddresses.subList(1, 5));
+ ledgerId = 3L;
+ createNonClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ digestType, password);
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
+ Long.toString(ledgerId),
BKException.Code.NoSuchLedgerExistsException);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 2, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(4).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 2, 3 }));
+
+ /*
+ * closed ledger.
+ *
+ * for this ledger entry 0 is overrreplicated, but a copy is missing in
+ * the set of bookies it is supposed to be. So it should be counted
+ * towards ledgersFoundHavingLessThanWQReplicasOfAnEntry.
+ */
+ ensembleSize = 4;
+ writeQuorumSize = 3;
+ ackQuorumSize = 2;
+ lastEntryId = 1;
+ length = 1000;
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 4));
+ ledgerId = 4L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1, 2, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 1, 3 }));
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(3).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0 }));
+ numLedgersFoundHavingLessThanWQReplicasOfAnEntry++;
+
+ /*
+ * this is closed ledger.
+ *
+ * For third bookie, asyncGetListOfEntriesOfLedger will fail with
+ * BookieHandleNotAvailableException, so this should not be counted
+ * against missing copies of an entry. Other than that, for both
entries
+ * 0 and 1, a copy is missing. Hence this should be counted towards
+ * numLedgersFoundHavingLessThanWQReplicasOfAnEntry.
+ */
+ ensembleSize = 3;
+ writeQuorumSize = 3;
+ ackQuorumSize = 2;
+ lastEntryId = 1;
+ length = 1000;
+ segmentEnsembles.clear();
+ segmentEnsembles.put(0L, bookieAddresses.subList(0, 3));
+ ledgerId = 5L;
+ createClosedLedgerMetadata(lm, ledgerId, ensembleSize,
writeQuorumSize, ackQuorumSize, segmentEnsembles,
+ lastEntryId, length, digestType, password);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(0).toString(),
Long.toString(ledgerId),
+
AvailabilityOfEntriesOfLedger.EMPTY_AVAILABILITYOFENTRIESOFLEDGER);
+
returnAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(1).toString(),
Long.toString(ledgerId),
+ new AvailabilityOfEntriesOfLedger(new long[] { 0, 1 }));
+
errorReturnValueForGetAvailabilityOfEntriesOfLedger.put(bookieAddresses.get(2).toString(),
+ Long.toString(ledgerId),
BKException.Code.BookieHandleNotAvailableException);
+ numLedgersFoundHavingLessThanWQReplicasOfAnEntry++;
+
+ runTestScenario(returnAvailabilityOfEntriesOfLedger,
errorReturnValueForGetAvailabilityOfEntriesOfLedger, 0, 0,
+ numLedgersFoundHavingLessThanWQReplicasOfAnEntry);
+ }
+}