You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by iv...@apache.org on 2018/11/22 15:23:35 UTC

[bookkeeper] branch master updated: Remove LedgerMetadata constructors except one for builder

This is an automated email from the ASF dual-hosted git repository.

ivank 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 c6031e0  Remove LedgerMetadata constructors except one for builder
c6031e0 is described below

commit c6031e0bdc8002b9cae1e1a90d27a32d9e315d5b
Author: Ivan Kelly <iv...@apache.org>
AuthorDate: Thu Nov 22 15:23:30 2018 +0000

    Remove LedgerMetadata constructors except one for builder
    
    LedgerMetadata shouldn't generally be created outside the client,
    except for testing. In the case where it is, the builder should be
    used to construct it.
    
    I've left the copy constructor for now, as I don't feel comfortable
    removing it until all fields are final, which will occur soon.
    
    Master issue: #281
    
    
    Reviewers: Enrico Olivelli <eo...@gmail.com>
    
    This closes #1827 from ivankelly/kill-constructors
---
 .../org/apache/bookkeeper/client/BookKeeper.java   | 11 +--
 .../apache/bookkeeper/client/LedgerCreateOp.java   | 48 ++++++-------
 .../apache/bookkeeper/client/LedgerMetadata.java   | 52 --------------
 .../bookkeeper/client/LedgerMetadataTest.java      | 82 +++++++++++-----------
 .../apache/bookkeeper/client/MockLedgerHandle.java | 14 +++-
 .../client/ReadLastConfirmedAndEntryOpTest.java    |  8 ++-
 .../client/TestLedgerFragmentReplication.java      | 22 +++---
 .../bookkeeper/client/TestWatchEnsembleChange.java | 11 ++-
 .../client/api/BookKeeperBuildersTest.java         | 20 +++---
 .../bookkeeper/meta/LedgerManagerIteratorTest.java | 16 ++++-
 .../replication/AuditorLedgerCheckerTest.java      |  9 ++-
 .../metadata/etcd/EtcdLedgerManagerTest.java       | 21 +++---
 12 files changed, 150 insertions(+), 164 deletions(-)

diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java
index 14760a8..72edf51 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java
@@ -32,6 +32,7 @@ import io.netty.util.HashedWheelTimer;
 import io.netty.util.concurrent.DefaultThreadFactory;
 import java.io.IOException;
 import java.net.URI;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
