/*
* @@COPYRIGHT@@
*/
package com.cosylab.acs.maci.manager.app;
import java.io.File;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import org.jacorb.orb.acs.AcsORBProfiler;
import org.jacorb.orb.acs.AcsProfilingORB;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NamingContextHelper;
import org.omg.PortableServer.IdAssignmentPolicyValue;
import org.omg.PortableServer.LifespanPolicyValue;
import org.omg.PortableServer.POA;
import org.prevayler.implementation.SnapshotPrevayler;
import com.cosylab.acs.maci.CoreException;
import com.cosylab.acs.maci.HandleConstants;
import com.cosylab.acs.maci.manager.ManagerImpl;
import com.cosylab.acs.maci.manager.ManagerShutdown;
import com.cosylab.acs.maci.plug.CORBAReferenceSerializator;
import com.cosylab.acs.maci.plug.CORBATransport;
import com.cosylab.acs.maci.plug.DefaultCORBAService;
import com.cosylab.acs.maci.plug.ManagerProxyImpl;
import com.cosylab.acs.maci.plug.NamingServiceRemoteDirectory;
import com.cosylab.cdb.client.CDBAccess;
import com.cosylab.util.FileHelper;
import si.ijs.maci.ManagerHelper;
import alma.acs.logging.AcsLogger;
import alma.acs.logging.ClientLogManager;
import alma.acs.logging.config.LogConfig;
import alma.acs.logging.config.LogConfigException;
/**
* Engine of the Manager GUI application.
*
* @author Matej Sekoranja (matej.sekoranja@cosylab.com)
* @version @@VERSION@@
*/
public class ManagerEngine
{
/**
* Manager domain (empty until manager federation is implemented).
*/
private final static String MANAGER_DOMAIN = "";
/**
* CORBA Manager Servant ID.
*/
private final static byte[] MANAGER_ID = { 'M', 'a', 'n', 'a', 'g', 'e', 'r' };
/**
* Directory name under ACS.temp where recovery fieles are stored
*/
private final static String RECOVERY_DIR_NAME = "Manager_Recovery";
/**
* Implementation of the Manager.
*/
private ManagerImpl manager = null;
/**
* Manager CORBA Proxy implementation.
*/
private ManagerProxyImpl managerProxy = null;
/**
* Manager POA.
*/
private POA managerPOA = null;
/**
* Manager reference.
*/
private si.ijs.maci.Manager managerReference = null;
/**
* Implementation of the shutdown method.
*/
private ManagerShutdown shutdownImplementation = null;
/**
* Recovery files directory.
*/
private String recoveryLocation = null;
/**
* Default logger is global logger.
* This default logger should never be used, since {@link #initializeManager()} will create and assign a proper ACS logger.
*/
private AcsLogger logger = AcsLogger.fromJdkLogger(Logger.global, "ur-logger");
/**
* CORBA service.
*/
private DefaultCORBAService corbaService = null;
public static final String DISABLE_PREVAYLER = "acs.disablePrevayler";
private static final boolean isPrevaylerDisabled = Boolean.getBoolean(DISABLE_PREVAYLER);
/**
* Constructor for ManagerEngine.
*
* @param shutdownImplementation implementation of the shutdown method.
*/
public ManagerEngine(ManagerShutdown shutdownImplementation)
{
super();
this.shutdownImplementation = shutdownImplementation;
}
/**
* Destroy.
*/
public void destroy()
{
try
{
destroyManager();
}
catch (Throwable th)
{
logger.log(Level.SEVERE, "Failed to deactivate Manager.", th);
}
}
/**
* Initialize manager.
*/
public void initialize()
{
try
{
initializeManager();
initializeShutdownHook();
}
catch (Throwable ex)
{
logger.log(Level.SEVERE, "FAILED TO INITIALIZE MANAGER.", ex);
if (!System.getProperty("ACS.noExit", "false").equalsIgnoreCase("true"))
System.exit(1);
}
logger.info("All initializations done.");
}
/**
* Initialize and activate Manager.
*/
private void initializeManager() throws Throwable
{
logger = ClientLogManager.getAcsLogManager().getLoggerForApplication("Manager", true);
logger.info("Initializing Manager.");
//
// CORBA
//
// obtain CORBA Service
corbaService = new DefaultCORBAService(logger);
// get ORB
final ORB orb = corbaService.getORB();
if (orb == null)
{
CoreException ce = new CoreException("CORBA Service can not provide ORB.");
throw ce;
}
// get RootPOA
POA rootPOA = corbaService.getRootPOA();
if (rootPOA == null)
{
CoreException ce = new CoreException("CORBA Service can not provide RootPOA.");
throw ce;
}
//
// Remote Directory
//
NamingServiceRemoteDirectory remoteDirectory = new NamingServiceRemoteDirectory(orb, logger);
Context context = null;
if (remoteDirectory != null)
context = remoteDirectory.getContext();
//
// Initialize CORBA
//
// set USER_ID, PERSISTENT policies
org.omg.CORBA.Policy [] policies = new org.omg.CORBA.Policy[2];
/*
// set USER_ID, PERSISTENT,BIDIRECTIONAL policies
org.omg.CORBA.Policy [] policies = new org.omg.CORBA.Policy[3];
*/
policies[0] = rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);
policies[1] = rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
/*
// create BIDIRECTIONAL policy
Any bidirValue = orb.create_any();
BidirectionalPolicyValueHelper.insert(bidirValue, BOTH.value);
policies[2] = orb.create_policy(BIDIRECTIONAL_POLICY_TYPE.value, bidirValue);
*/
// create ManagerPOA
managerPOA = rootPOA.create_POA("ManagerPOA", rootPOA.the_POAManager(), policies);
// destroy policies
for (int i = 0; i < policies.length; i++)
policies[i].destroy();
// initialize Manager implementation
CORBAReferenceSerializator.setOrb(orb); // allow object reference serialization
manager = new ManagerImpl();
manager.setDomain(MANAGER_DOMAIN);
recoveryLocation = FileHelper.getTempFileName(null, RECOVERY_DIR_NAME);
String readRecovery = System.getProperties().getProperty("Manager.recovery", "true");
if( readRecovery.equalsIgnoreCase("false") ) {
// if we are not interested in recovery files just delete them
File recoveryDir = new File(recoveryLocation);
//recoveryDir.delete();
File[] files = recoveryDir.listFiles();
for (int i = 0; files != null && i < files.length; i++)
files[i].delete();
// Now check if there are log files left. Maybe user do not have enough permision
// or we are didn't set proper permission before Manager killed.
// That can lead to unwanted or illegal state so we will refuse to continue
files = recoveryDir.listFiles();
for (int i = 0; files != null && i < files.length; i++) {
if( files[i].getName().endsWith(".commandLog") )
throw new Exception("Some recovery files are left in recovery location probably because of permission\nUnable to start without recovery state!");
}
}
else
{
// remove old recovery files
RecoveryFilesRemover.removeRecoveryFiles(new File(recoveryLocation));
}
SnapshotPrevayler prevayler = null;
if (isPrevaylerDisabled)
{
System.out.println( "Prevayler disabled!");
}
else
{
prevayler = new SnapshotPrevayler(manager, recoveryLocation);
if( readRecovery.equalsIgnoreCase("false") ) {
// just to invalidate prevaylers message
System.out.println( "Skipping saved manager state!");
}
manager = (ManagerImpl)prevayler.system();
}
CDBAccess cdbAccess = new CDBAccess(orb, logger);
LogConfig logConfig = ClientLogManager.getAcsLogManager().getLogConfig();
logConfig.setCDBLoggingConfigPath("MACI/Managers/Manager");
logConfig.setCDB(cdbAccess.connectAndGetDAL());
try {
logConfig.initialize(false);
} catch (LogConfigException ex) {
// if the CDB can't be read, we still want to run the manager, so
// we only log the problems
logger.log(Level.FINE, "Failed to configure logging (default values will be used). Reason: " + ex.getMessage());
}
// initialize manager "mock" container services
ManagerContainerServices managerContainerServices = new ManagerContainerServices(orb, managerPOA, cdbAccess.getDAL(), logger);
manager.initialize(prevayler, cdbAccess, context, logger, managerContainerServices);
manager.setShutdownImplementation(shutdownImplementation);
// setup ORB profiling
try {
if (orb instanceof AcsProfilingORB) {
AcsORBProfiler profiler = new ManagerOrbProfiler(manager, logger);
((AcsProfilingORB)orb).registerAcsORBProfiler(profiler);
logger.finer("Orb profiling set up, using class " + ManagerOrbProfiler.class.getName());
}
} catch (Throwable th) {
logger.log(Level.WARNING, "Failed to setup ORB profiling.", th);
}
if (prevayler != null)
{
FileHelper.setFileAttributes( "g+w", recoveryLocation );
// create new task for snapshoot creation,
final long MINUTE_IN_MS = 60*1000;
new RecoverySnapshotTask(prevayler, 1*MINUTE_IN_MS, recoveryLocation, manager.getStatePersitenceFlag());
}
// initialize Manager CORBA Proxy (create servant)
managerProxy = new ManagerProxyImpl(manager, logger);
//activate object
managerPOA.activate_object_with_id( MANAGER_ID, managerProxy );
// get object reference from the servant
org.omg.CORBA.Object obj = managerPOA.servant_to_reference(managerProxy);
managerReference = ManagerHelper.narrow(obj);
// get IOR
String ior = orb.object_to_string(managerReference);
// notify user
logger.info("Manager activated with " + ior);
// register special service components to the Manager
manager.setManagerComponentReference(managerReference);
// set transport
manager.setTransport(new CORBATransport(orb, ior));
// register NameService
if (remoteDirectory != null)
{
String reference = remoteDirectory.getReference();
if (reference != null)
{
// convert iiop to corbaloc
if (reference.startsWith("iiop://"))
{
reference = reference.replaceFirst("iiop://", "corbaloc::");
if (reference.charAt(reference.length()-1) != '/')
reference += "/NameService";
else
reference += "NameService";
}
}
try
{
obj = NamingContextHelper.narrow(orb.string_to_object(reference));
}
catch (Exception ex)
{
// Something went wrong getting the NS
logger.log(Level.SEVERE,"Error getting the NameServer. Manager exiting...");
this.shutdownImplementation.shutdown(false);
}
manager.setRemoteDirectoryComponentReference(obj);
}
// intitialize federation here - after remote directory is set (if it is)
// (this is not a nice solution)
Hashtable federationDirectoryProperties = new Hashtable();
// set CosNamingFactory
federationDirectoryProperties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.cosnaming.CNCtxFactory");
// set orb
federationDirectoryProperties.put("java.naming.corba.orb", orb);
manager.initializeFederation(federationDirectoryProperties);
// initialize remote logging
new Thread(new Runnable() {
public void run()
{
ClientLogManager.getAcsLogManager().initRemoteLogging(orb, managerReference, manager.getHandle(), true);
}
}, "Remote logging initializer").start();
manager.initializationDone();
}
/**
* Destroy the Manager.
*/
private void destroyManager() throws Exception
{
logger.info("Destroying Manager.");
// firsty destroy Manager implementation (if necessary)
if (!manager.isShuttingDown())
{
try
{
manager.shutdown(HandleConstants.MANAGER_MASK, 0);
}
catch (Throwable ex)
{
CoreException ce = new CoreException("Failed to destroy manager.", ex);
logger.log(Level.WARNING, "Failed to destroy manager.", ce);
}
}
// deactivate Manager
if (managerPOA != null && managerReference != null)
{
managerPOA.deactivate_object(MANAGER_ID);
managerPOA = null;
}
// destroy CORBA service
if (corbaService != null)
corbaService.destroy();
// add rights to group in order to be able to start with '-n'
if (recoveryLocation != null)
FileHelper.setFileAttributes( "g+w", recoveryLocation );
}
/**
* Initialize shutdown hook (CTRL-C signal).
*/
private void initializeShutdownHook()
{
/**
* Manager shitdown hook thread implementation.
*/
class ManagerShutdownHookThread extends Thread
{
public ManagerShutdownHookThread()
{
super("ManagerShutdownHook");
}
public void run()
{
// call shutdown
if (shutdownImplementation != null && !shutdownImplementation.isShutdownInProgress())
{
// fire destroy application
shutdownImplementation.shutdown(true);
}
}
}
// register shutdown hook
Runtime.getRuntime().addShutdownHook(new ManagerShutdownHookThread());
}
/**
* Returns number of pending requests.
* @return number of pending requests.
*/
public int getNumberOfPendingRequests()
{
if (managerProxy != null)
return managerProxy.getNumberOfPendingRequests();
else
return -1;
}
/**
* Get logger.
* @return logger.
*/
public Logger getLogger()
{
return logger;
}
}