Class BarrageMessageProducer
- All Implemented Interfaces:
LogOutputAppendable,LivenessManager,LivenessNode,LivenessReferent,NotificationStepReceiver,DynamicNode,Serializable
When a client subscribes initially, a snapshot of the table is sent. The snapshot is obtained using either get() or getPrev() based on the state of the LogicalClock. On each subsequent update, the client is given the deltas between the last update propagation and the next.
When a client changes its subscription it will be sent a snapshot of only the data that the server believes it needs assuming that the client has been respecting the existing subscription. Practically, this means that the server may omit some data if the client's viewport change overlaps the currently recognized viewport.
It is possible to use this replication source to create subscriptions that propagate changes from one UGP to another inside the same JVM.
The client-side counterpart of this is the BarrageMessageReader.
- See Also:
-
Nested Class Summary
Nested Classes -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final booleanWhether a producer compacts its queue of pending deltas before the subscribers' update interval elapses.static final longA producer does not compact unless doing so would free at least this many bytes of chunk storage, however wasteful its queue looks as a fraction.static final doubleA producer compacts once doing so would free this fraction of the chunk storage its pending deltas hold, *and* at leastCOMPACTION_FLOOR_BYTES.static final booleanWhether a propagation phase writes the propagated message once for each group of full subscriptions that would be sent identical bytes, handing each stream of the message to every member of the group as the stream is written, instead of writing the message once per subscription.static final intThe number of rows in every chunk a delta records, except the last of a column.static final longA group of subscriptions sharing one write copies each batch it captures to its members in parallel, on the propagation job scheduler, when the batch's size multiplied by one less than its members reaches this many bytes: the bytes the copies would move off the group's thread.static final StringThe name under which the server binds theSupplier<JobScheduler>that producers write to their subscribers through.static final intThe most threads that write one propagation phase's messages to its subscribers at once, counting the thread that runs the propagation job.static final booleanFields inherited from interface io.deephaven.engine.table.impl.NotificationStepReceiver
NULL_NOTIFICATION_STEP -
Constructor Summary
ConstructorsConstructorDescriptionBarrageMessageProducer(Scheduler scheduler, SessionService.ErrorTransformer errorTransformer, BarrageMessageWriter.Factory streamGeneratorFactory, BaseTable<?> parent, long updateIntervalMs, Runnable onGetSnapshot, @NotNull Supplier<JobScheduler> propagationJobSchedulerFactory) -
Method Summary
Modifier and TypeMethodDescriptionvoidaddParentReference(Object parent) Called on a dependent node to ensure that a strong reference is maintained to any parent object that is required for the proper maintenance and functioning of the dependent.voidaddSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener, BarrageSubscriptionOptions options, @Nullable BitSet columnsToSubscribe, @Nullable RowSet initialViewport, boolean reverseViewport) Add a subscription to this BarrageMessageProducer.protected voiddestroy()Attempt to release (destructively when necessary) resources held by this object.booleanIs the node updating?voidremoveSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener) voidsetLastNotificationStep(long lastNotificationStep) Deliver a last notification step to this receiver.voidsetOnGetSnapshot(Runnable onGetSnapshot, boolean isPreSnap) booleansetRefreshing(boolean refreshing) Change the node's run mode.booleanupdateSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener, @Nullable RowSet newViewport, @Nullable BitSet columnsToSubscribe) booleanupdateSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener, @Nullable RowSet newViewport, @Nullable BitSet columnsToSubscribe, boolean newReverseViewport) Methods inherited from class io.deephaven.engine.liveness.LivenessArtifact
manageWithCurrentScopeMethods inherited from class io.deephaven.engine.liveness.ReferenceCountedLivenessNode
ensureCleanupOnGC, findAnyManagedReferent, forEachManagedReference, getWeakReference, initializeTransientFieldsForLiveness, onReferenceCountAtZero, tryManage, tryUnmanage, tryUnmanageMethods inherited from class io.deephaven.engine.liveness.ReferenceCountedLivenessReferent
dropReference, tryRetainReferenceMethods inherited from class io.deephaven.util.referencecounting.ReferenceCounted
append, decrementReferenceCount, forceReferenceCountToZero, getReferenceCountDebug, incrementReferenceCount, resetReferenceCount, toString, tryDecrementReferenceCount, tryIncrementReferenceCountMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface io.deephaven.engine.liveness.LivenessManager
manage, unmanage, unmanageMethods inherited from interface io.deephaven.engine.liveness.LivenessReferent
dropReference, getReferentDescription, retainReference, tryRetainReferenceMethods inherited from interface io.deephaven.engine.table.impl.NotificationStepReceiver
initializeLastNotificationStep
-
Field Details
-
SUBSCRIPTION_GROWTH_ENABLED
public static final boolean SUBSCRIPTION_GROWTH_ENABLED -
DELTA_CHUNK_SIZE
public static final int DELTA_CHUNK_SIZEThe number of rows in every chunk a delta records, except the last of a column. A configureddeltaChunkSizethat is not a power of two is rounded up to the next one, because that is what lets the copy kernel turn an encoded position into a chunk index and an offset within that chunk with a shift and a mask rather than a division per row;BarrageCopyKernel.copy(io.deephaven.extensions.barrage.chunk.BarrageCopyKernel.Runs, io.deephaven.chunk.WritableChunk<io.deephaven.chunk.attributes.Values>[], io.deephaven.chunk.WritableChunk<io.deephaven.chunk.attributes.Values>[][], io.deephaven.chunk.WritableChunk<io.deephaven.chunk.attributes.Values>[][], int)asserts it. -
COMPACTION_ENABLED
public static final boolean COMPACTION_ENABLEDWhether a producer compacts its queue of pending deltas before the subscribers' update interval elapses. SeeshouldCompact()for the policy, andCOMPACTION_MIN_FREED_FRACTIONandCOMPACTION_FLOOR_BYTESfor its parameters. -
COMPACTION_FLOOR_BYTES
public static final long COMPACTION_FLOOR_BYTESA producer does not compact unless doing so would free at least this many bytes of chunk storage, however wasteful its queue looks as a fraction.This is what stops a stream of tiny deltas from compacting on every cycle. A delta that records a single row still occupies the pool's smallest chunk in each subscribed column, so from the second such delta on the freed fraction sits above 90% forever. That waste is real --
coalescedChunkBytes()measures allocated capacity, so the fraction is reporting chunks a compaction would genuinely release -- but what a fraction cannot say is how little it amounts to: such a queue grows by one smallest chunk per column per cycle, and the interval flushes it before it can grow far. Compacting there copies the whole queue to release one chunk per column, and the job's fixed costs -- scheduling, the run lock, the row set passes, the splice -- are the same as for a compaction that frees gigabytes. The floor makes such a producer wait until the saving is worth a job: at 4 MiB, a 20-byte row compacts about every 7,000 single-row appends and a 300-byte row about every 450. -
COMPACTION_MIN_FREED_FRACTION
public static final double COMPACTION_MIN_FREED_FRACTIONA producer compacts once doing so would free this fraction of the chunk storage its pending deltas hold, *and* at leastCOMPACTION_FLOOR_BYTES. A fraction from 0.0 to 1.0; at the default a compaction has to release half the queue to be worth running.The setting trades processor time against heap. Total copying is at most
(1 - f) / ftimes the data recorded, and the queue reaches about1 / (1 - f)times the footprint it would have if it were coalesced: 0.5 copies once per byte recorded and holds twice that footprint, while 0.9 copies about a ninth as much and holds ten times it. Since reclaiming that heap is the point of compacting at all, raise it only where processor time is the scarcer resource. At 0.0 a producer compacts whenever the floor alone is met; at 1.0 it never compacts, since a queue that would coalesce to nothing still has a delta to coalesce.The value is trusted as configured, not validated. Outside 0.0 to 1.0 it does what the formula in
shouldCompact()says: above one, or NaN, the threshold is unreachable and the producer never compacts; below zero the floor alone decides. -
PROPAGATION_THREADS
public static final int PROPAGATION_THREADSThe most threads that write one propagation phase's messages to its subscribers at once, counting the thread that runs the propagation job. Writing to a subscriber serializes the message into the gRPC transport's buffers, which accept it without waiting for the client, so each write is independent work bounded by the processor; with one thread a phase takes as long as all of its subscribers' writes put together. The threads beyond the job's own come from a pool that every producer in the process shares, and that pool never holds more than this number less one, whatever the number of producers. One or less writes to every subscriber in turn on the job's thread.- See Also:
-
PROPAGATION_JOB_SCHEDULER
The name under which the server binds theSupplier<JobScheduler>that producers write to their subscribers through. Each propagation phase takes aJobSchedulerfrom it and runs its writes as oneinvokeParallelon it, so the schedulers it supplies must be usable from any thread. The server's are backed by a pool sized byPROPAGATION_THREADS.- See Also:
-
DEDUP_IDENTICAL_SUBSCRIBERS
public static final boolean DEDUP_IDENTICAL_SUBSCRIBERSWhether a propagation phase writes the propagated message once for each group of full subscriptions that would be sent identical bytes, handing each stream of the message to every member of the group as the stream is written, instead of writing the message once per subscription. A full subscription joins a group once the subscription has the whole table, and a group's members share their subscription options and columns. Viewport subscriptions, and full subscriptions still growing toward the whole table, are always written alone. -
PARALLEL_COPY_MIN_BYTES
public static final long PARALLEL_COPY_MIN_BYTESA group of subscriptions sharing one write copies each batch it captures to its members in parallel, on the propagation job scheduler, when the batch's size multiplied by one less than its members reaches this many bytes: the bytes the copies would move off the group's thread. Smaller rounds are copied one after another on the group's thread, where handing the copies out would cost more than it saves. WithPROPAGATION_THREADSof one or less, every round is copied on the group's thread.
-
-
Constructor Details
-
BarrageMessageProducer
public BarrageMessageProducer(Scheduler scheduler, SessionService.ErrorTransformer errorTransformer, BarrageMessageWriter.Factory streamGeneratorFactory, BaseTable<?> parent, long updateIntervalMs, Runnable onGetSnapshot, @NotNull @NotNull Supplier<JobScheduler> propagationJobSchedulerFactory)
-
-
Method Details
-
getRowSet
-
getTableDefinition
-
setOnGetSnapshot
-
addSubscription
public void addSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener, BarrageSubscriptionOptions options, @Nullable @Nullable BitSet columnsToSubscribe, @Nullable @Nullable RowSet initialViewport, boolean reverseViewport) Add a subscription to this BarrageMessageProducer.- Parameters:
listener- The listener for this subscriptionoptions- Thesubscription optionscolumnsToSubscribe- The initial columns to subscribe toinitialViewport- Initial viewport, to be owned by the subscription
-
updateSubscription
public boolean updateSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener, @Nullable @Nullable RowSet newViewport, @Nullable @Nullable BitSet columnsToSubscribe) -
updateSubscription
public boolean updateSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener, @Nullable @Nullable RowSet newViewport, @Nullable @Nullable BitSet columnsToSubscribe, boolean newReverseViewport) -
removeSubscription
public void removeSubscription(io.grpc.stub.StreamObserver<BarrageMessageWriter.MessageView> listener) -
constructListener
-
destroy
@OverridingMethodsMustInvokeSuper protected void destroy()Description copied from class:ReferenceCountedLivenessReferentAttempt to release (destructively when necessary) resources held by this object. This may render the object unusable for subsequent operations. Implementations should be sure to call super.destroy().This is intended to only ever be used as a side effect of decreasing the reference count to 0.
- Overrides:
destroyin classReferenceCountedLivenessReferent
-
isRefreshing
public boolean isRefreshing()Description copied from interface:DynamicNodeIs the node updating?- Specified by:
isRefreshingin interfaceDynamicNode- Returns:
- true if the node is updating; false otherwise.
-
setRefreshing
public boolean setRefreshing(boolean refreshing) Description copied from interface:DynamicNodeChange the node's run mode.- Specified by:
setRefreshingin interfaceDynamicNode- Parameters:
refreshing- true to cause the node to update; false otherwise.- Returns:
- new refreshing state
-
addParentReference
Description copied from interface:DynamicNodeCalled on a dependent node to ensure that a strong reference is maintained to any parent object that is required for the proper maintenance and functioning of the dependent. In the most common case, the parent object is a child listener to a parent node. The parent node only keeps a weak reference to its child listener, but the listener maintains a strong reference to the parent node. In this scenario, the only strong reference to the listener (and thus indirectly to the parent node itself) is the reference kept by the dependent node.- Specified by:
addParentReferencein interfaceDynamicNode- Parameters:
parent- A parent of this node
-
setLastNotificationStep
public void setLastNotificationStep(long lastNotificationStep) Description copied from interface:NotificationStepReceiverDeliver a last notification step to this receiver.- Specified by:
setLastNotificationStepin interfaceNotificationStepReceiver- Parameters:
lastNotificationStep- The last notification step to be delivered
-