
net.roboconf.dm.management.Manager Maven / Gradle / Ivy
/**
* Copyright 2013-2016 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* 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 net.roboconf.dm.management;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.roboconf.core.Constants;
import net.roboconf.core.utils.Utils;
import net.roboconf.dm.internal.api.IRandomMngr;
import net.roboconf.dm.internal.api.impl.ApplicationMngrImpl;
import net.roboconf.dm.internal.api.impl.ApplicationTemplateMngrImpl;
import net.roboconf.dm.internal.api.impl.AutonomicMngrImpl;
import net.roboconf.dm.internal.api.impl.CommandsMngrImpl;
import net.roboconf.dm.internal.api.impl.ConfigurationMngrImpl;
import net.roboconf.dm.internal.api.impl.DebugMngrImpl;
import net.roboconf.dm.internal.api.impl.InstancesMngrImpl;
import net.roboconf.dm.internal.api.impl.MessagingMngrImpl;
import net.roboconf.dm.internal.api.impl.NotificationMngrImpl;
import net.roboconf.dm.internal.api.impl.PreferencesMngrImpl;
import net.roboconf.dm.internal.api.impl.RandomMngrImpl;
import net.roboconf.dm.internal.api.impl.TargetHandlerResolverImpl;
import net.roboconf.dm.internal.api.impl.TargetsMngrImpl;
import net.roboconf.dm.internal.environment.messaging.DmMessageProcessor;
import net.roboconf.dm.internal.environment.messaging.RCDm;
import net.roboconf.dm.internal.tasks.CheckerHeartbeatsTask;
import net.roboconf.dm.internal.tasks.CheckerMessagesTask;
import net.roboconf.dm.management.api.IApplicationMngr;
import net.roboconf.dm.management.api.IApplicationTemplateMngr;
import net.roboconf.dm.management.api.IAutonomicMngr;
import net.roboconf.dm.management.api.ICommandsMngr;
import net.roboconf.dm.management.api.IConfigurationMngr;
import net.roboconf.dm.management.api.IDebugMngr;
import net.roboconf.dm.management.api.IInstancesMngr;
import net.roboconf.dm.management.api.IMessagingMngr;
import net.roboconf.dm.management.api.INotificationMngr;
import net.roboconf.dm.management.api.IPreferencesMngr;
import net.roboconf.dm.management.api.ITargetHandlerResolver;
import net.roboconf.dm.management.api.ITargetsMngr;
import net.roboconf.dm.management.events.IDmListener;
import net.roboconf.messaging.api.business.ListenerCommand;
import net.roboconf.target.api.TargetHandler;
/**
* This class acts as a front-end to access the various features of the DM.
*
* This class is designed to work with OSGi, iPojo and Admin Config.
* But it can also be used programmatically.
*
*
* // Configure
* Manager manager = new Manager();
* manager.setMessagingType( "rabbitmq" );
*
* // Change the way we resolve handlers for deployment targetsMngr
* manager.setTargetResolver( ... );
*
* // Connect to the messaging server
* manager.start();
*
*
* @author Noël - LIG
* @author Pierre-Yves Gibello - Linagora
* @author Vincent Zurczak - Linagora
* @author Pierre Bourret - Université Joseph Fourier
*/
public class Manager {
// Constants
private static final long TIMER_PERIOD = 6000;
// Injected by iPojo or Admin Config
protected String messagingType;
// Internal fields
protected final Logger logger = Logger.getLogger( getClass().getName());
protected Timer timer;
private RCDm messagingClient;
// API access
private final NotificationMngrImpl notificationMngr;
private final MessagingMngrImpl messagingMngr;
private final ApplicationMngrImpl applicationMngr;
private final InstancesMngrImpl instancesMngr;
private final IRandomMngr randomMngr;
private final IPreferencesMngr preferencesMngr;
private final IConfigurationMngr configurationMngr;
private final IApplicationTemplateMngr applicationTemplateMngr;
private final ITargetsMngr targetsMngr;
private final IDebugMngr debugMngr;
private final ICommandsMngr commandsMngr;
private final IAutonomicMngr autonomicMngr;
private final TargetHandlerResolverImpl defaultTargetHandlerResolver;
/**
* Constructor.
*/
public Manager() {
super();
// Home-made DI.
// We do not want to mix N frameworks.
this.notificationMngr = new NotificationMngrImpl();
this.configurationMngr = new ConfigurationMngrImpl();
this.preferencesMngr = new PreferencesMngrImpl( this.configurationMngr );
this.randomMngr = new RandomMngrImpl( this.preferencesMngr );
this.messagingMngr = new MessagingMngrImpl();
this.defaultTargetHandlerResolver = new TargetHandlerResolverImpl();
this.targetsMngr = new TargetsMngrImpl( this.configurationMngr );
this.debugMngr = new DebugMngrImpl( this.messagingMngr, this.notificationMngr );
this.commandsMngr = new CommandsMngrImpl( this );
this.autonomicMngr = new AutonomicMngrImpl( this.commandsMngr, this.preferencesMngr );
this.applicationMngr = new ApplicationMngrImpl(
this.notificationMngr, this.configurationMngr,
this.targetsMngr, this.messagingMngr,
this.randomMngr, this.autonomicMngr );
this.applicationTemplateMngr = new ApplicationTemplateMngrImpl( this.notificationMngr, this.targetsMngr, this.applicationMngr, this.configurationMngr );
this.applicationMngr.setApplicationTemplateMngr( this.applicationTemplateMngr );
this.instancesMngr = new InstancesMngrImpl( this.messagingMngr, this.notificationMngr, this.targetsMngr, this.randomMngr );
this.instancesMngr.setTargetHandlerResolver( this.defaultTargetHandlerResolver );
this.instancesMngr.setRuleBasedHandler( this.autonomicMngr );
}
// iPojo stuff
/**
* Starts the manager.
*
* It is invoked by iPojo when an instance becomes VALID.
*
*/
public void start() {
this.logger.info( "The DM is about to be launched." );
// Load the preferences
this.preferencesMngr.loadProperties();
// Start the messaging
DmMessageProcessor messageProcessor = new DmMessageProcessor( this );
this.messagingClient = new RCDm( this.applicationMngr );
this.messagingClient.associateMessageProcessor( messageProcessor );
this.messagingMngr.setMessagingClient( this.messagingClient );
// Run the timer
this.timer = new Timer( "Roboconf's Management Timer", false );
this.timer.scheduleAtFixedRate( new CheckerMessagesTask( this.applicationMngr, this.messagingMngr ), 0, TIMER_PERIOD );
this.timer.scheduleAtFixedRate( new CheckerHeartbeatsTask( this.applicationMngr ), 0, Constants.HEARTBEAT_PERIOD );
// Configure the messaging
reconfigure();
// Restore what is necessary
this.applicationTemplateMngr.restoreTemplates();
this.applicationMngr.restoreApplications();
// We must update instance states after we restored applications
restoreAllInstances();
this.logger.info( "The DM was launched." );
}
/**
* Stops the manager.
*
* It is invoked by iPojo when an instance becomes INVALID.
*
*/
public void stop() {
this.logger.info( "The DM is about to be stopped." );
if( this.timer != null ) {
this.timer.cancel();
this.timer = null;
}
if( this.messagingClient != null ) {
// Stops listening to the debug queue.
try {
this.messagingClient.listenToTheDm( ListenerCommand.STOP );
} catch ( IOException e ) {
this.logger.log( Level.WARNING, "Cannot stop to listen to the debug queue", e );
}
this.messagingClient.getMessageProcessor().stopProcessor();
this.messagingClient.getMessageProcessor().interrupt();
try {
this.messagingClient.closeConnection();
} catch( IOException e ) {
this.logger.warning( "The messaging client could not be terminated correctly. " + e.getMessage());
Utils.logException( this.logger, e );
}
}
this.logger.info( "The DM was stopped." );
}
/**
* This method is invoked by iPojo every time a new target handler appears.
* @param targetItf the appearing target handler
*/
public void targetAppears( TargetHandler targetItf ) {
this.defaultTargetHandlerResolver.addTargetHandler( targetItf );
// When a target is deployed, we may also have to update instance states.
// Consider as an example when the DM restarts. Targets may be injected
// before and after the pojo was started by iPojo.
// See #519 for more details.
// Notice we restore instances only when the DM was started (the messaging
// must be ready). If it is not started, do nothing. The "start" method
// will trigger the restoration.
// We consider the DM is started if the timer is not null.
if( this.timer != null )
restoreInstancesFrom( targetItf );
}
/**
* This method is invoked by iPojo every time a target handler disappears.
* @param targetItf the disappearing target handler
*/
public void targetDisappears( TargetHandler targetItf ) {
this.defaultTargetHandlerResolver.removeTargetHandler( targetItf );
}
/**
* This method is invoked by iPojo every time a DM listener appears.
* @param targetItf the appearing listener
*/
public void listenerAppears( IDmListener listener ) {
this.notificationMngr.addListener( listener );
}
/**
* This method is invoked by iPojo every time a DM listener disappears.
* @param listener the disappearing listener
*/
public void listenerDisappears( IDmListener listener ) {
this.notificationMngr.removeListener( listener );
}
// Reconfiguration
/**
* This method reconfigures the manager.
*
* It is NOT invoked DIRECTLY by iPojo anymore.
*
*/
public void reconfigure() {
// Update the messaging client
if( this.messagingClient != null ) {
this.messagingClient.switchMessagingType( this.messagingType );
try {
if( this.messagingClient.isConnected())
this.messagingClient.listenToTheDm( ListenerCommand.START );
} catch ( IOException e ) {
this.logger.log( Level.WARNING, "Cannot start to listen to the debug queue", e );
}
}
// We must update instance states after we switched the messaging configuration.
restoreAllInstances();
this.logger.info( "The DM was successfully (re)configured." );
}
// Setters
public void setMessagingType( String messagingType ) {
// Properties are injected on every modification.
// so, we just want to track changes.
// We only want to reconfigure the messaging client
// when the messaging type changes.
if( ! Objects.equals( this.messagingType, messagingType )) {
this.messagingType = messagingType;
// Explicitly require a reconfiguration.
reconfigure();
}
}
public void setTargetResolver( ITargetHandlerResolver targetHandlerResolver ) {
if( targetHandlerResolver == null )
this.instancesMngr.setTargetHandlerResolver( this.defaultTargetHandlerResolver );
else
this.instancesMngr.setTargetHandlerResolver( targetHandlerResolver );
}
// Getters
public INotificationMngr notificationMngr() {
return this.notificationMngr;
}
public IMessagingMngr messagingMngr() {
return this.messagingMngr;
}
public IApplicationMngr applicationMngr() {
return this.applicationMngr;
}
public IInstancesMngr instancesMngr() {
return this.instancesMngr;
}
public IConfigurationMngr configurationMngr() {
return this.configurationMngr;
}
public IApplicationTemplateMngr applicationTemplateMngr() {
return this.applicationTemplateMngr;
}
public ITargetsMngr targetsMngr() {
return this.targetsMngr;
}
public IDebugMngr debugMngr() {
return this.debugMngr;
}
public ICommandsMngr commandsMngr() {
return this.commandsMngr;
}
public IPreferencesMngr preferencesMngr() {
return this.preferencesMngr;
}
public IAutonomicMngr autonomicMngr() {
return this.autonomicMngr;
}
// Private utilities
/**
* Restores the states of all the instances from the current target handlers.
*/
void restoreAllInstances() {
// instancesMngr() instead of this.instancesMngr (for unit tests).
this.logger.fine( "Restoring all the instance states from the current target handlers." );
for( ManagedApplication ma : this.applicationMngr.getManagedApplications()) {
// Build a new snapshot on every loop
List snapshot = this.defaultTargetHandlerResolver.getTargetHandlersSnapshot();
for( TargetHandler targetHandler : snapshot )
instancesMngr().restoreInstanceStates( ma, targetHandler );
}
}
/**
* Restores the states of all the instances from a given target handler.
*/
void restoreInstancesFrom( TargetHandler targetHandler ) {
// instancesMngr() instead of this.instancesMngr (for unit tests).
this.logger.fine( "Restoring the instance states with the '" + targetHandler.getTargetId() + "' target handler." );
for( ManagedApplication ma : this.applicationMngr.getManagedApplications())
instancesMngr().restoreInstanceStates( ma, targetHandler );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy