This is an automated email from the ASF dual-hosted git repository.
zhaijia pushed a commit to branch branch-4.6
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git
The following commit(s) were added to refs/heads/branch-4.6 by this push:
new 17cb7bc ISSUE #787: Client should be able to get ledger metadata from
Handles.
17cb7bc is described below
commit 17cb7bc7e4a76393437580f1454fdff40346919a
Author: Sijie Guo <[email protected]>
AuthorDate: Fri Dec 1 22:13:49 2017 +0800
ISSUE #787: Client should be able to get ledger metadata from Handles.
Descriptions of the changes in this PR:
- create a `LedgerMetadata` interface for exposing public information
- add `getLedgerMetadata` to Handle, so both WriteHandle and ReadHandle are
able to access the metadata.
Author: Sijie Guo <[email protected]>
Reviewers: Ivan Kelly <[email protected]>, Enrico Olivelli
<[email protected]>, Jia Zhai <None>
This closes #788 from sijie/ledger_metadata_interface, closes #787
(cherry picked from commit 5f3496f740629ba4ea0d0abb3272ca2e6d8ccba7)
Signed-off-by: Jia Zhai <[email protected]>
---
.../org/apache/bookkeeper/client/LedgerHandle.java | 5 +-
.../apache/bookkeeper/client/LedgerMetadata.java | 39 +++++--
.../org/apache/bookkeeper/client/LedgerOpenOp.java | 10 +-
.../org/apache/bookkeeper/client/api/Handle.java | 11 ++
.../bookkeeper/client/api/LedgerMetadata.java | 121 +++++++++++++++++++++
.../bookkeeper/client/LedgerMetadataTest.java | 33 ++++++
.../apache/bookkeeper/client/TestSequenceRead.java | 2 +-
.../main/resources/bookkeeper/findbugsExclude.xml | 4 +
8 files changed, 206 insertions(+), 19 deletions(-)
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerHandle.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerHandle.java
index ca6cb89..2207fc5 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerHandle.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerHandle.java
@@ -231,10 +231,9 @@ public class LedgerHandle implements WriteHandle {
}
/**
- * Get the LedgerMetadata
- *
- * @return LedgerMetadata for the LedgerHandle
+ * {@inheritDoc}
*/
+ @Override
public LedgerMetadata getLedgerMetadata() {
return metadata;
}
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 44c8ce7..180c59e 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
@@ -35,9 +35,11 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.NavigableMap;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
+import org.apache.bookkeeper.client.api.DigestType;
import org.apache.bookkeeper.net.BookieSocketAddress;
import org.apache.bookkeeper.proto.DataFormats.LedgerMetadataFormat;
import org.apache.bookkeeper.versioning.Version;
@@ -50,7 +52,7 @@ import org.slf4j.LoggerFactory;
*
* <p>It provides parsing and serialization methods of such metadata.
*/
-public class LedgerMetadata {
+public class LedgerMetadata implements
org.apache.bookkeeper.client.api.LedgerMetadata {
static final Logger LOG = LoggerFactory.getLogger(LedgerMetadata.class);
private static final String closed = "CLOSED";
@@ -77,7 +79,7 @@ public class LedgerMetadata {
private boolean storeSystemtimeAsLedgerCreationTime;
private LedgerMetadataFormat.State state;
- private SortedMap<Long, ArrayList<BookieSocketAddress>> ensembles =
+ private TreeMap<Long, ArrayList<BookieSocketAddress>> ensembles =
new TreeMap<Long, ArrayList<BookieSocketAddress>>();
ArrayList<BookieSocketAddress> currentEnsemble;
volatile Version version = Version.NEW;
@@ -173,30 +175,35 @@ public class LedgerMetadata {
* @return SortedMap of Ledger Fragments and the corresponding
* bookie ensembles that store the entries.
*/
- public SortedMap<Long, ArrayList<BookieSocketAddress>> getEnsembles() {
+ public TreeMap<Long, ArrayList<BookieSocketAddress>> getEnsembles() {
return ensembles;
}
- void setEnsembles(SortedMap<Long, ArrayList<BookieSocketAddress>>
ensembles) {
+ @Override
+ public NavigableMap<Long, ? extends List<BookieSocketAddress>>
getAllEnsembles() {
+ return ensembles;
+ }
+
+ void setEnsembles(TreeMap<Long, ArrayList<BookieSocketAddress>> ensembles)
{
this.ensembles = ensembles;
}
+ @Override
public int getEnsembleSize() {
return ensembleSize;
}
+ @Override
public int getWriteQuorumSize() {
return writeQuorumSize;
}
+ @Override
public int getAckQuorumSize() {
return ackQuorumSize;
}
- /**
- * Get the creation timestamp of the ledger
- * @return
- */
+ @Override
public long getCtime() {
return ctime;
}
@@ -221,18 +228,21 @@ public class LedgerMetadata {
return Arrays.copyOf(password, password.length);
}
- BookKeeper.DigestType getDigestType() {
+ @Override
+ public DigestType getDigestType() {
if (digestType.equals(LedgerMetadataFormat.DigestType.HMAC)) {
- return BookKeeper.DigestType.MAC;
+ return DigestType.MAC;
} else {
- return BookKeeper.DigestType.CRC32;
+ return DigestType.CRC32;
}
}
+ @Override
public long getLastEntryId() {
return lastEntryId;
}
+ @Override
public long getLength() {
return length;
}
@@ -241,6 +251,7 @@ public class LedgerMetadata {
this.length = length;
}
+ @Override
public boolean isClosed() {
return state == LedgerMetadataFormat.State.CLOSED;
}
@@ -279,6 +290,11 @@ public class LedgerMetadata {
return ensembles.get(ensembles.headMap(entryId + 1).lastKey());
}
+ @Override
+ public List<BookieSocketAddress> getEnsembleAt(long entryId) {
+ return getEnsemble(entryId);
+ }
+
/**
* the entry id greater than the given entry-id at which the next ensemble
change takes
* place
@@ -296,6 +312,7 @@ public class LedgerMetadata {
}
}
+ @Override
public Map<String, byte[]> getCustomMetadata() {
return this.customMetadata;
}
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java
index 910f33a..256cd59 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java
@@ -21,6 +21,8 @@
package org.apache.bookkeeper.client;
+import static
org.apache.bookkeeper.client.BookKeeper.DigestType.fromApiDigestType;
+
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -128,7 +130,7 @@ class LedgerOpenOp implements
GenericCallback<LedgerMetadata> {
final byte[] passwd;
DigestType digestType = enableDigestAutodetection
- ? metadata.getDigestType()
+ ?
fromApiDigestType(metadata.getDigestType())
: suggestedDigestType;
/* For an administrative open, the default passwords
@@ -136,7 +138,7 @@ class LedgerOpenOp implements
GenericCallback<LedgerMetadata> {
* already contains passwords, use these instead. */
if (administrativeOpen && metadata.hasPassword()) {
passwd = metadata.getPassword();
- digestType = metadata.getDigestType();
+ digestType = fromApiDigestType(metadata.getDigestType());
} else {
passwd = this.passwd;
@@ -146,7 +148,7 @@ class LedgerOpenOp implements
GenericCallback<LedgerMetadata> {
openComplete(BKException.Code.UnauthorizedAccessException,
null);
return;
}
- if (digestType != metadata.getDigestType()) {
+ if (digestType != fromApiDigestType(metadata.getDigestType()))
{
LOG.error("Provided digest does not match that in
metadata");
openComplete(BKException.Code.DigestMatchException, null);
return;
@@ -276,7 +278,7 @@ class LedgerOpenOp implements
GenericCallback<LedgerMetadata> {
return;
}
- LedgerOpenOp op = new LedgerOpenOp(bk, builderLedgerId,
DigestType.fromApiDigestType(builderDigestType),
+ LedgerOpenOp op = new LedgerOpenOp(bk, builderLedgerId,
fromApiDigestType(builderDigestType),
builderPassword, cb, null);
ReentrantReadWriteLock closeLock = bk.getCloseLock();
closeLock.readLock().lock();
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/api/Handle.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/api/Handle.java
index 326f2e6..f520e61 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/api/Handle.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/api/Handle.java
@@ -56,6 +56,17 @@ public interface Handle extends AutoCloseable {
}
/**
+ * Returns the metadata of this ledger.
+ *
+ * <p>This call only retrieves the metadata cached locally. If there is
any metadata updated, the read
+ * handle will receive the metadata updates and update the metadata
locally. The metadata notification
+ * can be deplayed, so it is possible you can receive a stale copy of
ledger metadata from this call.
+ *
+ * @return the metadata of this ledger.
+ */
+ LedgerMetadata getLedgerMetadata();
+
+ /**
* Asynchronous close, any adds in flight will return errors.
*
* <p>Closing a ledger will ensure that all clients agree on what the last
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/api/LedgerMetadata.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/api/LedgerMetadata.java
new file mode 100644
index 0000000..dc2deb6
--- /dev/null
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/api/LedgerMetadata.java
@@ -0,0 +1,121 @@
+/*
+ * 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.client.api;
+
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableMap;
+import
org.apache.bookkeeper.common.annotation.InterfaceAudience.LimitedPrivate;
+import org.apache.bookkeeper.common.annotation.InterfaceStability.Unstable;
+import org.apache.bookkeeper.net.BookieSocketAddress;
+
+/**
+ * Represents the client-side metadata of a ledger. It is immutable.
+ *
+ * @since 4.6
+ */
+@LimitedPrivate
+@Unstable
+public interface LedgerMetadata {
+
+ /**
+ * Returns the ensemble size of this ledger.
+ *
+ * @return the ensemble size of this ledger.
+ */
+ int getEnsembleSize();
+
+ /**
+ * Returns the write quorum size of this ledger.
+ *
+ * @return the write quorum size of this ledger.
+ */
+ int getWriteQuorumSize();
+
+ /**
+ * Returns the ack quorum size of this ledger.
+ *
+ * @return the ack quorum size of this ledger.
+ */
+ int getAckQuorumSize();
+
+ /**
+ * Returns the last entry id of this ledger.
+ *
+ * <p>If this ledger is not sealed {@link #isClosed()}, it returns {@code
-1L}.
+ *
+ * @return the last entry id of this ledger if it is sealed, otherwise -1.
+ */
+ long getLastEntryId();
+
+ /**
+ * Returns the length of this ledger.
+ *
+ * <p>If this ledger is not sealed {@link #isClosed()}, it returns {@code
0}.
+ *
+ * @return the length of this ledger if it is sealed, otherwise 0.
+ */
+ long getLength();
+
+ /**
+ * Returns the digest type used by this ledger.
+ *
+ * @return the digest type used by this ledger.
+ */
+ DigestType getDigestType();
+
+ /**
+ * Returns the creation timestamp of this ledger.
+ *
+ * @return the creation timestamp of this ledger.
+ */
+ long getCtime();
+
+ /**
+ * Returns whether the ledger is sealed or not.
+ *
+ * @return true if the ledger is sealed, otherwise false.
+ */
+ boolean isClosed();
+
+ /**
+ * Returns the custom metadata stored with the ledgers.
+ *
+ * @return the custom metadata stored with the ledgers.
+ */
+ Map<String, byte[]> getCustomMetadata();
+
+ /**
+ * Returns the ensemble at the given {@code entryId}.
+ *
+ * @param entryId the entry id to retrieve its ensemble information
+ * @return the ensemble which contains the given {@code entryId}.
+ */
+ List<BookieSocketAddress> getEnsembleAt(long entryId);
+
+ /**
+ * Returns all the ensembles of this entry.
+ *
+ * @return all the ensembles of this entry.
+ */
+ NavigableMap<Long, ? extends List<BookieSocketAddress>> getAllEnsembles();
+
+
+}
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 d7b913f..a58147c 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
@@ -20,10 +20,13 @@
package org.apache.bookkeeper.client;
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 java.util.Collections;
+import java.util.NoSuchElementException;
import org.apache.bookkeeper.client.BookKeeper.DigestType;
import org.apache.bookkeeper.proto.DataFormats.LedgerMetadataFormat;
import org.junit.Test;
@@ -36,6 +39,36 @@ public class LedgerMetadataTest {
private static final byte[] passwd = "testPasswd".getBytes(UTF_8);
@Test
+ public void testGetters() {
+ org.apache.bookkeeper.client.api.LedgerMetadata metadata = new
LedgerMetadata(
+ 3,
+ 2,
+ 1,
+ DigestType.CRC32,
+ passwd,
+ Collections.emptyMap(),
+ false);
+
+ assertEquals(3, metadata.getEnsembleSize());
+ assertEquals(2, metadata.getWriteQuorumSize());
+ assertEquals(1, metadata.getAckQuorumSize());
+ assertEquals(org.apache.bookkeeper.client.api.DigestType.CRC32,
metadata.getDigestType());
+ assertEquals(Collections.emptyMap(), metadata.getCustomMetadata());
+ assertEquals(-1L, metadata.getCtime());
+ 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
+ }
+ }
+
+ @Test
public void testStoreSystemtimeAsLedgerCtimeEnabled()
throws Exception {
LedgerMetadata lm = new LedgerMetadata(
diff --git
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestSequenceRead.java
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestSequenceRead.java
index 8e38487..05cf072 100644
---
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestSequenceRead.java
+++
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestSequenceRead.java
@@ -55,7 +55,7 @@ public class TestSequenceRead extends
BookKeeperClusterTestCase {
final LedgerHandle lh = bkc.createLedger(3, 3, 3, digestType, passwd);
// introduce duplicated bookies in an ensemble.
SortedMap<Long, ArrayList<BookieSocketAddress>> ensembles =
lh.getLedgerMetadata().getEnsembles();
- SortedMap<Long, ArrayList<BookieSocketAddress>> newEnsembles = new
TreeMap<Long, ArrayList<BookieSocketAddress>>();
+ TreeMap<Long, ArrayList<BookieSocketAddress>> newEnsembles = new
TreeMap<>();
for (Map.Entry<Long, ArrayList<BookieSocketAddress>> entry :
ensembles.entrySet()) {
ArrayList<BookieSocketAddress> newList = new
ArrayList<BookieSocketAddress>(entry.getValue().size());
BookieSocketAddress firstBookie = entry.getValue().get(0);
diff --git a/buildtools/src/main/resources/bookkeeper/findbugsExclude.xml
b/buildtools/src/main/resources/bookkeeper/findbugsExclude.xml
index e239e67..2cc5ce7 100644
--- a/buildtools/src/main/resources/bookkeeper/findbugsExclude.xml
+++ b/buildtools/src/main/resources/bookkeeper/findbugsExclude.xml
@@ -51,6 +51,10 @@
<Bug pattern="NM_SAME_SIMPLE_NAME_AS_INTERFACE" />
</Match>
<Match>
+ <Class name="org.apache.bookkeeper.client.LedgerMetadata" />
+ <Bug pattern="NM_SAME_SIMPLE_NAME_AS_INTERFACE" />
+ </Match>
+ <Match>
<Class name="org.apache.bookkeeper.client.BookKeeper" />
<Bug pattern="NM_SAME_SIMPLE_NAME_AS_INTERFACE" />
</Match>
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].