Node refactoring: move building advertised services before SMM initialisation - the node doesn't need to maintain a reference to a uniqueness provider anymore.

Extract parts of start() into separate methods.
This commit is contained in:
Andrius Dagys 2017-02-21 17:24:09 +00:00
parent 8b1864e07c
commit 2b3200207a

View File

@ -152,7 +152,6 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
lateinit var keyManagement: KeyManagementService
var inNodeNetworkMapService: NetworkMapService? = null
var inNodeNotaryService: NotaryService? = null
var uniquenessProvider: UniquenessProvider? = null
lateinit var identity: IdentityService
lateinit var net: MessagingServiceInternal
lateinit var netMapCache: NetworkMapCache
@ -200,38 +199,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
// Do all of this in a database transaction so anything that might need a connection has one.
initialiseDatabasePersistence {
val storageServices = initialiseStorageService(configuration.baseDirectory)
storage = storageServices.first
checkpointStorage = storageServices.second
netMapCache = InMemoryNetworkMapCache()
net = makeMessagingService()
schemas = makeSchemaService()
vault = makeVaultService(configuration.dataSourceProperties)
info = makeInfo()
identity = makeIdentityService()
// Place the long term identity key in the KMS. Eventually, this is likely going to be separated again because
// the KMS is meant for derived temporary keys used in transactions, and we're not supposed to sign things with
// the identity key. But the infrastructure to make that easy isn't here yet.
keyManagement = makeKeyManagementService()
flowLogicFactory = initialiseFlowLogicFactory()
scheduler = NodeSchedulerService(database, services, flowLogicFactory, unfinishedSchedules = busyNodeLatch)
val tokenizableServices = mutableListOf(storage, net, vault, keyManagement, identity, platformClock, scheduler)
customServices.clear()
customServices.addAll(buildPluginServices(tokenizableServices))
val uploaders: List<FileUploader> = listOf(storageServices.first.attachments as NodeAttachmentService) +
customServices.filterIsInstance(AcceptsFileUpload::class.java)
(storage as StorageServiceImpl).initUploaders(uploaders)
// TODO: uniquenessProvider creation should be inside makeNotaryService(), but notary service initialisation
// depends on smm, while smm depends on tokenizableServices, which uniquenessProvider is part of
advertisedServices.singleOrNull { it.type.isNotary() }?.let {
uniquenessProvider = makeUniquenessProvider(it.type)
tokenizableServices.add(uniquenessProvider!!)
}
val tokenizableServices = makeServices()
smm = StateMachineManager(services,
listOf(tokenizableServices),
@ -248,13 +216,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
}
}
buildAdvertisedServices()
// TODO: this model might change but for now it provides some de-coupling
// Add vault observers
CashBalanceAsMetricsObserver(services, database)
ScheduledActivityObserver(services)
HibernateObserver(services)
makeVaultObservers()
checkpointStorage.forEach {
isPreviousCheckpointsPresent = true
@ -273,6 +235,50 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
return this
}
/**
* Builds node internal, advertised, and plugin services.
* Returns a list of tokenizable services to be added to the serialisation context.
*/
private fun makeServices(): MutableList<Any> {
val storageServices = initialiseStorageService(configuration.baseDirectory)
storage = storageServices.first
checkpointStorage = storageServices.second
netMapCache = InMemoryNetworkMapCache()
net = makeMessagingService()
schemas = makeSchemaService()
vault = makeVaultService(configuration.dataSourceProperties)
info = makeInfo()
identity = makeIdentityService()
// Place the long term identity key in the KMS. Eventually, this is likely going to be separated again because
// the KMS is meant for derived temporary keys used in transactions, and we're not supposed to sign things with
// the identity key. But the infrastructure to make that easy isn't here yet.
keyManagement = makeKeyManagementService()
flowLogicFactory = initialiseFlowLogicFactory()
scheduler = NodeSchedulerService(database, services, flowLogicFactory, unfinishedSchedules = busyNodeLatch)
val tokenizableServices = mutableListOf(storage, net, vault, keyManagement, identity, platformClock, scheduler)
makeAdvertisedServices(tokenizableServices)
customServices.clear()
customServices.addAll(makePluginServices(tokenizableServices))
initUploaders(storageServices)
return tokenizableServices
}
private fun initUploaders(storageServices: Pair<TxWritableStorageService, CheckpointStorage>) {
val uploaders: List<FileUploader> = listOf(storageServices.first.attachments as NodeAttachmentService) +
customServices.filterIsInstance(AcceptsFileUpload::class.java)
(storage as StorageServiceImpl).initUploaders(uploaders)
}
private fun makeVaultObservers() {
CashBalanceAsMetricsObserver(services, database)
ScheduledActivityObserver(services)
HibernateObserver(services)
}
private fun makeInfo(): NodeInfo {
val advertisedServiceEntries = makeServiceEntries()
val legalIdentity = obtainLegalIdentity()
@ -345,7 +351,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
return FlowLogicRefFactory(flowWhitelist)
}
private fun buildPluginServices(tokenizableServices: MutableList<Any>): List<Any> {
private fun makePluginServices(tokenizableServices: MutableList<Any>): List<Any> {
val pluginServices = pluginRegistries.flatMap { x -> x.servicePlugins }
val serviceList = mutableListOf<Any>()
for (serviceConstructor in pluginServices) {
@ -364,13 +370,13 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
return this
}
private fun buildAdvertisedServices() {
private fun makeAdvertisedServices(tokenizableServices: MutableList<Any>) {
val serviceTypes = info.advertisedServices.map { it.info.type }
if (NetworkMapService.type in serviceTypes) makeNetworkMapService()
val notaryServiceType = serviceTypes.singleOrNull { it.isNotary() }
if (notaryServiceType != null) {
inNodeNotaryService = makeNotaryService(notaryServiceType)
inNodeNotaryService = makeNotaryService(notaryServiceType, tokenizableServices)
}
}
@ -426,13 +432,15 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
inNodeNetworkMapService = PersistentNetworkMapService(services)
}
open protected fun makeNotaryService(type: ServiceType): NotaryService {
open protected fun makeNotaryService(type: ServiceType, tokenizableServices: MutableList<Any>): NotaryService {
val timestampChecker = TimestampChecker(platformClock, 30.seconds)
val uniquenessProvider = makeUniquenessProvider(type)
tokenizableServices.add(uniquenessProvider)
return when (type) {
SimpleNotaryService.type -> SimpleNotaryService(services, timestampChecker, uniquenessProvider!!)
ValidatingNotaryService.type -> ValidatingNotaryService(services, timestampChecker, uniquenessProvider!!)
RaftValidatingNotaryService.type -> RaftValidatingNotaryService(services, timestampChecker, uniquenessProvider!! as RaftUniquenessProvider)
SimpleNotaryService.type -> SimpleNotaryService(services, timestampChecker, uniquenessProvider)
ValidatingNotaryService.type -> ValidatingNotaryService(services, timestampChecker, uniquenessProvider)
RaftValidatingNotaryService.type -> RaftValidatingNotaryService(services, timestampChecker, uniquenessProvider as RaftUniquenessProvider)
else -> {
throw IllegalArgumentException("Notary type ${type.id} is not handled by makeNotaryService.")
}