Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 0BF15200D49 for ; Fri, 24 Nov 2017 21:38:11 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 0A2CC160BF2; Fri, 24 Nov 2017 20:38:11 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 7CC64160BDA for ; Fri, 24 Nov 2017 21:38:09 +0100 (CET) Received: (qmail 634 invoked by uid 500); 24 Nov 2017 20:38:08 -0000 Mailing-List: contact commits-help@bookkeeper.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: bookkeeper-dev@bookkeeper.apache.org Delivered-To: mailing list commits@bookkeeper.apache.org Received: (qmail 625 invoked by uid 99); 24 Nov 2017 20:38:08 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Nov 2017 20:38:08 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 82F5F854A1; Fri, 24 Nov 2017 20:38:07 +0000 (UTC) Date: Fri, 24 Nov 2017 20:38:07 +0000 To: "commits@bookkeeper.apache.org" Subject: [bookkeeper] branch asf-site updated: Updated site at revision 2915f55 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <151155588723.9136.18183692227882550682@gitbox.apache.org> From: git-site-role@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: bookkeeper X-Git-Refname: refs/heads/asf-site X-Git-Reftype: branch X-Git-Oldrev: 63ee9610ab3814db527e40a5274e070f92e04171 X-Git-Newrev: 202c26d3392e4d543b827497101e593312801d07 X-Git-Rev: 202c26d3392e4d543b827497101e593312801d07 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated archived-at: Fri, 24 Nov 2017 20:38:11 -0000 This is an automated email from the ASF dual-hosted git repository. git-site-role pushed a commit to branch asf-site in repository https://gitbox.apache.org/repos/asf/bookkeeper.git The following commit(s) were added to refs/heads/asf-site by this push: new 202c26d Updated site at revision 2915f55 202c26d is described below commit 202c26d3392e4d543b827497101e593312801d07 Author: jenkins AuthorDate: Fri Nov 24 20:38:05 2017 +0000 Updated site at revision 2915f55 --- content/docs/4.6.0/api/ledger-api/index.html | 288 ++++++++++++++++++++++ content/docs/latest/api/ledger-adv-api/index.html | 29 +++ 2 files changed, 317 insertions(+) diff --git a/content/docs/4.6.0/api/ledger-api/index.html b/content/docs/4.6.0/api/ledger-api/index.html index 750040c..bbd7a2d 100644 --- a/content/docs/4.6.0/api/ledger-api/index.html +++ b/content/docs/4.6.0/api/ledger-api/index.html @@ -941,6 +941,282 @@ Value = 3, isLeader = +

New API

+ +

Since 4.6 BookKeeper provides a new client API which leverages Java8 CompletableFuture facility. +WriteHandle, WriteAdvHandle, ReadHandle are introduced for replacing the generic LedgerHandle.

+ +
+

All the new API now is available in org.apache.bookkeeper.client.api. You should only use interfaces defined in this package.

+
+ +

Beware that this API in 4.6 is still experimental API and can be subject to changes in next minor releases.

+ +

Create a new client

+ +

In order to create a new BookKeeper client object, you need to construct a ClientConfiguration object and set a connection string first, and then use

// construct a client configuration instance
+ClientConfiguration conf = new ClientConfiguration();
+conf.setZkServers(zkConnectionString);
+conf.setZkLedgersRootPath("/path/to/ledgers/root");
+
+// build the bookkeeper client
+BookKeeper bk = BookKeeper.newBuilder(conf)
+    .statsLogger(...)
+    ...
+    .build();
+
+
+ + +

Create ledgers

+ +

the easiest way to create a ledger using the java client is via the createbuilder. you must specify at least +a digesttype and a password.

+ +

here’s an example:

+ +
BookKeeper bk = ...;
+
+byte[] password = "some-password".getBytes();
+
+WriteHandle wh = bk.newCreateLedgerOp()
+    .withDigestType(DigestType.CRC32)
+    .withPassword(password)
+    .withEnsembleSize(3)
+    .withWriteQuorumSize(3)
+    .withAckQuorumSize(2)
+    .execute()          // execute the creation op
+    .get();             // wait for the execution to complete
+
+
+ +

A WriteHandle is returned for applications to write and read entries to and from the ledger.

+ +

Append entries to ledgers

+ +

The WriteHandle can be used for applications to append entries to the ledgers.

