CORDA-716 Rename one TestClock to DemoClock, and unduplicate code (#1988)

This commit is contained in:
Andrzej Cichocki
2017-11-06 11:13:56 +00:00
committed by GitHub
parent 9baa9037ae
commit 00a9014852
10 changed files with 95 additions and 175 deletions

View File

@ -0,0 +1,61 @@
package net.corda.node.internal
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SingletonSerializationToken
import rx.Observable
import rx.Subscriber
import rx.subscriptions.Subscriptions
import java.time.Clock
import java.time.Instant
import java.time.ZoneId
import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.atomic.AtomicLong
import javax.annotation.concurrent.ThreadSafe
/** A [Clock] that tokenizes itself when serialized, and delegates to an underlying [Clock] implementation. */
abstract class CordaClock : Clock(), SerializeAsToken {
protected abstract val delegateClock: Clock
private val token = SingletonSerializationToken.singletonSerializationToken(javaClass)
override fun toToken(context: SerializeAsTokenContext) = token.registerWithContext(context, this)
override fun instant(): Instant = delegateClock.instant()
override fun getZone(): ZoneId = delegateClock.zone
@Deprecated("Do not use this. Instead seek to use ZonedDateTime methods.", level = DeprecationLevel.ERROR)
override fun withZone(zone: ZoneId) = throw UnsupportedOperationException("Tokenized clock does not support withZone()")
}
@ThreadSafe
class SimpleClock(override val delegateClock: Clock) : CordaClock()
/**
* An abstract class with helper methods for a type of Clock that might have it's concept of "now" adjusted externally.
* e.g. for testing (so unit tests do not have to wait for timeouts in realtime) or for demos and simulations.
*/
abstract class MutableClock(private var _delegateClock: Clock) : CordaClock() {
override var delegateClock
@Synchronized get() = _delegateClock
@Synchronized set(clock) {
_delegateClock = clock
}
private val _version = AtomicLong(0L)
/** This is an observer on the mutation count of this [Clock], which reflects the occurence of mutations. */
val mutations: Observable<Long> by lazy {
Observable.create { subscriber: Subscriber<in Long> ->
if (!subscriber.isUnsubscribed) {
mutationObservers.add(subscriber)
// This is not very intuitive, but subscribing to a subscriber observes unsubscribes.
subscriber.add(Subscriptions.create { mutationObservers.remove(subscriber) })
}
}
}
private val mutationObservers = CopyOnWriteArraySet<Subscriber<in Long>>()
/** Must be called by subclasses when they mutate (but not just with the passage of time as per the "wall clock"). */
protected fun notifyMutationObservers() {
val version = _version.incrementAndGet()
for (observer in mutationObservers) {
if (!observer.isUnsubscribed) {
observer.onNext(version)
}
}
}
}

View File

@ -1,45 +0,0 @@
package net.corda.node.internal
import rx.Observable
import rx.Subscriber
import rx.subscriptions.Subscriptions
import java.time.Clock
import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.atomic.AtomicLong
/**
* An abstract class with helper methods for a type of Clock that might have it's concept of "now"
* adjusted externally.
*
* e.g. for testing (so unit tests do not have to wait for timeouts in realtime) or for demos and simulations.
*/
abstract class MutableClock : Clock() {
private val _version = AtomicLong(0L)
/**
* This is an observer on the mutation count of this [Clock], which reflects the occurence of mutations.
*/
val mutations: Observable<Long> by lazy {
Observable.create({ subscriber: Subscriber<in Long> ->
if (!subscriber.isUnsubscribed) {
mutationObservers.add(subscriber)
// This is not very intuitive, but subscribing to a subscriber observes unsubscribes.
subscriber.add(Subscriptions.create { mutationObservers.remove(subscriber) })
}
})
}
private val mutationObservers = CopyOnWriteArraySet<Subscriber<in Long>>()
/**
* Must be called by subclasses when they mutate (but not just with the passage of time as per the "wall clock").
*/
protected fun notifyMutationObservers() {
val version = _version.incrementAndGet()
for (observer in mutationObservers) {
if (!observer.isUnsubscribed) {
observer.onNext(version)
}
}
}
}

View File

@ -15,7 +15,6 @@ import net.corda.core.utilities.loggerFor
import net.corda.node.VersionInfo
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.node.serialization.NodeClock
import net.corda.node.services.RPCUserService
import net.corda.node.services.RPCUserServiceImpl
import net.corda.node.services.api.SchemaService
@ -25,7 +24,7 @@ import net.corda.node.services.messaging.MessagingService
import net.corda.node.services.messaging.NodeMessagingClient
import net.corda.node.utilities.AddressUtils
import net.corda.node.utilities.AffinityExecutor
import net.corda.node.utilities.TestClock
import net.corda.node.utilities.DemoClock
import net.corda.nodeapi.ArtemisMessagingComponent
import net.corda.nodeapi.internal.ShutdownHook
import net.corda.nodeapi.internal.addShutdownHook
@ -67,7 +66,7 @@ open class Node(configuration: NodeConfiguration,
}
private fun createClock(configuration: NodeConfiguration): Clock {
return if (configuration.useTestClock) TestClock() else NodeClock()
return (if (configuration.useTestClock) ::DemoClock else ::SimpleClock)(Clock.systemUTC())
}
private val sameVmNodeCounter = AtomicInteger()

View File

@ -1,36 +0,0 @@
package net.corda.node.serialization
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SingletonSerializationToken
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
import java.time.Clock
import java.time.Instant
import java.time.ZoneId
import javax.annotation.concurrent.ThreadSafe
/**
* A [Clock] that tokenizes itself when serialized, and delegates to an underlying [Clock] implementation.
*/
@ThreadSafe
class NodeClock(private val delegateClock: Clock = Clock.systemUTC()) : Clock(), SerializeAsToken {
private val token = singletonSerializationToken(javaClass)
override fun toToken(context: SerializeAsTokenContext) = token.registerWithContext(context, this)
override fun instant(): Instant {
return delegateClock.instant()
}
// Do not use this. Instead seek to use ZonedDateTime methods.
override fun withZone(zone: ZoneId): Clock {
throw UnsupportedOperationException("Tokenized clock does not support withZone()")
}
override fun getZone(): ZoneId {
return delegateClock.zone
}
}

View File

@ -0,0 +1,23 @@
package net.corda.node.utilities
import net.corda.core.internal.until
import net.corda.node.internal.MutableClock
import java.time.Clock
import java.time.LocalDate
import javax.annotation.concurrent.ThreadSafe
/** A [Clock] that can have the date advanced for use in demos. */
@ThreadSafe
class DemoClock(delegateClock: Clock) : MutableClock(delegateClock) {
@Synchronized
fun updateDate(date: LocalDate): Boolean {
val currentDate = LocalDate.now(this)
if (currentDate.isBefore(date)) {
// It's ok to increment
delegateClock = Clock.offset(delegateClock, currentDate.atStartOfDay() until date.atStartOfDay())
notifyMutationObservers()
return true
}
return false
}
}

View File

@ -1,49 +0,0 @@
package net.corda.node.utilities
import net.corda.core.internal.until
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
import net.corda.node.internal.MutableClock
import java.time.Clock
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
import javax.annotation.concurrent.ThreadSafe
/**
* A [Clock] that can have the date advanced for use in demos.
*/
@ThreadSafe
class TestClock(private var delegateClock: Clock = Clock.systemUTC()) : MutableClock(), SerializeAsToken {
private val token = singletonSerializationToken(javaClass)
override fun toToken(context: SerializeAsTokenContext) = token.registerWithContext(context, this)
@Synchronized
fun updateDate(date: LocalDate): Boolean {
val currentDate = LocalDate.now(this)
if (currentDate.isBefore(date)) {
// It's ok to increment
delegateClock = Clock.offset(delegateClock, currentDate.atStartOfDay() until date.atStartOfDay())
notifyMutationObservers()
return true
}
return false
}
@Synchronized override fun instant(): Instant {
return delegateClock.instant()
}
// Do not use this. Instead seek to use ZonedDateTime methods.
override fun withZone(zone: ZoneId): Clock {
throw UnsupportedOperationException("Tokenized clock does not support withZone()")
}
@Synchronized override fun getZone(): ZoneId {
return delegateClock.zone
}
}