@@ -743,7 +744,8 @@ public class BookKeeper implements org.apache.bookkeeper.client.api.BookKeeper {
                                   final int writeQuorumSize,
                                   final DigestType digestType,
                                   final byte[] passwd, final CreateCallback cb, final Object ctx) {
-        asyncCreateLedger(ensSize, writeQuorumSize, writeQuorumSize, digestType, passwd, cb, ctx, null);
+        asyncCreateLedger(ensSize, writeQuorumSize, writeQuorumSize,
+                          digestType, passwd, cb, ctx, Collections.emptyMap());
     }
 
     /**
@@ -832,7 +834,7 @@ public class BookKeeper implements org.apache.bookkeeper.client.api.BookKeeper {
     public LedgerHandle createLedger(int ensSize, int qSize,
                                      DigestType digestType, byte passwd[])
             throws InterruptedException, BKException {
-        return createLedger(ensSize, qSize, qSize, digestType, passwd, null);
+        return createLedger(ensSize, qSize, qSize, digestType, passwd, Collections.emptyMap());
     }
 
     /**
@@ -852,7 +854,7 @@ public class BookKeeper implements org.apache.bookkeeper.client.api.BookKeeper {
     public LedgerHandle createLedger(int ensSize, int writeQuorumSize, int ackQuorumSize,
             DigestType digestType, byte passwd[])
             throws InterruptedException, BKException {
-        return createLedger(ensSize, writeQuorumSize, ackQuorumSize, digestType, passwd, null);
+        return createLedger(ensSize, writeQuorumSize, ackQuorumSize, digestType, passwd, Collections.emptyMap());
     }
 
     /**
@@ -906,7 +908,8 @@ public class BookKeeper implements org.apache.bookkeeper.client.api.BookKeeper {
     public LedgerHandle createLedgerAdv(int ensSize, int writeQuorumSize, int ackQuorumSize,
                                         DigestType digestType, byte passwd[])
             throws InterruptedException, BKException {
-        return createLedgerAdv(ensSize, writeQuorumSize, ackQuorumSize, digestType, passwd, null);
+        return createLedgerAdv(ensSize, writeQuorumSize, ackQuorumSize,
+                               digestType, passwd, Collections.emptyMap());
     }
 
     /**
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerCreateOp.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerCreateOp.java
index 16a6e95..d95665c 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerCreateOp.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerCreateOp.java
@@ -59,10 +59,14 @@ class LedgerCreateOp {
     static final Logger LOG = LoggerFactory.getLogger(LedgerCreateOp.class);
 
     final CreateCallback cb;
-    final LedgerMetadata metadata;
+    LedgerMetadata metadata;
     LedgerHandle lh;
     long ledgerId = -1L;
     final Object ctx;
+    final int ensembleSize;
+    final int writeQuorumSize;
+    final int ackQuorumSize;
+    final Map<String, byte[]> customMetadata;
     final byte[] passwd;
     final BookKeeper bk;
     final DigestType digestType;
@@ -102,15 +106,11 @@ class LedgerCreateOp {
             EnumSet<WriteFlag> writeFlags,
             BookKeeperClientStats clientStats) {
         this.bk = bk;
-        this.metadata = new LedgerMetadata(
-            ensembleSize,
-            writeQuorumSize,
-            ackQuorumSize,
-            digestType,
-            passwd,
-            customMetadata,
-            bk.getConf().getStoreSystemtimeAsLedgerCreationTime());
+        this.ensembleSize = ensembleSize;
+        this.writeQuorumSize = writeQuorumSize;
+        this.ackQuorumSize = ackQuorumSize;
         this.digestType = digestType;
+        this.customMetadata = customMetadata;
         this.writeFlags = writeFlags;
         this.passwd = passwd;
         this.cb = cb;
@@ -124,29 +124,29 @@ class LedgerCreateOp {
      * Initiates the operation.
      */
     public void initiate() {
-        // allocate ensemble first
-
-        /*
-         * Adding bookies to ledger handle
-         */
+        LedgerMetadataBuilder metadataBuilder = LedgerMetadataBuilder.create()
+            .withEnsembleSize(ensembleSize).withWriteQuorumSize(writeQuorumSize).withAckQuorumSize(ackQuorumSize)
+            .withDigestType(digestType.toApiDigestType()).withPassword(passwd);
+        if (customMetadata != null) {
+            metadataBuilder.withCustomMetadata(customMetadata);
+        }
+        if (bk.getConf().getStoreSystemtimeAsLedgerCreationTime()) {
+            metadataBuilder.withCreationTime(System.currentTimeMillis());
+        }
 
-        List<BookieSocketAddress> ensemble;
+        // select bookies for first ensemble
         try {
-            ensemble = bk.getBookieWatcher()
-                    .newEnsemble(metadata.getEnsembleSize(),
-                            metadata.getWriteQuorumSize(),
-                            metadata.getAckQuorumSize(),
-                            metadata.getCustomMetadata());
+            List<BookieSocketAddress> ensemble = bk.getBookieWatcher()
+                .newEnsemble(ensembleSize, writeQuorumSize, ackQuorumSize, customMetadata);
+            metadataBuilder.newEnsembleEntry(0L, ensemble);
         } catch (BKNotEnoughBookiesException e) {
             LOG.error("Not enough bookies to create ledger");
             createComplete(e.getCode(), null);
             return;
         }
 
-        /*
-         * Add ensemble to the configuration
-         */
-        metadata.addEnsemble(0L, ensemble);
+
+        this.metadata = metadataBuilder.build();
         if (this.generateLedgerId) {
             generateLedgerIdAndCreateLedger();
         } else {
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java
index 90f0f13..5fd5f06 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java
@@ -91,44 +91,6 @@ public class LedgerMetadata implements org.apache.bookkeeper.client.api.LedgerMe
 
     private Map<String, byte[]> customMetadata = Maps.newHashMap();
 
-    public LedgerMetadata(int ensembleSize,
-                          int writeQuorumSize,
-                          int ackQuorumSize,
-                          BookKeeper.DigestType digestType,
-                          byte[] password,
-                          Map<String, byte[]> customMetadata,
-                          boolean storeSystemtimeAsLedgerCreationTime) {
-        this.ensembleSize = ensembleSize;
-        this.writeQuorumSize = writeQuorumSize;
-        this.ackQuorumSize = ackQuorumSize;
-        if (storeSystemtimeAsLedgerCreationTime) {
-            this.ctime = System.currentTimeMillis();
-            this.storeCtime = storeSystemtimeAsLedgerCreationTime;
-        } else {
-            // if client disables storing its system time as ledger creation time, there should be no ctime at this
-            // moment.
-            this.ctime = -1L;
-            this.storeCtime = false;
-        }
-
-        /*
-         * It is set in PendingReadOp.readEntryComplete, and
-         * we read it in LedgerRecoveryOp.readComplete.
-         */
-        this.length = 0;
-        this.state = LedgerMetadataFormat.State.OPEN;
-        this.lastEntryId = LedgerHandle.INVALID_ENTRY_ID;
-        this.metadataFormatVersion = CURRENT_METADATA_FORMAT_VERSION;
-
-        this.digestType = digestType.equals(BookKeeper.DigestType.MAC)
-            ? LedgerMetadataFormat.DigestType.HMAC : LedgerMetadataFormat.DigestType.valueOf(digestType.toString());
-        this.password = Arrays.copyOf(password, password.length);
-        this.hasPassword = true;
-        if (customMetadata != null) {
-            this.customMetadata = customMetadata;
-        }
-    }
-
     LedgerMetadata(int metadataFormatVersion,
                    int ensembleSize,
                    int writeQuorumSize,
@@ -176,15 +138,6 @@ public class LedgerMetadata implements org.apache.bookkeeper.client.api.LedgerMe
     }
 
     /**
-     * Used for testing purpose only.
-     */
-    @VisibleForTesting
-    public LedgerMetadata(int ensembleSize, int writeQuorumSize, int ackQuorumSize,
-            BookKeeper.DigestType digestType, byte[] password) {
-        this(ensembleSize, writeQuorumSize, ackQuorumSize, digestType, password, null, false);
-    }
-
-    /**
      * Copy Constructor.
      */
     LedgerMetadata(LedgerMetadata other) {
@@ -208,11 +161,6 @@ public class LedgerMetadata implements org.apache.bookkeeper.client.api.LedgerMe
         this.customMetadata = other.customMetadata;
     }
 
-    private LedgerMetadata() {
-        this(0, 0, 0, BookKeeper.DigestType.MAC, new byte[] {});
-        this.hasPassword = false;
-    }
-
     @Override
     public NavigableMap<Long, ? extends List<BookieSocketAddress>> getAllEnsembles() {
         return ensembles;
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/LedgerMetadataTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/LedgerMetadataTest.java
index 5f802cb..38e5260 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/LedgerMetadataTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/LedgerMetadataTest.java
@@ -23,11 +23,12 @@ import static com.google.common.base.Charsets.UTF_8;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
+import com.google.common.collect.Lists;
 import java.util.Collections;
-import java.util.NoSuchElementException;
+import java.util.List;
 import org.apache.bookkeeper.client.BookKeeper.DigestType;
+import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.proto.DataFormats.LedgerMetadataFormat;
 import org.junit.Test;
 
@@ -41,14 +42,15 @@ public class LedgerMetadataTest {
 
     @Test
     public void testGetters() {
-        org.apache.bookkeeper.client.api.LedgerMetadata metadata = new LedgerMetadata(
-            3,
-            2,
-            1,
-            DigestType.CRC32,
-            passwd,
-            Collections.emptyMap(),
-            false);
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234));
+        org.apache.bookkeeper.client.api.LedgerMetadata metadata = LedgerMetadataBuilder.create()
+            .withEnsembleSize(3).withWriteQuorumSize(2).withAckQuorumSize(1)
+            .withDigestType(DigestType.CRC32.toApiDigestType()).withPassword(passwd)
+            .newEnsembleEntry(0L, ensemble)
+            .build();
 
         assertEquals(3, metadata.getEnsembleSize());
         assertEquals(2, metadata.getWriteQuorumSize());
@@ -59,27 +61,23 @@ public class LedgerMetadataTest {
         assertEquals(-1L, metadata.getLastEntryId());
         assertEquals(0, metadata.getLength());
         assertFalse(metadata.isClosed());
-        assertTrue(metadata.getAllEnsembles().isEmpty());
-
-        try {
-            metadata.getEnsembleAt(99L);
-            fail("Should fail to retrieve ensemble if ensembles is empty");
-        } catch (NoSuchElementException e) {
-            // expected
-        }
+        assertEquals(1, metadata.getAllEnsembles().size());
+        assertEquals(ensemble, metadata.getAllEnsembles().get(0L));
+        assertEquals(ensemble, metadata.getEnsembleAt(99L));
     }
 
     @Test
     public void testStoreSystemtimeAsLedgerCtimeEnabled()
             throws Exception {
-        LedgerMetadata lm = new LedgerMetadata(
-            3,
-            3,
-            2,
-            DigestType.CRC32,
-            passwd,
-            Collections.emptyMap(),
-            true);
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234));
+        LedgerMetadata lm = LedgerMetadataBuilder.create()
+            .newEnsembleEntry(0L, ensemble)
+            .withCreationTime(System.currentTimeMillis())
+            .storingCreationTime(true)
+            .build();
         LedgerMetadataFormat format = lm.buildProtoFormat();
         assertTrue(format.hasCtime());
     }
@@ -87,28 +85,28 @@ public class LedgerMetadataTest {
     @Test
     public void testStoreSystemtimeAsLedgerCtimeDisabled()
             throws Exception {
-        LedgerMetadata lm = new LedgerMetadata(
-            3,
-            3,
-            2,
-            DigestType.CRC32,
-            passwd,
-            Collections.emptyMap(),
-            false);
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234));
+        LedgerMetadata lm = LedgerMetadataBuilder.create()
+            .newEnsembleEntry(0L, ensemble).build();
+
         LedgerMetadataFormat format = lm.buildProtoFormat();
         assertFalse(format.hasCtime());
     }
 
     @Test
     public void testToString() {
-        LedgerMetadata lm1 = new LedgerMetadata(
-            3,
-            3,
-            2,
-            DigestType.CRC32,
-            passwd,
-            Collections.emptyMap(),
-            true);
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234));
+
+        LedgerMetadata lm1 = LedgerMetadataBuilder.create()
+            .withDigestType(DigestType.CRC32.toApiDigestType())
+            .withPassword(passwd)
+            .newEnsembleEntry(0L, ensemble).build();
 
         assertTrue("toString should contain 'password' field", lm1.toString().contains("password"));
         assertTrue("toString should contain password value", lm1.toString().contains(passwdStr));
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/MockLedgerHandle.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/MockLedgerHandle.java
index c2235c2..b7cb9e1 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/MockLedgerHandle.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/MockLedgerHandle.java
@@ -28,6 +28,7 @@ import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Queue;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.RejectedExecutionException;
@@ -41,6 +42,7 @@ import org.apache.bookkeeper.client.api.LedgerEntries;
 import org.apache.bookkeeper.client.api.ReadHandle;
 import org.apache.bookkeeper.client.api.WriteFlag;
 import org.apache.bookkeeper.client.impl.LedgerEntryImpl;