+ +
WriteHandle wh = ...;
+
+CompletableFuture<Long> addFuture = wh.append("Some entry data".getBytes());
+
+// option 1: you can wait for add to complete synchronously
+try {
+    long entryId = FutureUtils.result(addFuture.get());
+} catch (BKException bke) {
+    // error handling
+}
+
+// option 2: you can process the result and exception asynchronously
+addFuture
+    .thenApply(entryId -> {
+        // process the result
+    })
+    .exceptionally(cause -> {
+        // handle the exception
+    })
+
+// option 3: bookkeeper provides a twitter-future-like event listener for processing result and exception asynchronously
+addFuture.whenComplete(new FutureEventListener() {
+    @Override
+    public void onSuccess(long entryId) {
+        // process the result
+    }
+    @Override
+    public void onFailure(Throwable cause) {
+        // handle the exception
+    }
+});
+
+
+ +

The append method supports three representations of a bytes array: the native java byte[], java nio ByteBuffer and netty ByteBuf. +It is recommended to use ByteBuf as it is more gc friendly.

+ +

Open ledgers

+ +

You can open ledgers to read entries. Opening ledgers is done by openBuilder. You must specify the ledgerId and the password +in order to open the ledgers.

+ +

here’s an example:

+ +
BookKeeper bk = ...;
+
+long ledgerId = ...;
+byte[] password = "some-password".getBytes();
+
+ReadHandle rh = bk.newOpenLedgerOp()
+    .withLedgerId(ledgerId)
+    .withPassword(password)
+    .execute()          // execute the open op
+    .get();             // wait for the execution to complete
+
+
+ +

A ReadHandle is returned for applications to read entries to and from the ledger.

+ +

Recovery vs NoRecovery

+ +

By default, the openBuilder opens the ledger in a NoRecovery mode. You can open the ledger in Recovery mode by specifying +withRecovery(true) in the open builder.

+ +
BookKeeper bk = ...;
+
+long ledgerId = ...;
+byte[] password = "some-password".getBytes();
+
+ReadHandle rh = bk.newOpenLedgerOp()
+    .withLedgerId(ledgerId)
+    .withPassword(password)
+    .withRecovery(true)
+    .execute()
+    .get();
+
+
+
+ +

What is the difference between “Recovery” and “NoRecovery”?

+ +

If you are opening a ledger in “Recovery” mode, it will basically fence and seal the ledger – no more entries are allowed +to be appended to it. The writer which is currently appending entries to the ledger will fail with LedgerFencedException.

+ +

In constrat, opening a ledger in “NoRecovery” mode, it will not fence and seal the ledger. “NoRecovery” mode is usually used by applications to tailing-read from a ledger.

+ +

Read entries from ledgers

+ +

The ReadHandle returned from the open builder can be used for applications to read entries from the ledgers.

+ +
ReadHandle rh = ...;
+
+long startEntryId = ...;
+long endEntryId = ...;
+CompletableFuture<LedgerEntries> readFuture = rh.read(startEntryId, endEntryId);
+
+// option 1: you can wait for read to complete synchronously
+try {
+    LedgerEntries entries = FutureUtils.result(readFuture.get());
+} catch (BKException bke) {
+    // error handling
+}
+
+// option 2: you can process the result and exception asynchronously
+readFuture
+    .thenApply(entries -> {
+        // process the result
+    })
+    .exceptionally(cause -> {
+        // handle the exception
+    })
+
+// option 3: bookkeeper provides a twitter-future-like event listener for processing result and exception asynchronously
+readFuture.whenComplete(new FutureEventListener<>() {
+    @Override
+    public void onSuccess(LedgerEntries entries) {
+        // process the result
+    }
+    @Override
+    public void onFailure(Throwable cause) {
+        // handle the exception
+    }
+});
+
+
+ +

Once you are done with processing the LedgerEntries, you can call #close() on the LedgerEntries instance to +release the buffers held by it.

+ +

Applications are allowed to read any entries between 0 and LastAddConfirmed. If the applications +attempts to read entries beyond LastAddConfirmed, they will receive IncorrectParameterException.

+ +

Read unconfirmed entries from ledgers

+ +

readUnconfirmed is provided the mechanism for applications to read entries beyond LastAddConfirmed. Applications should be aware of readUnconfirmed doesn’t provide any +repeatable read consistency.

+ +
CompletableFuture<LedgerEntries> readFuture = rh.readUnconfirmed(startEntryId, endEntryId);
+
+
+ +

Tailing Reads

+ +

There are two methods for applications to achieve tailing reads: Polling and Long-Polling.

+ +

