io.sarl.sre.janus.network.services.HazelcastContextService.sarl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of janus.network Show documentation
Show all versions of janus.network Show documentation
Network Module of the Janus Platform
The newest version!
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2024 SARL.io, the Original Authors and Main Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sarl.sre.janus.network.services
import com.hazelcast.core.EntryEvent
import com.hazelcast.core.EntryListener
import com.hazelcast.core.HazelcastInstance
import com.hazelcast.map.IMap
import com.hazelcast.map.MapEvent
import io.bootique.di.Injector
import io.sarl.lang.core.Agent
import io.sarl.sre.janus.KernelScope
import io.sarl.sre.janus.boot.configs.SreConfig
import io.sarl.sre.janus.internal.Factories
import io.sarl.sre.janus.services.context.Context
import io.sarl.sre.janus.services.context.ContextFactory
import io.sarl.sre.janus.services.context.MemoryBasedContextService
import io.sarl.sre.janus.services.logging.LoggingService
import java.text.MessageFormat
import java.util.UUID
import java.util.logging.Logger
import javax.inject.Inject
import javax.inject.Provider
import org.eclipse.xtend.lib.annotations.Accessors
/** Implementation of a context-space service that is connected to remote SRE with the Hazelcast framework.
*
* @author Nicolas Gaud
* @version janus.network 3.0.14.0 20241106-161408
* @mavengroupid io.sarl.sre.janus
* @mavenartifactid janus.network
* @since 0.12
*/
class HazelcastContextService extends MemoryBasedContextService {
/**
* Local Hazelcast instance
*/
@Accessors(PUBLIC_GETTER)
var hazelcastInstance : HazelcastInstance;
/**
* Map linking a context id to its associated default space id. This map must be
* distributed and synchronized all over the network
*/
var defaultSpaces : IMap
/**
* ID of the listener defined on defaultSpaces map
*/
var defaultSpacesListenerID : UUID
@Inject
new(sreConfig : SreConfig, @KernelScope rootContext : Context, logger : LoggingService,
injector : Injector, factory : ContextFactory,
factories : Provider,
hazelcastInstance : HazelcastInstance) {
super(rootContext, logger, injector, factory, factories);
this.hazelcastInstance = hazelcastInstance
/*kernelLogger.log(Level::INFO, "Creating HazelcastContextService")
kernelLogger.log(Level::INFO, "RootID from BootCOnfig: " + sreConfig.boot.rootContextID)
kernelLogger.log(Level::INFO, "RootSpaceID from BootCOnfig: " + sreConfig.boot.rootSpaceID)
kernelLogger.log(Level::INFO, "RootID from rootContext: " + rootContext.ID)
kernelLogger.log(Level::INFO, "RootSpaceID from rootContext: " + rootContext.defaultSpace.spaceID.ID)*/
this.logger.info[Messages::HazelcastContextService_0]
this.defaultSpaces = this.hazelcastInstance.getMap(sreConfig.boot.rootContextID.toString());
// Can't access to that rootContext.defaultSpace
// registering root context, the root context is created differently than other contexts using a call to the ContextFactory directly
this.logger.info[Messages::HazelcastContextService_1]
this.defaultSpaces.putIfAbsent(sreConfig.boot.rootContextID, sreConfig.boot.rootSpaceID);
this.logger.info[Messages::HazelcastContextService_2]
var defaultSpacesListener : EntryListener = new DefaultSpacesMapListener(this)
this.defaultSpacesListenerID = this.defaultSpaces.addEntryListener(defaultSpacesListener, true)
this.logger.info[Messages::HazelcastContextService_3]
}
protected override createLogger(loggingService : LoggingService) : Logger {
loggingService.getKernelModuleLogger(Messages::HazelcastContextService_9)
}
protected def newContextInstance(contextID : UUID, defaultSpaceID : UUID, owner : Agent) : Context {
this.logger.info[MessageFormat::format(Messages::HazelcastContextService_4, contextID, defaultSpaceID)]
this.defaultSpaces.putIfAbsent(contextID, defaultSpaceID);
return super.newContextInstance(contextID, defaultSpaceID, owner)
}
override removeContext(contextID : UUID) : Context {
this.defaultSpaces.remove(contextID);
super.removeContext(contextID)
}
override onStart {
super.onStart
}
protected def ensureDefaultSpaceDefinition(contextID : UUID, defaultSpaceID : UUID, owner : Agent) {
this.logger.info[MessageFormat::format(Messages::HazelcastContextService_5, defaultSpaceID, contextID)]
if (!this.contextInternalStructure.containsKey(contextID)) {
// Assuming the first request we got, is the one corresponding to the default space
super.createContext(contextID, defaultSpaceID, owner);
} else {
if (getContext(contextID).defaultSpace.spaceID.ID != defaultSpaceID) {
this.logger.severe[MessageFormat::format(Messages::HazelcastContextService_6, defaultSpaceID, contextID)]
}
}
}
protected def removeDefaultSpaceDefinition(contextID : UUID, defaultSpaceID : UUID) {
if (getContext(contextID).defaultSpace.isPseudoEmpty()) {
if (getContext(contextID).defaultSpace.spaceID.ID === defaultSpaceID) {
this.logger.info[MessageFormat::format(Messages::HazelcastContextService_7, defaultSpaceID, contextID)]
super.removeContext(contextID)
} else {
this.logger.severe[MessageFormat::format(Messages::HazelcastContextService_8, defaultSpaceID, contextID)]
}
}
}
override onStop {
super.onStop
// TODO check if it is really necessary to clean this distributed map of Contexts, because it will impact other kernels staying active on the network
this.defaultSpaces.clear
this.defaultSpaces.removeEntryListener(this.defaultSpacesListenerID)
if (hazelcastInstance.lifecycleService.running) {
hazelcastInstance.shutdown();
}
}
/** Listener on Hazelcast's shared map events.
*
* @author Nicolas Gaud
* @version janus.network 3.0.14.0 20241106-161408
* @mavengroupid io.sarl.sre.janus
* @mavenartifactid janus.network
* @since 0.12
*/
protected static class DefaultSpacesMapListener implements EntryListener {
var hazelcastContextService : HazelcastContextService
new(hazelcastContextService : HazelcastContextService) {
this.hazelcastContextService = hazelcastContextService
}
def entryAdded(^event : EntryEvent) {
this.hazelcastContextService.ensureDefaultSpaceDefinition(^event.key, ^event.value, null)
}
def entryUpdated(^event : EntryEvent) {
//
}
def entryRemoved(^event : EntryEvent) {
this.hazelcastContextService.removeDefaultSpaceDefinition(^event.key, ^event.value)
}
def entryEvicted(^event : EntryEvent) {
//
}
def entryExpired(^event : EntryEvent) {
//
}
def mapCleared(^event : MapEvent) {
//
}
def mapEvicted(^event : MapEvent) {
//
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy