merlimat opened a new pull request, #4883:
URL: https://github.com/apache/bookkeeper/pull/4883

   Descriptions of the changes in this PR:
   
   Adds an opt-in inline execution path to `SingleThreadExecutor` and uses it 
for reads issued on a writable ledger handle from the ledger's own worker 
thread, which until now were queued back onto that same thread.
   
   ### Motivation
   
   `LedgerHandle` runs its work on one `OrderedExecutor` thread per ledger. 
When the caller is already on that thread, going through `execute()` costs a 
queue round trip on the same thread and delays the request behind whatever else 
is queued. With #4881 an application can put its own per-ledger work on that 
same thread (Pulsar's managed ledger runs on `chooseThread(mlName)`), which 
makes this the common case for tailing reads issued from the managed-ledger 
thread.
   
   Adds already run `PendingAddOp.initiate()` inline on the caller's thread and 
reads on read-only handles already bypass the executor ("avoids a 
context-switch to OSE thread"); reads on writable handles were the remaining 
same-thread hop.
   
   A blanket shortcut inside `execute()` would change the executor's contract, 
so the shortcut is opt-in: a task submitted from the executor's own thread runs 
before the tasks already queued and nested inside the submitting task, which is 
only acceptable where the caller knows it. This follows the pattern of 
`OrderedGenericCallback` (inline when already on the thread selected by the 
key) and Netty's `inEventLoop()`.
   
   ### Changes
   
   - `SingleThreadExecutor.isCurrentThread()` and `executeOrRun(Runnable)`: 
runs the task inline when called from the executor's thread, otherwise 
delegates to `execute`. Inline runs go through the same `safeRunTask` as queued 
tasks, so failures are logged and counted the same way; the queued path 
(`runQueuedTask`) only adds the pending-count decrement that pairs with the 
enqueue-time increment of bounded queues. Submitted and completed counters 
include inline runs, so `getQueuedTasksCount()` stays consistent.
   - `LedgerHandle.executor` is now typed as `SingleThreadExecutor` (cast at 
construction): the client's main worker pool is a plain `OrderedExecutor`, 
whose threads are `SingleThreadExecutor` instances (`OrderedScheduler` 
overrides the per-thread executor with a scheduled-executor wrapper, so 
`chooseThread` itself cannot be declared to return the concrete type). The two 
read submission sites for writable handles, in `asyncReadEntriesInternal` and 
`readEntriesInternalAsync`, call `executor.executeOrRun(op)`.
   - Test fixtures: `MockClientContext` and `MockBookKeeperTestCase` handed the 
client an `OrderedScheduler` as its main worker pool; they now provide an 
`OrderedExecutor`, with the mock bookie client dispatching on that same pool 
(the scheduler stays for timers). That also makes the mock bookie callbacks and 
the handle share one thread per ledger, as in production.
   - Applications holding a worker thread from 
`OrderedExecutor.chooseThread(...)` can use `isCurrentThread()` / 
`executeOrRun` for their own re-dispatches; the Pulsar follow-up is 
`OpAddEntry.addComplete`, which re-enqueues onto the managed-ledger thread it 
is already on once #4881 is in use.
   
   ### Verification
   
   - `TestSingleThreadExecutor`: `isCurrentThread` from both sides; 
`executeOrRun` from the executor thread runs before returning and ahead of an 
already queued task, with consistent counters; from another thread it is queued 
and runs on the executor thread; an inline failure is isolated from the 
submitting task and counted as failed.
   - New `LedgerHandleInlineReadTest` (mock bookies): a read issued on the 
ledger thread reaches the bookie client before `readAsync` / `asyncReadEntries` 
return, on that same thread; a read from another thread is still queued onto 
the ledger thread.
   - Existing tests: `TestOrderedExecutor`, `BookieReadWriteTest`, 
`TestSpeculativeRead`, `TestSpeculativeBatchRead`, `TestBatchedRead`, 
`TestReadLastConfirmedAndEntry`, `TestReadLastConfirmedLongPoll`, 
`BookKeeperTest`, and the suites built on the changed fixtures 
(`HandleFailuresTest`, `LedgerClose2Test`, `LedgerRecovery2Test`, 
`LedgerRecoveryTest`, `DeferredSyncTest`, `TestMaxEnsembleChangeNum`, 
`BookKeeperBuildersTest`, `BookKeeperBuildersOpenLedgerTest`, 
`LoggerContextTest`, `BookKeeperApiTest`, `MockBookKeeperTest`, 
`TestLedgerFragmentReplicationWithMock`): all green, except 
`testSequenceReadLocalEnsemble` in the two speculative-read classes, which 
fails on the development machine on any branch because its hostname does not 
resolve (the local placement policy then derives a loopback bookie address that 
the client-side configuration rejects while constructing the test client).
   - `checkstyle:check` and `spotbugs:check` pass on bookkeeper-common and 
bookkeeper-server.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to