/******************************************************************************* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * @author dragan * * To change this generated comment edit the template variable "typecomment": * Window>Preferences>Java>Templates. * To enable and disable the creation of type comments go to * Window>Preferences>Java>Code Generation. */ package com.cosylab.cdb.jdal; import java.io.FileWriter; import java.io.PrintWriter; import java.util.Properties; import java.util.StringTokenizer; import java.util.logging.Logger; import org.omg.CORBA.NO_RESOURCES; import org.omg.CORBA.ORB; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContext; import org.omg.CosNaming.NamingContextHelper; import org.omg.PortableServer.IdAssignmentPolicyValue; import org.omg.PortableServer.LifespanPolicyValue; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAHelper; import org.omg.PortableServer.Servant; import com.cosylab.CDB.JDAL; import com.cosylab.CDB.JDALHelper; import com.cosylab.CDB.WJDALOperations; import com.cosylab.CDB.WJDALPOATie; import alma.acs.logging.AcsLogLevel; import alma.acs.logging.ClientLogManager; import alma.acs.monitoring.SimpleCallInterceptor; import alma.acs.util.ACSPorts; public class Server { public static final String CDB_LOGGER_NAME = "CDB"; public static final String LOG_CDB_CALLS_PROPERTYNAME = "alma.acs.cdb.log_corba_calls"; public static void main (String[] args) { new Server().run(args); } private JDAL jdal; public void run(String args[]) { String iorFileName = null; final Logger sharedLogger = ClientLogManager.getAcsLogManager().getLoggerForApplication(CDB_LOGGER_NAME, true); try { Properties properties = System.getProperties(); boolean useJacORB = false; // default is JDK ORB int portNumber = Integer.parseInt(ACSPorts.getCDBPort()); for (int i = 0; i < args.length; i++) { if (args[i].equals("-OAport") || args[i].equals("-OAPort")) { if (i < args.length - 1) { portNumber = Integer.valueOf(args[++i]).intValue(); } } if (args[i].equals("-OAIAddr")) { if (i < args.length - 1) { properties.put("OAIAddr", args[++i]); } } if (args[i].equals("-orbacus")) { sharedLogger.log(AcsLogLevel.NOTICE, "ORBacus is no longer supported, switching to JacORB."); //System.err.println( // "ORBacus is no longer supported, switching to JacORB."); useJacORB = true; } if (args[i].equals("-jacorb")) { useJacORB = true; } if (args[i].equals("-o")) { if (i < args.length - 1) { iorFileName = args[++i]; } else { iorFileName = "DAL.ior"; } } } if (useJacORB) { sharedLogger.log(AcsLogLevel.DELOUSE, "DALfs will use JacORB ORB"); properties.put("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB"); properties.put( "org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton"); // port properties.put("OAPort", Integer.toString(portNumber)); // ORB implementation name properties.put("jacorb.implname", "ORB"); /* * by setting the following property, the ORB will * accept client requests targeted at the object with * key "CDB", so more readable corbaloc URLs * can be used */ properties.put( "jacorb.orb.objectKeyMap.CDB", "ORB/dalPOA/CDB"); } else { properties.put( "com.sun.CORBA.POA.ORBPersistentServerPort", Integer.toString(portNumber)); } // create and initialize the ORB ORB orb = ORB.init(args, properties); // get reference to rootpoa & activate the POAManager POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); /* create a user defined poa for the naming contexts */ org.omg.CORBA.Policy[] policies = new org.omg.CORBA.Policy[2]; policies[0] = rootpoa.create_id_assignment_policy( IdAssignmentPolicyValue.USER_ID); if (useJacORB) policies[1] = rootpoa.create_lifespan_policy( LifespanPolicyValue.PERSISTENT); else policies[1] = rootpoa.create_lifespan_policy( LifespanPolicyValue.TRANSIENT); POA dalpoa = rootpoa.create_POA( "dalPOA", rootpoa.the_POAManager(), policies); for (int i = 0; i < policies.length; i++) policies[i].destroy(); rootpoa.the_POAManager().activate(); // create servant and register it with the ORB final WDALImpl servantDelegate = new WDALImpl(args, orb, dalpoa, sharedLogger); WJDALOperations topLevelServantDelegate = servantDelegate; if (Boolean.getBoolean(LOG_CDB_CALLS_PROPERTYNAME)) { // Currently we only intercept the functional IDL-defined methods, by wrapping servantDelegate. // If we want to also intercept the CORBA admin methods, then *servant* should be wrapped with a dynamic proxy instead. WJDALOperations interceptingServantDelegate = SimpleCallInterceptor.createSimpleInterceptor(WJDALOperations.class, servantDelegate, sharedLogger); topLevelServantDelegate = interceptingServantDelegate; } final Servant servant = new WJDALPOATie(topLevelServantDelegate); //create object id byte[] id = { 'C', 'D', 'B' }; //activate object dalpoa.activate_object_with_id(id, servant); // get object reference from the servant org.omg.CORBA.Object ref = dalpoa.servant_to_reference(servant); jdal = JDALHelper.narrow(ref); // try to bind it in IOR if (useJacORB) { // nothing to do here } else { ( (com.sun.corba.se.internal.Interceptors.PIORB) orb) .register_initial_reference( "CDB", rootpoa.servant_to_reference(servant)); } // register in name service if available try { // get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Bind the object reference in naming NameComponent nc = new NameComponent("CDB", ""); NameComponent path[] = { nc }; ncRef.rebind(path, jdal); } // GCH 2003-07-04 // Here I have to catch Exception and not RuntimeException, // because otherwise org.omg.CORBA.ORBPackage.InvalidName // is not catched and jDAL gives up. // This situation occurrs when the NameSetvice initial reference // is not set at all with the ORBInitRef.NameService property catch (Exception e1) { sharedLogger.log(AcsLogLevel.NOTICE, "JDAL is NOT registered in the name service because of: " + e1); } if (Integer.getInteger("ACS.logstdout", 4) < 4) { sharedLogger.log(AcsLogLevel.INFO, "JDAL is listening on " + ACSPorts.getIP() + ":" + portNumber + "/CDB"); } // recover (notify) clients if (servantDelegate instanceof Recoverer) { ((Recoverer) servantDelegate).recoverClients(); } if (iorFileName != null) { // write the object reference to a file PrintWriter iorFile = new PrintWriter(new FileWriter(iorFileName)); iorFile.println(orb.object_to_string(jdal)); iorFile.close(); } sharedLogger.log(AcsLogLevel.INFO, "JDAL is ready and waiting ..."); // GCH 2006-11-13 // Here we put also a println to be sure that the message // ALWAYS appears on standart output, also if the logging level // is put higher than INFO. // This is needed because the ACS startup scripts wait for this message // to declare complete the startup of the CDB. System.out.println("JDAL is ready and waiting ..."); // preload cache new Thread(new Runnable() { public void run() { preloadCache(servantDelegate.getDALImplDelegate(), sharedLogger); } }, "preload-cache").start(); // Init remote Logging try { ClientLogManager.getAcsLogManager().initRemoteLoggingForService(orb, true); } catch (Throwable t) { sharedLogger.log(AcsLogLevel.ERROR, "Error initializing the remote logging"); } // wait for invocations from clients orb.run(); sharedLogger.log(AcsLogLevel.INFO, "JDAL exiting ORB loop ..."); } catch (Exception e) { sharedLogger.log(AcsLogLevel.NOTICE, "ERROR: " + e); e.printStackTrace(System.out); } } public void shutdown() { jdal.shutdown(); } private static String[] PRELOAD_TABLE = { "MACI/Managers/Manager", "MACI/Components" }; private static String[] PRELOAD_TABLE_SUBTREE = { "MACI/Containers" }; private void preloadCache(DALImpl dal, Logger sharedLogger) { boolean allRead = false; sharedLogger.log(AcsLogLevel.DEBUG, "Starting pre-filling cache..."); try { for (String node : PRELOAD_TABLE) { if (dal.wasCacheLimitReached()) return; try { jdal.get_DAO(node); } catch (alma.cdbErrType.CDBXMLErrorEx xmlerr) { // noop } catch (alma.cdbErrType.CDBRecordDoesNotExistEx noRec) { // noop } } for (String subTree : PRELOAD_TABLE_SUBTREE) { if (dal.wasCacheLimitReached()) return; String daos = jdal.list_nodes(subTree); if (daos != null) { StringTokenizer tokenizer = new StringTokenizer(daos); while (tokenizer.hasMoreTokens()) { try { jdal.get_DAO(subTree+"/"+tokenizer.nextToken()); } catch (alma.cdbErrType.CDBXMLErrorEx xmlerr) { // noop } catch (alma.cdbErrType.CDBRecordDoesNotExistEx noRec) { // noop } } } } allRead = true; } catch (NO_RESOURCES nores) { // shutdown sharedLogger.log(AcsLogLevel.DEBUG, "Cache filling canceled due to server shutdown."); return; } if (allRead) sharedLogger.log(AcsLogLevel.DEBUG, "Cache filling fully completed."); else sharedLogger.log(AcsLogLevel.DEBUG, "Cache filling partly completed, terminated since cache memory limit was reached."); } }