+import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.versioning.LongVersion;
 import org.apache.bookkeeper.versioning.Versioned;
 import org.slf4j.Logger;
@@ -62,7 +64,7 @@ public class MockLedgerHandle extends LedgerHandle {
 
     MockLedgerHandle(MockBookKeeper bk, long id, DigestType digest, byte[] passwd) throws GeneralSecurityException {
         super(bk.getClientCtx(), id,
-              new Versioned<>(new LedgerMetadata(3, 3, 2, DigestType.MAC, "".getBytes()), new LongVersion(0L)),
+              new Versioned<>(createMetadata(), new LongVersion(0L)),
               DigestType.MAC, "".getBytes(), WriteFlag.NONE);
         this.bk = bk;
         this.id = id;
@@ -265,6 +267,16 @@ public class MockLedgerHandle extends LedgerHandle {
         return readHandle.readLastAddConfirmedAndEntryAsync(entryId, timeOutInMillis, parallel);
     }
 
+    private static LedgerMetadata createMetadata() {
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234));
+        return LedgerMetadataBuilder.create()
+            .newEnsembleEntry(0L, ensemble)
+            .build();
+    }
+
     private static final Logger log = LoggerFactory.getLogger(MockLedgerHandle.class);
 
 }
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOpTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOpTest.java
index 3d9c394..252c1b9 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOpTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOpTest.java
@@ -99,13 +99,15 @@ public class ReadLastConfirmedAndEntryOpTest {
         internalConf = ClientInternalConf.fromConfig(conf);
 
         // metadata
-        this.ledgerMetadata =
-            new LedgerMetadata(3, 3, 2, DigestType.CRC32, new byte[0]);
         ArrayList<BookieSocketAddress> ensemble = new ArrayList<>(3);
         for (int i = 0; i < 3; i++) {
             ensemble.add(new BookieSocketAddress("127.0.0.1", 3181 + i));
         }
-        this.ledgerMetadata.addEnsemble(0L, ensemble);
+        this.ledgerMetadata = LedgerMetadataBuilder.create()
+            .withEnsembleSize(3).withWriteQuorumSize(2).withAckQuorumSize(2)
+            .withDigestType(DigestType.CRC32.toApiDigestType())
+            .withPassword(new byte[0])
+            .newEnsembleEntry(0L, ensemble).build();
         this.distributionSchedule = new RoundRobinDistributionSchedule(3, 2, 3);
         // schedulers
         this.scheduler = Executors.newSingleThreadScheduledExecutor();
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestLedgerFragmentReplication.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestLedgerFragmentReplication.java
index f407c35..3503e91 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestLedgerFragmentReplication.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestLedgerFragmentReplication.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
 import java.util.Enumeration;
@@ -234,18 +235,17 @@ public class TestLedgerFragmentReplication extends BookKeeperClusterTestCase {
     @Test
     public void testSplitIntoSubFragmentsWithDifferentFragmentBoundaries()
             throws Exception {
-        LedgerMetadata metadata = new LedgerMetadata(3, 3, 3, TEST_DIGEST_TYPE,
-                TEST_PSSWD) {
-            @Override
-            List<BookieSocketAddress> getEnsemble(long entryId) {
-                return null;
-            }
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234));
+        LedgerMetadata metadata = LedgerMetadataBuilder.create()
+            .withEnsembleSize(3).withWriteQuorumSize(3).withAckQuorumSize(3)
+            .withPassword(TEST_PSSWD).withDigestType(TEST_DIGEST_TYPE.toApiDigestType())
+            .closingAt(-1, 0)
+            .newEnsembleEntry(0L, ensemble)
+            .build();
 
-            @Override
-            public boolean isClosed() {
-                return true;
-            }
-        };
         LedgerHandle lh = new LedgerHandle(bkc.getClientCtx(), 0,
                                            new Versioned<>(metadata, new LongVersion(0L)),
                                            TEST_DIGEST_TYPE,
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestWatchEnsembleChange.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestWatchEnsembleChange.java
index 38411ac..2590666 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestWatchEnsembleChange.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestWatchEnsembleChange.java
@@ -24,6 +24,7 @@ import static org.apache.bookkeeper.meta.MetadataDrivers.runFunctionWithLedgerMa
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.UncheckedExecutionException;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
@@ -130,10 +131,18 @@ public class TestWatchEnsembleChange extends BookKeeperClusterTestCase {
         final CountDownLatch createLatch = new CountDownLatch(1);
         final CountDownLatch removeLatch = new CountDownLatch(1);
 
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234),
+                new BookieSocketAddress("192.0.2.4", 1234));
         idGenerator.generateLedgerId(new GenericCallback<Long>() {
                 @Override
                 public void operationComplete(int rc, final Long lid) {
-                    LedgerMetadata metadata = new LedgerMetadata(4, 2, 2, digestType, "fpj was here".getBytes());
+                    LedgerMetadata metadata = LedgerMetadataBuilder.create()
+                        .withEnsembleSize(4).withWriteQuorumSize(2)
+                        .withAckQuorumSize(2)
+                        .newEnsembleEntry(0L, ensemble).build();
                     manager.createLedgerMetadata(lid, metadata)
                         .whenComplete((result, exception) -> {
                                 bbLedgerId.putLong(lid);
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/api/BookKeeperBuildersTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/api/BookKeeperBuildersTest.java
index 58b75ba..f593642 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/api/BookKeeperBuildersTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/api/BookKeeperBuildersTest.java
@@ -34,6 +34,7 @@ import org.apache.bookkeeper.client.BKException.BKNoSuchLedgerExistsException;
 import org.apache.bookkeeper.client.BookKeeper;
 import org.apache.bookkeeper.client.LedgerHandle;
 import org.apache.bookkeeper.client.LedgerMetadata;
+import org.apache.bookkeeper.client.LedgerMetadataBuilder;
 import org.apache.bookkeeper.client.MockBookKeeperTestCase;
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.proto.BookieProtocol;
@@ -405,16 +406,15 @@ public class BookKeeperBuildersTest extends MockBookKeeperTestCase {
     protected LedgerMetadata generateLedgerMetadata(int ensembleSize,
         int writeQuorumSize, int ackQuorumSize, byte[] password,
         Map<String, byte[]> customMetadata) {
-        LedgerMetadata ledgerMetadata = new LedgerMetadata(
-            ensembleSize,
-            writeQuorumSize,
-            ackQuorumSize,
-            BookKeeper.DigestType.CRC32,
-            password,
-            customMetadata,
-            true);
-        ledgerMetadata.addEnsemble(0, generateNewEnsemble(ensembleSize));
-        return ledgerMetadata;
+        return LedgerMetadataBuilder.create()
+            .withEnsembleSize(ensembleSize)
+            .withWriteQuorumSize(writeQuorumSize)
+            .withAckQuorumSize(ackQuorumSize)
+            .withDigestType(BookKeeper.DigestType.CRC32.toApiDigestType())
+            .withPassword(password)
+            .withCustomMetadata(customMetadata)
+            .withCreationTime(System.currentTimeMillis())
+            .newEnsembleEntry(0, generateNewEnsemble(ensembleSize)).build();
     }
 
 }
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/meta/LedgerManagerIteratorTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/meta/LedgerManagerIteratorTest.java
index 90fb2ee..73f8d39 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/meta/LedgerManagerIteratorTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/meta/LedgerManagerIteratorTest.java
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import com.google.common.collect.Lists;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -46,8 +47,10 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.bookkeeper.client.BKException;
 import org.apache.bookkeeper.client.BookKeeper;
 import org.apache.bookkeeper.client.LedgerMetadata;
+import org.apache.bookkeeper.client.LedgerMetadataBuilder;
 import org.apache.bookkeeper.meta.LedgerManager.LedgerRangeIterator;
 import org.apache.bookkeeper.meta.zk.ZKMetadataDriverBase;
+import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.util.MathUtils;
 import org.apache.bookkeeper.util.ZkUtils;
 import org.apache.bookkeeper.versioning.Version;
@@ -84,9 +87,16 @@ public class LedgerManagerIteratorTest extends LedgerManagerTestCase {
      * @throws InterruptedException
      */
     void createLedger(LedgerManager lm, Long ledgerId) throws Exception {
-        LedgerMetadata meta = new LedgerMetadata(
-                3, 3, 2,
-                BookKeeper.DigestType.CRC32, "passwd".getBytes());
+        List<BookieSocketAddress> ensemble = Lists.newArrayList(
+                new BookieSocketAddress("192.0.2.1", 1234),
+                new BookieSocketAddress("192.0.2.2", 1234),
+                new BookieSocketAddress("192.0.2.3", 1234));
+        LedgerMetadata meta = LedgerMetadataBuilder.create()
+            .withEnsembleSize(3).withWriteQuorumSize(3).withAckQuorumSize(2)
+            .withDigestType(BookKeeper.DigestType.CRC32.toApiDigestType())
+            .withPassword("passwd".getBytes())
+            .newEnsembleEntry(0L, ensemble)
+            .build();
         lm.createLedgerMetadata(ledgerId, meta).get();
     }
 
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorLedgerCheckerTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorLedgerCheckerTest.java
index 83d1dc0..9db9188 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorLedgerCheckerTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorLedgerCheckerTest.java
@@ -52,6 +52,7 @@ import org.apache.bookkeeper.client.BKException;
 import org.apache.bookkeeper.client.BookKeeper.DigestType;
 import org.apache.bookkeeper.client.LedgerHandle;
 import org.apache.bookkeeper.client.LedgerMetadata;
+import org.apache.bookkeeper.client.LedgerMetadataBuilder;
 import org.apache.bookkeeper.common.util.OrderedScheduler;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.meta.LedgerManager;
@@ -545,12 +546,16 @@ public class AuditorLedgerCheckerTest extends BookKeeperClusterTestCase {
         int numofledgers = 5;
         Random rand = new Random();
         for (int i = 0; i < numofledgers; i++) {
-            LedgerMetadata metadata = new LedgerMetadata(3, 2, 2, DigestType.CRC32, "passwd".getBytes());
             ArrayList<BookieSocketAddress> ensemble = new ArrayList<BookieSocketAddress>();
             ensemble.add(new BookieSocketAddress("99.99.99.99:9999"));
             ensemble.add(new BookieSocketAddress("11.11.11.11:1111"));
             ensemble.add(new BookieSocketAddress("88.88.88.88:8888"));
-            metadata.addEnsemble(0, ensemble);
+
+            LedgerMetadata metadata = LedgerMetadataBuilder.create()
+                .withEnsembleSize(3).withWriteQuorumSize(2).withAckQuorumSize(2)
+                .withDigestType(DigestType.CRC32.toApiDigestType())
+                .withPassword("passwd".getBytes())
+                .newEnsembleEntry(0L, ensemble).build();
 
             long ledgerId = (Math.abs(rand.nextLong())) % 100000000;
 
diff --git a/metadata-drivers/etcd/src/test/java/org/apache/bookkeeper/metadata/etcd/EtcdLedgerManagerTest.java b/metadata-drivers/etcd/src/test/java/org/apache/bookkeeper/metadata/etcd/EtcdLedgerManagerTest.java
index da33165..95da4ff 100644
--- a/metadata-drivers/etcd/src/test/java/org/apache/bookkeeper/metadata/etcd/EtcdLedgerManagerTest.java
+++ b/metadata-drivers/etcd/src/test/java/org/apache/bookkeeper/metadata/etcd/EtcdLedgerManagerTest.java
@@ -239,11 +239,11 @@ public class EtcdLedgerManagerTest extends EtcdTestBase {
     private void createNumLedgers(int numLedgers) throws Exception {
         List<CompletableFuture<Versioned<LedgerMetadata>>> createFutures = new ArrayList<>(numLedgers);
         for (int i = 0; i < numLedgers; i++) {
-            LedgerMetadata metadata = new LedgerMetadata(
-                3, 3, 2,
-                DigestType.CRC32C,
-                "test-password".getBytes(UTF_8)
-            );
+            LedgerMetadata metadata = LedgerMetadataBuilder.create()
+                .withEnsembleSize(3).withWriteQuorumSize(3).withAckQuorumSize(2)
+                .withDigestType(DigestType.CRC32C.toApiDigestType())
+                .withPassword("test-password".getBytes(UTF_8))
+                .newEnsembleEntry(0L, createNumBookies(3)).build();
             createFutures.add(lm.createLedgerMetadata(i, metadata));
         }
         FutureUtils.result(FutureUtils.collect(createFutures));
@@ -254,12 +254,11 @@ public class EtcdLedgerManagerTest extends EtcdTestBase {
         long ledgerId = System.currentTimeMillis();
 
         // create a ledger metadata
-        LedgerMetadata metadata = new LedgerMetadata(
-            3, 3, 2,
-            DigestType.CRC32C,
-            "test-password".getBytes(UTF_8)
-        );
-        metadata.addEnsemble(0L, createNumBookies(3));
+        LedgerMetadata metadata = LedgerMetadataBuilder.create()
+                .withEnsembleSize(3).withWriteQuorumSize(3).withAckQuorumSize(2)
+                .withDigestType(DigestType.CRC32C.toApiDigestType())
+                .withPassword("test-password".getBytes(UTF_8))
+                .newEnsembleEntry(0L, createNumBookies(3)).build();
         result(lm.createLedgerMetadata(ledgerId, metadata));
         Versioned<LedgerMetadata> readMetadata = lm.readLedgerMetadata(ledgerId).get();
         log.info("Create ledger metadata : {}", readMetadata.getValue());