/** * ALMA - Atacama Large Millimiter Array Copyright (c) ESO - European Southern Observatory, 2005 * * 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 dfugate * @version $Id: ChannelProperties.java,v 1.15 2012/02/10 12:54:39 hsommer Exp $ * @since */ /** * ChannelProperties is a class which discovers the the quality of service and * administrative properties that should be used with any particular channel * name. */ package alma.acs.nc; import java.util.logging.Level; import java.util.logging.Logger; import org.omg.CORBA.Any; import org.omg.CosNotification.AnyOrder; import org.omg.CosNotification.BestEffort; import org.omg.CosNotification.ConnectionReliability; import org.omg.CosNotification.DeadlineOrder; import org.omg.CosNotification.DiscardPolicy; import org.omg.CosNotification.EventReliability; import org.omg.CosNotification.FifoOrder; import org.omg.CosNotification.LifoOrder; import org.omg.CosNotification.MaxConsumers; import org.omg.CosNotification.MaxEventsPerConsumer; import org.omg.CosNotification.MaxQueueLength; import org.omg.CosNotification.MaxSuppliers; import org.omg.CosNotification.OrderPolicy; import org.omg.CosNotification.Persistent; import org.omg.CosNotification.Priority; import org.omg.CosNotification.PriorityOrder; import org.omg.CosNotification.Property; import org.omg.CosNotification.RejectNewEvents; import org.omg.CosNotification.StartTimeSupported; import org.omg.CosNotification.StopTimeSupported; import org.omg.CosNotification.Timeout; import alma.JavaContainerError.wrappers.AcsJContainerServicesEx; import alma.acs.container.ContainerServicesBase; import alma.acs.exceptions.AcsJException; import alma.cdbErrType.CDBFieldDoesNotExistEx; import alma.cdbErrType.WrongCDBDataTypeEx; import com.cosylab.CDB.DAO; /** * ChannelProperties is a class designed to retrieve the various quality of * service and administrative properties for a given channel. It is intended to * be used primarily by the Helper class within this package. * * <p> * @TODO think about joining this class with {@link ChannelInfo}. * <p> * @TODO: Cache CDB data and only re-read when CDB calls back to us via DALChangeListener mechanism. * * @author dfugate */ public class ChannelProperties { /** * Creates a new instance of ChannelProperties. * * @param services * A reference to the ContainerServices. Used to retrieve other * CORBA references and to access the logger. */ public ChannelProperties(ContainerServicesBase services) { // save a local reference to the container services m_services = services; // immediately grab a logger m_logger = m_services.getLogger(); } // ////////////////////////////////////////////////////////////////////////// /** * Simple function which returns true if the given channel has an entry in * $ACS_CDB/CDB/MACI/EventChannels/ section of the ACS configuration * database. * * @param channelName * is a string referring to the name of a Notification Channel * registered in the CORBA Naming Service * @return true if * $ACS_CDB/CDB/MACI/EventChannels/channel_name/channel_name.xml * exists and is a valid XML. false otherwise. */ public boolean cdbChannelConfigExists(String channelName) { try { m_services.getCDB().get_DAO("MACI/Channels/" + channelName); return true; } catch (Exception e) { m_logger.finer("No CDB entry found for '" + channelName + "' channel"); return false; } } // ----------------------------------------------------------- /** * When some attribute is set within the CDB (currently <code>IntegrationLogs</code> * defined in <code>EventChannel.xsd</code>, see NC document), a log is published * each time an event is sent or received. * For performance reasons, this should be used very carefully to say the least. * * @param channelName * Name of the channel. * @return True if event publishing/receiving should be traced by log messages. * @throws AcsJException * @since ACS 6.0.1 (formerly called "getIntegrationLogs") */ public boolean isTraceEventsEnabled(String channelName) throws AcsJException { // use this object to get at channel information from the CDB DAO tempDAO = null; try { tempDAO = m_services.getCDB().get_DAO_Servant("MACI/Channels/" + channelName); } catch (alma.cdbErrType.CDBRecordDoesNotExistEx e) { return false; } catch (alma.cdbErrType.CDBXMLErrorEx e) { m_logger.log(Level.SEVERE, "Bad CDB entry found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJUnknownEx(e); } catch (AcsJContainerServicesEx e) { m_logger.log(Level.SEVERE, "CDB unavailable", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJNoResourcesEx(e); } try { if (tempDAO.get_string("IntegrationLogs").equals("false")) { return false; } return true; } catch (WrongCDBDataTypeEx e) { m_logger.log(Level.SEVERE, "Wrong type of data for IntegrationLogs", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJNoResourcesEx(e); } catch (CDBFieldDoesNotExistEx e) { m_logger.log(Level.SEVERE, "Field does not exist for IntegrationLogs", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJNoResourcesEx(e); } } // ////////////////////////////////////////////////////////////////////////// /** * Given a channel name that exists in the ACS CDB * ($ACS_CDB/CDB/MACI/Channels/channelName/channelName.xml), this function * returns the channels administrative properties in their CORBA format. * * @param channelName * name of the channel found in $ACS_CDB/CDB/MACI/Channels * @return channel's admin properties * @throws AcsJException * if the channel's CDB entry is corrupted in any way */ public Property[] getCDBAdminProps(String channelName) throws AcsJException { // use this object to get at channel information from the CDB DAO tempDAO = null; try { tempDAO = m_services.getCDB().get_DAO_Servant("MACI/Channels/" + channelName); } catch (alma.cdbErrType.CDBXMLErrorEx e) { m_logger.log(Level.WARNING, "Bad CDB entry found for '" + channelName + "' channel"); throw new alma.ACSErrTypeCommon.wrappers.AcsJUnknownEx(e); } catch (alma.cdbErrType.CDBRecordDoesNotExistEx e) { m_logger.log(Level.WARNING, "No CDB entry found for '" + channelName + "' channel"); throw new alma.ACSErrTypeCommon.wrappers.AcsJFileNotFoundEx(e); } catch (AcsJContainerServicesEx e) { m_logger.log(Level.WARNING, "CDB unavailable"); throw new alma.ACSErrTypeCommon.wrappers.AcsJNoResourcesEx(e); } // MaxQueueLength - TAO 1.1 had a queque of ~5 events. TAO 1.3 allows an // infinite amount of events to be stored. 20 seems like // a reasonable default. Any maxQLAny = m_services.getAdvancedContainerServices().getAny(); try { maxQLAny.insert_long(tempDAO.get_long("MaxQueueLength")); } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } Property maxQL = new Property(MaxQueueLength.value, maxQLAny); // MaxConsumers - /////////////////////////////////////////////////////// Any maxConsumersAny = m_services.getAdvancedContainerServices().getAny(); try { maxConsumersAny.insert_long(tempDAO.get_long("MaxConsumers")); } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } Property maxConsumers = new Property(MaxConsumers.value, maxConsumersAny); // MaxSuppliers - /////////////////////////////////////////////////////// Any maxSuppliersAny = m_services.getAdvancedContainerServices().getAny(); try { maxSuppliersAny.insert_long(tempDAO.get_long("MaxSuppliers")); } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } Property maxSuppliers = new Property(MaxSuppliers.value, maxSuppliersAny); // RejectNewEvents - if the queque is full, suppliers get exceptions when // trying to push events onto the channel. Any rejectNEAny = m_services.getAdvancedContainerServices().getAny(); boolean tBool = true; try { if (tempDAO.get_string("RejectNewEvents").equals("false")) { tBool = false; } } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } rejectNEAny.insert_boolean(tBool); Property rejectNE = new Property(RejectNewEvents.value, rejectNEAny); Property[] adminProps = { maxQL, maxConsumers, maxSuppliers, rejectNE }; return adminProps; } // ////////////////////////////////////////////////////////////////////////// /** * Given a channel name that exists in the ACS CDB * ($ACS_CDB/CDB/MACI/Channels/channelName/channelName.xml), this function * returns the channel's quality of service properties in their CORBA format. * <p> * The schema for this channel configuration is <code>urn:schemas-cosylab-com:EventChannel:1.0</code>. * * @param channelName * name of the channel found in $ACS_CDB/CDB/MACI/Channels * @return channel's quality of service properties * @throws AcsJException * if the channel's CDB entry is corrupted in any way */ public Property[] getCDBQoSProps(String channelName) throws alma.acs.exceptions.AcsJException { // use this object to get at channel information from the CDB DAO tempDAO = null; try { tempDAO = m_services.getCDB().get_DAO_Servant("MACI/Channels/" + channelName); } catch (alma.cdbErrType.CDBXMLErrorEx e) { m_logger.log(Level.WARNING, "Bad CDB entry found for '" + channelName + "' channel"); throw new alma.ACSErrTypeCommon.wrappers.AcsJUnknownEx(e); } catch (alma.cdbErrType.CDBRecordDoesNotExistEx e) { m_logger.log(Level.WARNING, "No CDB entry found for '" + channelName + "' channel"); throw new alma.ACSErrTypeCommon.wrappers.AcsJFileNotFoundEx(e); } catch (AcsJContainerServicesEx e) { m_logger.log(Level.WARNING, "CDB unavailable", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJNoResourcesEx(e); } // EventReliability - /////////////////////////////////////////////// Any eventRelAny = m_services.getAdvancedContainerServices().getAny(); short eventRelVal = Persistent.value; try { if (tempDAO.get_string(EventReliability.value).equals("BestEffort")) { eventRelVal = BestEffort.value; } } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } eventRelAny.insert_short(eventRelVal); Property eventRel = new Property(EventReliability.value, eventRelAny); // ConnectionReliability - /////////////////////////////////////////////// Any connectRelAny = m_services.getAdvancedContainerServices().getAny(); short connectRelVal = Persistent.value; try { if (tempDAO.get_string(ConnectionReliability.value).equals("BestEffort")) { connectRelVal = BestEffort.value; } } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } connectRelAny.insert_short(Persistent.value); Property connectRel = new Property(ConnectionReliability.value, connectRelAny); //@TODO do something with this connectRel, e.g. check why it's commented out at the end of this method! // Also enforce that EventReliability=Persistent && ConnectionRelability=BestEffort is undefined (spec 2.5.5.1). // ConnectionRelability=Persistent requires TAO topology persistence to be enabled. // Priority - /////////////////////////////////////////////// Any priorityAny = m_services.getAdvancedContainerServices().getAny(); try { priorityAny.insert_short((short) tempDAO.get_long(Priority.value)); } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } Property priority = new Property(Priority.value, priorityAny); // Timeout - /////////////////////////////////////////////// Any timeoutAny = m_services.getAdvancedContainerServices().getAny(); try { org.omg.TimeBase.TimeTHelper.insert(timeoutAny, tempDAO.get_long(Timeout.value)); } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } Property timeout = new Property(Timeout.value, timeoutAny); // OrderPolicy - /////////////////////////////////////////////// Any orderPolAny = m_services.getAdvancedContainerServices().getAny(); short orderPolicyVal; try { if (tempDAO.get_string(OrderPolicy.value).equals("AnyOrder")) { orderPolicyVal = AnyOrder.value; } else if (tempDAO.get_string(OrderPolicy.value).equals("FifoOrder")) { orderPolicyVal = FifoOrder.value; } else if (tempDAO.get_string(OrderPolicy.value).equals("PriorityOrder")) { orderPolicyVal = PriorityOrder.value; } else if (tempDAO.get_string(OrderPolicy.value).equals("DeadlineOrder")) { orderPolicyVal = DeadlineOrder.value; } else { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel"); throw new Exception("No value found for order policy."); } } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } orderPolAny.insert_short(orderPolicyVal); Property orderPol = new Property(OrderPolicy.value, orderPolAny); // DiscardPolicy - /////////////////////////////////////////////// Any discardPolAny = m_services.getAdvancedContainerServices().getAny(); short discardPolicyVal; try { if (tempDAO.get_string(DiscardPolicy.value).equals("AnyOrder")) { discardPolicyVal = AnyOrder.value; } else if (tempDAO.get_string(DiscardPolicy.value).equals("FifoOrder")) { discardPolicyVal = FifoOrder.value; } else if (tempDAO.get_string(DiscardPolicy.value).equals("PriorityOrder")) { discardPolicyVal = PriorityOrder.value; } else if (tempDAO.get_string(DiscardPolicy.value).equals("DeadlineOrder")) { discardPolicyVal = DeadlineOrder.value; } else if (tempDAO.get_string(DiscardPolicy.value).equals("LifoOrder")) { discardPolicyVal = LifoOrder.value; } else { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel"); throw new Exception("No value found for discard policy."); } } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } discardPolAny.insert_short(discardPolicyVal); Property discardPol = new Property(DiscardPolicy.value, discardPolAny); // StartTimeSupported - /////////////////////////////////////////////// Any startTSAny = m_services.getAdvancedContainerServices().getAny(); boolean startTSVal = true; try { if (tempDAO.get_string(StartTimeSupported.value).equals("false")) { startTSVal = false; } } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } startTSAny.insert_boolean(startTSVal); Property startTS = new Property(StartTimeSupported.value, startTSAny); // StopTimeSupported - /////////////////////////////////////////////// Any stopTSAny = m_services.getAdvancedContainerServices().getAny(); boolean stopTSVal = true; try { if (tempDAO.get_string(StopTimeSupported.value).equals("false")) { stopTSVal = false; } } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } stopTSAny.insert_boolean(stopTSVal); Property stopTS = new Property(StopTimeSupported.value, stopTSAny); // MaxEventsPerConsumer - /////////////////////////////////////////////// Any MEPCAny = m_services.getAdvancedContainerServices().getAny(); try { MEPCAny.insert_long(tempDAO.get_long(MaxEventsPerConsumer.value)); } catch (Exception e) { m_logger.log(Level.SEVERE, "Bad CDB entry datatype found for '" + channelName + "' channel", e); throw new alma.ACSErrTypeCommon.wrappers.AcsJTypeNotSupportedEx(e); } Property MEPC = new Property(MaxEventsPerConsumer.value, MEPCAny); Property[] qosProps = { // eventRel, // connectRel, priority, timeout, orderPol, discardPol, // startTS, // stopTS, MEPC }; return qosProps; } // ////////////////////////////////////////////////////////////////////////// /** * Override this method in a subclass to specify your own quality of service * properties for the channel. Only useful if the channel has not already * been registered with the naming service. * * @param channelName * Name of the channel we are looking for. * * @return A property array consisting of the quality of service * specifications. * @throws AcsJException * Thrown if a CORBA Any cannot be created. */ protected Property[] configQofS(String channelName) throws AcsJException { // if there's a CDB entry for this channel... if (cdbChannelConfigExists(channelName) == true) { // ...return that CDB entry m_logger.finer("Using CDB for '" + channelName + "' channel's Q of S properties"); return getCDBQoSProps(channelName); } Property[] initial_QOS = {}; return initial_QOS; } // ////////////////////////////////////////////////////////////////////////// /** * Override this method in a subclass to specify your own administrative * properties for the channel. Only useful if the channel has not already * been registered with the naming service. * * @param channelName * Name of the channel we are looking for * * @return A property array consisting of the administrative specifications. * @throws AcsJException * Thrown if a CORBA Any cannot be created. */ protected Property[] configAdminProps(String channelName) throws AcsJException { // if there's a CDB entry for this channel... if (cdbChannelConfigExists(channelName) == true) { // ...return that CDB entry m_logger.finer("Using CDB for '" + channelName + "' channel's admin properties"); return getCDBAdminProps(channelName); } Property[] initialAdmin = {}; return initialAdmin; } /** * Access to the component's name along with the logging service. */ private final ContainerServicesBase m_services; /** * Standard logger */ private final Logger m_logger; }