Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
467 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
sre/io.janusproject/io.janusproject.network/META-INF/services/io.bootique.BQModuleProvider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
io.sarl.sre.network.totoprovider | ||
io.sarl.sre.network.NetworkModuleProvider | ||
|
||
|
51 changes: 51 additions & 0 deletions
51
...janusproject/io.janusproject.network/src/main/sarl/io/sarl/sre/network/NetworkModule.sarl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,56 @@ | ||
package io.sarl.sre.network | ||
|
||
import com.google.inject.AbstractModule | ||
import com.google.inject.Module | ||
import com.google.inject.Provides | ||
import com.hazelcast.core.Hazelcast | ||
import com.hazelcast.core.HazelcastInstance | ||
import io.bootique.BQModule | ||
import io.bootique.BQModuleProvider | ||
import io.sarl.sre.boot.internal.services.ContextServiceModule | ||
import io.sarl.sre.network.services.HazelcastContextService | ||
import io.sarl.sre.network.services.HazelcastEventTransportService | ||
import io.sarl.sre.network.services.HazelcastSpaceRepository | ||
import io.sarl.sre.services.context.ContextService | ||
import io.sarl.sre.services.context.SpaceRepository | ||
import io.sarl.sre.spaces.EventTransportService | ||
import java.util.Collection | ||
import javax.inject.Singleton | ||
|
||
class NetworkModule extends AbstractModule { | ||
|
||
protected override configure { | ||
typeof(SpaceRepository).bind.to(typeof(HazelcastSpaceRepository)) | ||
typeof(ContextService).bind.to(typeof(HazelcastContextService)).in(typeof(Singleton)) | ||
typeof(EventTransportService).bind.to(typeof(HazelcastEventTransportService)).in(typeof(Singleton)) | ||
|
||
} | ||
|
||
@Provides | ||
@Singleton | ||
def provideHazelcastInstance() : HazelcastInstance { | ||
Hazelcast.newHazelcastInstance | ||
} | ||
|
||
|
||
} | ||
|
||
class NetworkModuleProvider implements BQModuleProvider { | ||
|
||
override module : Module { | ||
return new NetworkModule | ||
} | ||
|
||
override moduleBuilder : BQModule.Builder { | ||
return BQModule::builder(module).overrides(overrides).providerName(name).configs(configs).description( | ||
"First version of SRE Network Module"); | ||
} | ||
|
||
override overrides : Collection<Class<? extends Module>> { | ||
#[ContextServiceModule] | ||
} | ||
|
||
} | ||
|
||
|
||
|
137 changes: 132 additions & 5 deletions
137
...usproject.network/src/main/sarl/io/sarl/sre/network/services/HazelcastContextService.sarl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,145 @@ | ||
package io.sarl.sre.network.services | ||
|
||
import com.google.inject.Injector | ||
import com.hazelcast.core.EntryEvent | ||
import com.hazelcast.core.EntryListener | ||
import com.hazelcast.core.HazelcastInstance | ||
import com.hazelcast.map.IMap | ||
import io.sarl.lang.core.SpaceID | ||
import com.hazelcast.map.MapEvent | ||
import io.sarl.lang.core.Agent | ||
import io.sarl.sre.KernelScope | ||
import io.sarl.sre.boot.configs.SreConfig | ||
import io.sarl.sre.services.context.Context | ||
import io.sarl.sre.services.context.ContextFactory | ||
import io.sarl.sre.services.context.MemoryBasedContextService | ||
import io.sarl.sre.services.logging.LoggingService | ||
import java.util.UUID | ||
import java.util.logging.Level | ||
import java.util.logging.Logger | ||
import javax.inject.Inject | ||
|
||
class HazelcastContextService extends MemoryBasedContextService { | ||
|
||
/** | ||
* Local Hazelcast instance | ||
*/ | ||
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<UUID, SpaceID> | ||
|
||
|
||
|
||
var defaultSpaces : IMap<UUID, UUID> | ||
|
||
/** | ||
* ID of the listener defined on defaultSpaces map | ||
*/ | ||
var defaultSpacesListenerID : UUID | ||
|
||
/** | ||
* SRE Kernel logger | ||
*/ | ||
var kernelLogger : Logger; | ||
|
||
@Inject | ||
new(sreConfig : SreConfig, @KernelScope rootContext : Context, injector : Injector, factory : ContextFactory, | ||
iHazelcastInstance : HazelcastInstance, distributedContextSpaceMapName : String, logger : LoggingService) { | ||
super(rootContext, injector, factory) | ||
hazelcastInstance = iHazelcastInstance | ||
defaultSpaces = this.hazelcastInstance.getMap(sreConfig.boot.rootContextID.toString()); | ||
|
||
kernelLogger = logger.kernelLogger | ||
} | ||
|
||
protected def newContextInstance(contextID : UUID, defaultSpaceID : UUID, owner : Agent) : Context { | ||
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 | ||
var defaultSpacesListerner = new EntryListener<UUID, UUID>() { | ||
|
||
def entryAdded(^event : EntryEvent<UUID, UUID>) { | ||
ensureDefaultSpaceDefinition(^event.key, ^event.value, null) | ||
} | ||
|
||
def entryUpdated(^event : EntryEvent<UUID, UUID>) { | ||
// | ||
} | ||
|
||
def entryRemoved(^event : EntryEvent<UUID, UUID>) { | ||
removeDefaultSpaceDefinition(^event.key, ^event.value) | ||
} | ||
|
||
def entryEvicted(^event : EntryEvent<UUID, UUID>) { | ||
// | ||
} | ||
|
||
def entryExpired(^event : EntryEvent<UUID, UUID>) { | ||
// | ||
} | ||
|
||
def mapCleared(^event : MapEvent) { | ||
// | ||
} | ||
|
||
def mapEvicted(^event : MapEvent) { | ||
// | ||
} | ||
|
||
} | ||
defaultSpacesListenerID = defaultSpaces.addEntryListener(defaultSpacesListerner, true) | ||
} | ||
|
||
protected def ensureDefaultSpaceDefinition(contextID : UUID, defaultSpaceID : UUID, owner : Agent) { | ||
kernelLogger.log(Level::INFO, | ||
"Creating local space " + defaultSpaceID + " of the Context " + contextID + " following a network request") | ||
|
||
if (getContext(contextID) === null) { | ||
// 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) { | ||
kernelLogger.log(Level::SEVERE, | ||
"ERROR: Trying to create a local space" + defaultSpaceID + | ||
" considered as the default space of the Context " + contextID + | ||
" following a network request, but is is not") | ||
} | ||
} | ||
} | ||
|
||
protected def removeDefaultSpaceDefinition(contextID : UUID, defaultSpaceID : UUID) { | ||
if (getContext(contextID).defaultSpace.isPseudoEmpty()) { | ||
|
||
if (getContext(contextID).defaultSpace.spaceID.ID === defaultSpaceID) { | ||
|
||
kernelLogger.log(Level::INFO, | ||
"Removing local space " + defaultSpaceID + " of the Context " + contextID + | ||
" following a network request") | ||
super.removeContext(contextID) | ||
|
||
} else { | ||
kernelLogger.log(Level::SEVERE, | ||
"ERROR: Trying to remove a local space" + defaultSpaceID + | ||
" considered as the default space of the Context " + contextID + | ||
" following a network request, but is is not") | ||
} | ||
|
||
} | ||
} | ||
|
||
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 | ||
defaultSpaces.clear | ||
defaultSpaces.removeEntryListener(defaultSpacesListenerID) | ||
} | ||
|
||
} |
Oops, something went wrong.