Polling

+ +

You can do this in synchronous way:

+ +
ReadHandle rh = ...;
+
+long startEntryId = 0L;
+long nextEntryId = startEntryId;
+int numEntriesPerBatch = 4;
+while (!rh.isClosed() || nextEntryId <= rh.getLastAddConfirmed()) {
+    long lac = rh.getLastAddConfirmed();
+    if (nextEntryId > lac) {
+        // no more entries are added
+        Thread.sleep(1000);
+
+        lac = rh.readLastAddConfirmed().get();
+        continue;
+    }
+
+    long endEntryId = Math.min(lac, nextEntryId + numEntriesPerBatch - 1);
+    LedgerEntries entries = rh.read(nextEntryId, endEntryId).get();
+
+    // process the entries
+
+    nextEntryId = endEntryId + 1;
+}
+
+
+ +

Long Polling

+ +
ReadHandle rh = ...;
+
+long startEntryId = 0L;
+long nextEntryId = startEntryId;
+int numEntriesPerBatch = 4;
+while (!rh.isClosed() || nextEntryId <= rh.getLastAddConfirmed()) {
+    long lac = rh.getLastAddConfirmed();
+    if (nextEntryId > lac) {
+        // no more entries are added
+        try (LastConfirmedAndEntry lacAndEntry = rh.readLastAddConfirmedAndEntry(nextEntryId, 1000, false).getif (lacAndEntry.hasEntry()) {
+                // process the entry
+
+                ++nextEntryId;
+            }
+        }
+    } else {
+        long endEntryId = Math.min(lac, nextEntryId + numEntriesPerBatch - 1);
+        LedgerEntries entries = rh.read(nextEntryId, endEntryId).get();
+
+        // process the entries
+        nextEntryId = endEntryId + 1;
+    }
+}
+
+
+ +

Delete ledgers

+ +

Ledgers can be deleted by using DeleteBuilder.

+ +
BookKeeper bk = ...;
+long ledgerId = ...;
+
+bk.newDeleteLedgerOp()
+    .withLedgerId(ledgerId)
+    .execute()
+    .get();
+
+
+ @@ -975,6 +1251,18 @@ Value = 3, isLeader = Leaders and followers (and a bit of background)
  • Why not just use ZooKeeper?
  • Electing a leader
  • +
  • New API
  • +
  • Create a new client
  • +
  • Create ledgers
  • +
  • Append entries to ledgers
  • +
  • Open ledgers
  • +
  • Recovery vs NoRecovery
  • +
  • Read entries from ledgers
  • +
  • Read unconfirmed entries from ledgers
  • +
  • Tailing Reads
  • +
  • Polling
  • +
  • Long Polling
  • +
  • Delete ledgers
  • diff --git a/content/docs/latest/api/ledger-adv-api/index.html b/content/docs/latest/api/ledger-adv-api/index.html index b4769f1..ebad1fb 100644 --- a/content/docs/latest/api/ledger-adv-api/index.html +++ b/content/docs/latest/api/ledger-adv-api/index.html @@ -511,6 +511,26 @@ If a ledger already exists when users try to create an advanced ledger with same a LedgerExistsException is thrown by the bookkeeper client.

    +

    Creating advanced ledgers can be done throught a fluent API since 4.6.

    + +
    BookKeeper bk = ...;
    +
    +byte[] passwd = "some-passwd".getBytes();
    +
    +WriteHandle wh = bk.newCreateLedgerOp()
    +    .withDigestType(DigestType.CRC32)
    +    .withPassword(passwd)
    +    .withEnsembleSize(3)
    +    .withWriteQuorumSize(3)
    +    .withAckQuorumSize(2)
    +    .makeAdv()                  // convert the create ledger builder to create ledger adv builder
    +    .withLedgerId(1234L)
    +    .execute()                  // execute the creation op
    +    .get();                     // wait for the execution to complete
    +
    +
    +
    +

    Add Entries

    The normal add entries api in advanced ledgers are disabled. Instead, when users want to add entries @@ -522,6 +542,15 @@ to advanced ledgers, an entry id is required to pass in along with the entry dat +

    If you are using the new API, you can do as following:

    + +
    WriteHandle wh = ...;
    +long entryId = ...; // entry id generated externally
    +
    +wh.write(entryId, "Some entry data".getBytes()).get();
    +
    +
    +

    A few notes when using this API:

      -- To stop receiving notification emails like this one, please contact ['"commits@bookkeeper.apache.org" '].