Enum LiveTableMonitor
- All Implemented Interfaces:
com.fishlib.base.log.LogOutputAppendable
,LiveTableRegistrar
,NotificationQueue
,NotificationQueue.Dependency
,Serializable
,Comparable<LiveTableMonitor>
,java.lang.constant.Constable
public enum LiveTableMonitor extends Enum<LiveTableMonitor> implements LiveTableRegistrar, NotificationQueue, NotificationQueue.Dependency
This class contains a thread which periodically updates a set of monitored LiveTables
at a specified target cycle time. The target cycle time can be configured
to reduce or increase the refresh rate of the monitored tables.
This class can be configured via the following Configuration
property
- LiveTableMonitor.targetcycletime (optional) - The default target cycle time in ms (1000 if not defined)
-
Nested Class Summary
Nested classes/interfaces inherited from interface com.illumon.iris.db.tables.live.NotificationQueue
NotificationQueue.Dependency, NotificationQueue.IndexUpdateNotification, NotificationQueue.Notification
-
Enum Constant Summary
Enum Constants Enum Constant Description DEFAULT
-
Method Summary
Modifier and Type Method Description void
addNotification(NotificationQueue.Notification notification)
Enqueue a notification to be flushed according to its priority.void
addNotifications(Collection<? extends NotificationQueue.Notification> notifications)
Enqueue a collection of notifications to be flushed.void
addTable(LiveTable table)
Add a table to the list of tables to refresh and mark it asrefreshing
if it was aDynamicNode
.com.fishlib.base.log.LogOutput
append(com.fishlib.base.log.LogOutput logOutput)
void
checkInitiateTableOperation()
If we are establishing a new table operation, on a refreshing table without the LiveTableMonitor lock; then we are likely committing a grievous error, but one that will only occasionally result in us getting the wrong answer or if we are lucky an assertion.void
completeCycleForUnitTests()
Do the second half of the update cycle, including flushing notifications, and completing theLogicalClock
update cycle.<R> R
computeLocked(com.fishlib.base.Function.Nullary<R> r)
void
doLocked(com.fishlib.base.Procedure.Nullary r)
<T> T
doLocked(Supplier<T> r)
void
doLockedInterruptible(com.fishlib.base.Procedure.Nullary r)
<T> T
doLockedInterruptible(Supplier<T> r)
<T extends Exception>
voiddoLockedThrowing(com.fishlib.base.Procedure.ThrowingNullary<T> r)
Deprecated.void
doUnchecked(Runnable runnable)
Execute the supplied code while table operations are unchecked.<T> T
doUnchecked(Supplier<T> supplier)
Execute the supplied code while table operations are unchecked.void
enableUnitTestMode()
Enable unit test mode.AwareFunctionalLock
exclusiveLock()
Get the exclusive lock for thisLiveTableMonitor
.void
flushAllNormalNotificationsForUnitTests()
Flush all the normal notifications from the LTM queue.Runnable
flushAllNormalNotificationsForUnitTests(BooleanSupplier done, long timeoutMillis)
Flush all the normal notifications from the LTM queue, continuing untildone
returnstrue
.boolean
flushOneNotificationForUnitTests()
Flush a single notification from the LTM queue.boolean
flushOneNotificationForUnitTestsInternal()
boolean
getCheckTableOperations()
Should this thread check table operations?long
getTargetCycleTime()
Get the target period between refresh cycles.int
getUpdateThreads()
Retrieve the number of update threads.int
getWatchDogMillis()
Get the current watchdogtimeout
value.boolean
isLockedByCurrentThread()
Deprecated.boolean
isRefreshThread()
Test if this thread is part of our refresh thread executor service.void
lock()
Deprecated.Prefer {exclusiveLock()
}.lock().void
lockInterruptibly()
Deprecated.Prefer {exclusiveLock()
}.lockInterruptibly().com.fishlib.io.log.LogEntry
logDependencies(Object identity)
boolean
maybeAddNotification(NotificationQueue.Notification notification, long deliveryStep)
Add a notification for this NotificationQueue to deliver (by invoking its run() method), iff the delivery step is the current step and the update cycle for that step is still in process.void
maybeRefreshTable(LiveTable liveTable, boolean onlyIfHaveLock)
Acquire the exclusive lock if necessary and do a refresh ofliveTable
on this thread if it is registered with this LTM.Condition
newCondition()
Deprecated.Prefer {exclusiveLock()
}.newCondition().void
refreshLiveTableForUnitTests(LiveTable liveTable)
Refresh aLiveTable
on a simulated LTM refresh thread, rather than this thread.void
removeTable(LiveTable liveTable)
Remove a table from this registrar.void
removeTables(Collection<LiveTable> tablesToRemove)
Remove a collection of tables from the list of refreshing tables.void
requestRefresh(LiveTable liveTable)
Request a refresh for a singlelive table
, which must already be registered with this LiveTableMonitor.void
requestSignal(Condition liveTableMonitorCondition)
void
resetCycleTime()
Resets the refresh cycle time to the default target configured via the LiveTableMonitor.targetcycletime property.void
resetForUnitTests()
Clear all monitored tables and enqueued notifications to supportunit-tests
.void
resetForUnitTests(boolean randomizedNotifications, int seed, int maxRandomizedThreadCount, int notificationStartDelay, int notificationAdditionDelay)
void
rootRefreshCompleteForUnitTests()
Mark the root tables satisfied within a unit test.<T extends Exception>
voidrunWithinUnitTestCycle(FunctionalInterfaces.ThrowingRunnable<T> runnable)
Execute the given runnable wrapped withstartCycleForUnitTests()
andcompleteCycleForUnitTests()
.boolean
satisfied(long step)
Is this ancestor satisfied? Note that this method must be safe to call on any thread.boolean
setCheckTableOperations(boolean value)
If you know that the table operations you are performing are indeed safe, then call this method with false to disable table operation checking.void
setTargetCycleTime(long cycleTime)
Set the target clock time between refresh cycles.void
setWatchDogMillis(int watchDogMillis)
Enable the loop watchdog with the specified timeout.void
setWatchDogTimeoutProcedure(LongConsumer procedure)
Set the procedure to be called when the watchdogtimes out
.AwareFunctionalLock
sharedLock()
Get the shared lock for thisLiveTableMonitor
.void
start()
Start the table refresh thread.void
startCycleForUnitTests()
Begin the nextupdate cycle
while inunit-test
mode.void
startCycleForUnitTests(boolean rootsSatisfied)
Begin the nextupdate cycle
while inunit-test
mode.String
toString()
boolean
tryLock()
Deprecated.Prefer {exclusiveLock()
}.tryLock().boolean
tryLock(long time, TimeUnit unit)
Deprecated.Prefer {exclusiveLock()
}.tryLock().void
unlock()
Deprecated.Prefer {exclusiveLock()
}.unlock().static LiveTableMonitor
valueOf(String name)
Returns the enum constant of this type with the specified name.static LiveTableMonitor[]
values()
Returns an array containing the constants of this enum type, in the order they are declared.void
wakeRefreshThreadForUnitTests()
If the refresh thread is waiting influshNormalNotificationsAndCompleteCycle()
orflushAllNormalNotificationsForUnitTests(BooleanSupplier, long)
, wake it up.
-
Enum Constant Details
-
Method Details
-
values
Returns an array containing the constants of this enum type, in the order they are declared.- Returns:
- an array containing the constants of this enum type, in the order they are declared
-
valueOf
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)- Parameters:
name
- the name of the enum constant to be returned.- Returns:
- the enum constant with the specified name
- Throws:
IllegalArgumentException
- if this enum type has no constant with the specified nameNullPointerException
- if the argument is null
-
append
public com.fishlib.base.log.LogOutput append(@NotNull com.fishlib.base.log.LogOutput logOutput)- Specified by:
append
in interfacecom.fishlib.base.log.LogOutputAppendable
-
toString
- Overrides:
toString
in classEnum<LiveTableMonitor>
-
getUpdateThreads
public int getUpdateThreads()Retrieve the number of update threads.The LiveTableMonitor has a configurable number of update processing threads. The number of threads is exposed in your method to enable you to partition a query based on the number of threads.
- Returns:
- the number of update threads configured.
-
sharedLock
Get the shared lock for this
LiveTableMonitor
.Using this lock will prevent refresh processing from proceeding concurrently, but will allow other read-only processing to proceed.
The shared lock implementation is expected to support reentrance.
This lock does not support
Lock.newCondition()
. Use the exclusive lock if you need to wait on events that are driven by refresh processing.- Returns:
- The shared lock for this
LiveTableMonitor
-
exclusiveLock
Get the exclusive lock for this
LiveTableMonitor
.Using this lock will prevent refresh or read-only processing from proceeding concurrently.
The exclusive lock implementation is expected to support reentrance.
Note that using the exclusive lock while the shared lock is held by the current thread will result in exceptions, as lock upgrade is not supported.
This lock does support
Lock.newCondition()
.- Returns:
- The exclusive lock for this
LiveTableMonitor
-
lock
Deprecated.Prefer {exclusiveLock()
}.lock(). -
lockInterruptibly
Deprecated.Prefer {exclusiveLock()
}.lockInterruptibly().- Throws:
InterruptedException
-
tryLock
Deprecated.Prefer {exclusiveLock()
}.tryLock(). -
tryLock
@Deprecated public final boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedExceptionDeprecated.Prefer {exclusiveLock()
}.tryLock().- Throws:
InterruptedException
-
unlock
Deprecated.Prefer {exclusiveLock()
}.unlock(). -
newCondition
Deprecated.Prefer {exclusiveLock()
}.newCondition(). -
isLockedByCurrentThread
Deprecated.Test if this thread holds the lock (exclusively).- Returns:
- Whether the current thread holds the lock exclusively
-
doLocked
Deprecated.Safely execute the supplied code while holding the lock.- Parameters:
r
- the stuff to run- Returns:
- the result of the stuff to run
-
doLockedInterruptible
@Deprecated public final <T> T doLockedInterruptible(@NotNull Supplier<T> r) throws InterruptedExceptionDeprecated.Safely execute the supplied code while holding the lock. Lock acquisition may be interrupted.- Parameters:
r
- the stuff to run- Returns:
- the result of the stuff to run
- Throws:
InterruptedException
- if the thread was interrupted attempting to acquire the lock
-
doLocked
Deprecated.Safely execute the supplied code while holding the lock.- Parameters:
r
- the stuff to run
-
computeLocked
Deprecated.Safely execute the supplied function while holding the lock.- Parameters:
r
- the function to run- Returns:
- the return value of the function
-
doLockedInterruptible
@Deprecated public final void doLockedInterruptible(@NotNull com.fishlib.base.Procedure.Nullary r) throws InterruptedExceptionDeprecated.Safely execute the supplied code while holding the lock.- Parameters:
r
- the stuff to run- Throws:
InterruptedException
-
doLockedThrowing
@Deprecated public final <T extends Exception> void doLockedThrowing(@NotNull com.fishlib.base.Procedure.ThrowingNullary<T> r) throws T extends ExceptionDeprecated.Safely execute the supplied code while holding the lock.- Parameters:
r
- the stuff to run- Throws:
T
- exception of type TT extends Exception
-
isRefreshThread
public boolean isRefreshThread()Test if this thread is part of our refresh thread executor service.- Returns:
- whether this is one of our refresh threads.
-
checkInitiateTableOperation
public void checkInitiateTableOperation()If we are establishing a new table operation, on a refreshing table without the LiveTableMonitor lock; then we are likely committing a grievous error, but one that will only occasionally result in us getting the wrong answer or if we are lucky an assertion. This method is called from various query operations that should not be established without the LTM lock.
The refresh thread pool threads are allowed to instantiate operations, even though that thread does not have the lock; because they are protected by the main refresh thread and dependency tracking.
If you are sure that you know what you are doing better than the query engine, you may call
setCheckTableOperations(boolean)
to set a thread local variable bypassing this check. -
setCheckTableOperations
public boolean setCheckTableOperations(boolean value)If you know that the table operations you are performing are indeed safe, then call this method with false to disable table operation checking. Conversely, if you want to enforce checking even if the configuration disagrees; call it with true.- Parameters:
value
- the new value of check table operations- Returns:
- the old value of check table operations
-
doUnchecked
Execute the supplied code while table operations are unchecked.- Parameters:
supplier
- the function to run- Returns:
- the result of supplier
-
doUnchecked
Execute the supplied code while table operations are unchecked.- Parameters:
runnable
- the function to run
-
getCheckTableOperations
public boolean getCheckTableOperations()Should this thread check table operations?- Returns:
- if we should check table operations.
-
setTargetCycleTime
public void setTargetCycleTime(long cycleTime)Set the target clock time between refresh cycles.
Can be reset to default via
resetCycleTime()
- Parameters:
cycleTime
- The target time between refreshes in milliseconds- ImplNote:
- Any cycle time < 0 will be clamped to 0.
-
getTargetCycleTime
public long getTargetCycleTime()Get the target period between refresh cycles.- Returns:
- The
current
minimum cycle time
-
resetCycleTime
public void resetCycleTime()Resets the refresh cycle time to the default target configured via the LiveTableMonitor.targetcycletime property.- ImplNote:
- If the LiveTableMonitor.targetcycletime property is not set, this value defaults to 1000ms.
-
enableUnitTestMode
public void enableUnitTestMode()Enable unit test mode.
In this mode calls to
addTable(LiveTable)
will only mark tables asrefreshing
. Additionallystart()
may not be called. -
setWatchDogMillis
public void setWatchDogMillis(int watchDogMillis)Enable the loop watchdog with the specified timeout. A value of 0 disables the watchdog.- Parameters:
watchDogMillis
- The time in milliseconds to set the watchdog, or 0 to disable.- ImplNote:
- Any timeout < 0 will be clamped to 0.
-
getWatchDogMillis
public int getWatchDogMillis()Get the current watchdogtimeout
value.- Returns:
- The current timeout for the watchdog, 0 for disabled
-
setWatchDogTimeoutProcedure
Set the procedure to be called when the watchdogtimes out
.- Parameters:
procedure
- The procedure to call
-
requestSignal
-
start
public void start()Start the table refresh thread.- ImplNote:
- Must not be in
unit test
mode.
-
addTable
Add a table to the list of tables to refresh and mark it asrefreshing
if it was aDynamicNode
.- Specified by:
addTable
in interfaceLiveTableRegistrar
- Parameters:
table
- The table to be added to the refresh list- ImplNote:
- This will do nothing in
unit test
mode other than mark the table as refreshing.
-
removeTable
Description copied from interface:LiveTableRegistrar
Remove a table from this registrar.- Specified by:
removeTable
in interfaceLiveTableRegistrar
- Parameters:
liveTable
- The table to remove
-
removeTables
Remove a collection of tables from the list of refreshing tables.- Parameters:
tablesToRemove
- The tables to remove from the list of refreshing tables- ImplNote:
- This will not set the tables as
non-refreshing
.
-
addNotification
Enqueue a notification to be flushed according to its priority. Non-terminal notifications should only be enqueued during the updating phase of a cycle. That is, they should be enqueued from aLiveTable.refresh()
or subsequent notification delivery.- Specified by:
addNotification
in interfaceNotificationQueue
- Parameters:
notification
- The notification to enqueue- See Also:
NotificationQueue.Notification.isTerminal()
,LogicalClock.State
-
maybeAddNotification
public boolean maybeAddNotification(@NotNull NotificationQueue.Notification notification, long deliveryStep)Description copied from interface:NotificationQueue
Add a notification for this NotificationQueue to deliver (by invoking its run() method), iff the delivery step is the current step and the update cycle for that step is still in process. This is only supported for non-terminal notifications.- Specified by:
maybeAddNotification
in interfaceNotificationQueue
- Parameters:
notification
- The notification to adddeliveryStep
- The step to deliver this notification on
-
satisfied
public boolean satisfied(long step)Description copied from interface:NotificationQueue.Dependency
Is this ancestor satisfied? Note that this method must be safe to call on any thread.- Specified by:
satisfied
in interfaceNotificationQueue.Dependency
- Parameters:
step
- The step for which we are testing satisfaction- Returns:
- Whether the dependency is satisfied on
step
(and will not fire subsequent notifications)
-
addNotifications
public void addNotifications(@NotNull Collection<? extends NotificationQueue.Notification> notifications)Enqueue a collection of notifications to be flushed.- Parameters:
notifications
- The notification to enqueue- See Also:
addNotification(Notification)
-
maybeRefreshTable
Acquire the exclusive lock if necessary and do a refresh ofliveTable
on this thread if it is registered with this LTM.- Specified by:
maybeRefreshTable
in interfaceLiveTableRegistrar
- Parameters:
liveTable
- TheLiveTable
that we would like to refreshonlyIfHaveLock
- If true, check that the lock is held first and do nothing if it is not
-
requestRefresh
Request a refresh for a single
live table
, which must already be registered with this LiveTableMonitor.The update will occur on the LTM thread, but will not necessarily wait for the next scheduled cycle.
- Specified by:
requestRefresh
in interfaceLiveTableRegistrar
- Parameters:
liveTable
- Thelive table
to refresh
-
resetForUnitTests
Clear all monitored tables and enqueued notifications to supportunit-tests
. -
resetForUnitTests
@TestUseOnly public void resetForUnitTests(boolean randomizedNotifications, int seed, int maxRandomizedThreadCount, int notificationStartDelay, int notificationAdditionDelay) -
startCycleForUnitTests
Begin the nextupdate cycle
while inunit-test
mode. Note that this happens on a simulated LTM refresh thread, rather than this thread. -
startCycleForUnitTests
Begin the nextupdate cycle
while inunit-test
mode. Note that this happens on a simulated LTM refresh thread, rather than this thread.- Parameters:
rootsSatisfied
- if true, then the roots will be marked as satisfied, if false; then you must manually callrootRefreshCompleteForUnitTests()
-
rootRefreshCompleteForUnitTests
Mark the root tables satisfied within a unit test. -
completeCycleForUnitTests
Do the second half of the update cycle, including flushing notifications, and completing theLogicalClock
update cycle. Note that this happens on a simulated LTM refresh thread, rather than this thread. -
runWithinUnitTestCycle
@TestUseOnly public <T extends Exception> void runWithinUnitTestCycle(FunctionalInterfaces.ThrowingRunnable<T> runnable) throws T extends ExceptionExecute the given runnable wrapped withstartCycleForUnitTests()
andcompleteCycleForUnitTests()
. Note that the runnable is run on the current thread.- Parameters:
runnable
- the runnable to execute.- Throws:
T extends Exception
-
refreshLiveTableForUnitTests
Refresh aLiveTable
on a simulated LTM refresh thread, rather than this thread.- Parameters:
liveTable
- TheLiveTable
to refresh
-
flushOneNotificationForUnitTests
Flush a single notification from the LTM queue. Note that this happens on a simulated LTM refresh thread, rather than this thread.- Returns:
- whether a notification was found in the queue
-
flushOneNotificationForUnitTestsInternal
-
flushAllNormalNotificationsForUnitTests
Flush all the normal notifications from the LTM queue. Note that the flushing happens on a simulated LTM refresh thread, rather than this thread. -
flushAllNormalNotificationsForUnitTests
@TestUseOnly public Runnable flushAllNormalNotificationsForUnitTests(@NotNull BooleanSupplier done, long timeoutMillis)Flush all the normal notifications from the LTM queue, continuing untildone
returnstrue
. Note that the flushing happens on a simulated LTM refresh thread, rather than this thread.- Parameters:
done
- Function to determine when we can stop waiting for new notifications- Returns:
- A Runnable that may be used to wait for the concurrent flush job to complete
-
wakeRefreshThreadForUnitTests
If the refresh thread is waiting influshNormalNotificationsAndCompleteCycle()
orflushAllNormalNotificationsForUnitTests(BooleanSupplier, long)
, wake it up. -
logDependencies
-