All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tango.orb.ORBManager Maven / Gradle / Ivy

There is a newer version: 10.0.0
Show newest version
/**
 * Copyright (C) :     2012
 *
 * 	Synchrotron Soleil
 * 	L'Orme des merisiers
 * 	Saint Aubin
 * 	BP48
 * 	91192 GIF-SUR-YVETTE CEDEX
 *
 * This file is part of Tango.
 *
 * Tango 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 3 of the License, or
 * (at your option) any later version.
 *
 * Tango 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 Tango.  If not, see .
 */
package org.tango.orb;

import fr.esrf.Tango.*;
import org.omg.CORBA.*;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.PortableServer.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
import org.tango.client.database.DatabaseFactory;
import org.tango.client.database.DeviceImportInfo;
import org.tango.utils.DevFailedUtils;

import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
 * Initialize, shutdown the ORB
 *
 * @author ABEILLE
 *
 */
public final class ORBManager {

    private static final String INIT_ERROR = "INIT_ERROR";
    private static final XLogger XLOGGER = XLoggerFactory.getXLogger(ORBManager.class);
    private static final Logger LOGGER = LoggerFactory.getLogger(ORBManager.class);
    /**
     * POA for no db device
     */
    public static final String NODB_POA = "nodb_poa";
    /**
     * impl name for nodb device
     */
    public static final String SERVER_IMPL_NAME = "nodb.device";
    /**
     * A jacorb system property for IP address on multi-homed host
     */
    public static final String OAI_ADDR = System.getProperty("OAIAddr");
    private static ORB orb;
    private static POA poa;
    private static ExecutorService orbStart;

    private ORBManager() {
    }

    /**
     * Initialise the ORB
     *
     * @param useDb
     *            is using tango db
     * @param adminDeviceName
     *            admin device name
     * @throws DevFailed
     */
    public static synchronized void init(final boolean useDb, final String adminDeviceName) throws DevFailed {
        // Modified properties fo ORB usage.
        final Properties props = System.getProperties();
        props.put("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB");
        props.put("org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton");
        // register interceptors
        props.put("org.omg.PortableInterceptor.ORBInitializerClass.ForwardInit",
                InterceptorInitializer.class.getCanonicalName());
        // Set retry properties
        props.put("jacorb.retries", "0");
        props.put("jacorb.retry_interval", "100");

        props.put("jacorb.codeset", true);
        // props.put("jacorb.config.dir", "fr/esrf/TangoApi");

        // Initial timeout for establishing a connection.
        props.put("jacorb.connection.client.connect_timeout", "5000");

        // Set the Largest transfert.
        final String str = checkORBgiopMaxMsgSize();
        props.put("jacorb.maxManagedBufSize", str);

        // Set jacorb verbosity at minimum value
        props.put("jacorb.config.log.verbosity", "0");

        // only used for no db device
        props.setProperty("jacorb.implname", SERVER_IMPL_NAME);
        // System.setProperties(props);
        // props.setProperty("jacorb.net.tcp_listener",
        // ConnectionListener.class.getName());

        // Initialize ORB
        orb = ORB.init(new String[] {}, props);

        try {
            poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
            // boot_manager =
            // BootManagerHelper.narrow(orb.resolve_initial_references("BootManager"));
        } catch (final InvalidName e) {
            DevFailedUtils.throwDevFailed(e);
        } catch (final INITIALIZE e) {
            // ignore, occurs when starting several times a server that failed
            if (!useDb) {
                DevFailedUtils.throwDevFailed(e);
            }
        }

        try {
            if (!useDb) {
                // If the database is not used, create a POA with the
                // USER_ID policy
                final org.omg.CORBA.Policy[] policies = new org.omg.CORBA.Policy[2];
                policies[0] = poa.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);
                policies[1] = poa.create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
                final org.omg.PortableServer.POAManager manager = poa.the_POAManager();
                poa = poa.create_POA(NODB_POA, manager, policies);
            }
        } catch (final org.omg.PortableServer.POAPackage.AdapterAlreadyExists e) {
            DevFailedUtils.throwDevFailed(e);
        } catch (final org.omg.PortableServer.POAPackage.InvalidPolicy e) {
            DevFailedUtils.throwDevFailed(e);
        }

        final POAManager manager = poa.the_POAManager();
        try {
            manager.activate();
        } catch (final org.omg.PortableServer.POAManagerPackage.AdapterInactive ex) {
            DevFailedUtils.throwDevFailed("API_CantActivatePOAManager", "The POA activate method throws an exception");
        }

        if (useDb) {

            // Build device name and try to import it from database
            final DeviceImportInfo importInfo = DatabaseFactory.getDatabase().importDevice(adminDeviceName);
            if (importInfo.isExported()) {
                LOGGER.debug("{} is set as exported in tango db - checking if it is already running", adminDeviceName);
                // if is exported, try to connect to it
                ORBManager.checkServerRunning(importInfo, adminDeviceName);
            }
        }
    }

    /**
     * Create an {@link Any}
     *
     * @return a Any
     * @throws DevFailed
     */
    public static Any createAny() throws DevFailed {
        return orb.create_any();
    }

    /**
     * Check the server is already running
     *
     * @param importInfo
     * @param toBeImported
     * @throws DevFailed
     */
    private static void checkServerRunning(final DeviceImportInfo importInfo, final String toBeImported)
            throws DevFailed {
        XLOGGER.entry();
        Device_5 devIDL5 = null;
        Device_4 devIDL4 = null;
        Device_3 devIDL3 = null;
        Device_2 devIDL2 = null;
        Device devIDL1 = null;
        try {
            // try IDL5
            try {
                devIDL5 = narrowIDL5(importInfo);
            } catch (final BAD_PARAM e) {
                // try IDL4
                try {
                    devIDL4 = narrowIDL4(importInfo);
                } catch (final BAD_PARAM e4) {
                    // maybe another IDL is currently running
                    // try IDL3
                    try {
                        devIDL3 = narrowIDL3(importInfo);
                    } catch (final BAD_PARAM e1) {
                        // maybe another IDL is currently running
                        // try IDL2
                        try {
                            devIDL2 = narrowIDL2(importInfo);
                        } catch (final BAD_PARAM e2) {
                            // maybe another IDL is currently running
                            // try IDL1
                            try {
                                devIDL1 = narrowIDL1(importInfo);
                            } catch (final BAD_PARAM e3) {
                                // may not occur, unknown CORBA server
                                DevFailedUtils.throwDevFailed(e);
                            }
                        }
                    }
                }
            }
            if (devIDL5 == null && devIDL4 == null && devIDL3 == null && devIDL2 == null && devIDL1 == null) {
                LOGGER.debug("out, device is not running");
            } else {
                checkDeviceName(toBeImported, devIDL5, devIDL4, devIDL3, devIDL2, devIDL1);
            }
        } catch (final org.omg.CORBA.TIMEOUT e) {
            // Receive a Timeout exception ---> It is not running !!!!
            LOGGER.debug("out on TIMEOUT");
        } catch (final BAD_OPERATION e) {
            // System.err.println("Can't pack/unpack data sent to/from database in/to Any object");
            DevFailedUtils.throwDevFailed(e);
        } catch (final TRANSIENT e) {
            LOGGER.debug("out on TRANSIENT, device is not running");
        } catch (final OBJECT_NOT_EXIST e) {
            LOGGER.debug("out on OBJECT_NOT_EXIST, device is not running");
        } catch (final COMM_FAILURE e) {
            LOGGER.debug("out on COMM_FAILURE,, device is not running");
        } catch (final BAD_INV_ORDER e) {
            LOGGER.debug("out on BAD_INV_ORDER,, device is not running");
        }

        XLOGGER.exit();
    }

    private static void checkDeviceName(final String toBeImported, final Device_5 devIDL5, final Device_4 devIDL4,
            final Device_3 devIDL3, final Device_2 devIDL2, final Device devIDL1) throws DevFailed {
        // get the device name from the server
        try {
            if (devIDL5 != null) {
                checkDev(toBeImported, devIDL5.name(), "5");
            } else if (devIDL4 != null) {
                checkDev(toBeImported, devIDL4.name(), "4");
            } else if (devIDL3 != null) {
                checkDev(toBeImported, devIDL3.name(), "3");
            } else if (devIDL2 != null) {
                checkDev(toBeImported, devIDL2.name(), "2");
            } else if (devIDL1 != null) {
                checkDev(toBeImported, devIDL1.name(), "1");
            }

        } catch (final NO_RESPONSE e) {
            DevFailedUtils.throwDevFailed(e);
        } catch (final COMM_FAILURE e) {
            LOGGER.debug("out on COMM_FAILURE, device is not running");
        } catch (final OBJECT_NOT_EXIST e) {
            LOGGER.debug("out on OBJECT_NOT_EXIST, device is not running");
        } catch (final TRANSIENT e) {
            LOGGER.debug("out on TRANSIENT, device is not running");
        } catch (final BAD_INV_ORDER e) {
            LOGGER.debug("out on BAD_INV_ORDER, device is not running");
        }
    }

    private static void checkDev(final String toBeImported, final String deviceName, final String version)
            throws DevFailed {
        if (deviceName.equals(toBeImported)) {
            DevFailedUtils.throwDevFailed(INIT_ERROR, "This server is already running in IDL" + version + ", exiting!");
        }
    }

    private static Device_5 narrowIDL5(final DeviceImportInfo importInfo) throws DevFailed {
        Device_5 dev = null;
        final org.omg.CORBA.Object obj = orb.string_to_object(importInfo.getIor());
        LOGGER.debug("try narrow {} as IDL5 with PID {} because it is exported ", importInfo.getName(),
                importInfo.getPid());
        dev = Device_5Helper.narrow(obj);
        LOGGER.debug("narrow IDL5 done");
        return dev;
    }

    private static Device_4 narrowIDL4(final DeviceImportInfo importInfo) throws DevFailed {
        Device_4 dev = null;
        final org.omg.CORBA.Object obj = orb.string_to_object(importInfo.getIor());
        LOGGER.debug("try narrow {} as IDL4 with PID {} because it is exported ", importInfo.getName(),
                importInfo.getPid());
        dev = Device_4Helper.narrow(obj);
        LOGGER.debug("narrow IDL4 done");
        return dev;
    }

    private static Device_3 narrowIDL3(final DeviceImportInfo importInfo) throws DevFailed {
        Device_3 dev = null;
        final org.omg.CORBA.Object obj = orb.string_to_object(importInfo.getIor());
        LOGGER.debug("try narrow {} as IDL3 with PID {}", importInfo.getName(), importInfo.getPid());
        dev = Device_3Helper.narrow(obj);
        LOGGER.debug("narrow IDL3 done");
        return dev;
    }

    private static Device_2 narrowIDL2(final DeviceImportInfo importInfo) throws DevFailed {
        Device_2 dev = null;
        final org.omg.CORBA.Object obj = orb.string_to_object(importInfo.getIor());
        LOGGER.debug("try narrow {} as IDL2 with PID {}", importInfo.getName(), importInfo.getPid());
        dev = Device_2Helper.narrow(obj);
        LOGGER.debug("narrow IDL2 done");
        return dev;
    }

    private static Device narrowIDL1(final DeviceImportInfo importInfo) throws DevFailed {
        Device dev = null;
        final org.omg.CORBA.Object obj = orb.string_to_object(importInfo.getIor());
        LOGGER.debug("try narrow {} as IDL1 with PID {}", importInfo.getName(), importInfo.getPid());
        dev = DeviceHelper.narrow(obj);
        LOGGER.debug("narrow IDL1 done");
        return dev;
    }

    /**
     * Start the ORB. Blocks until stopped.
     */
    private static void start() {
        if (orb != null) {
            orb.run();
        }
    }

    /**
     * Start the ORB. non blocking.
     */
    public static void startDetached() {
        orbStart = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(final Runnable r) {
                return new Thread(r, "ORB run");
            }
        });
        orbStart.submit(new StartTask());
        LOGGER.debug("ORB started");
    }

    private static class StartTask implements Callable {
        @Override
        public Void call() {
            ORBManager.start();
            return null;
        }
    }

    /**
     * Check if the checkORBgiopMaxMsgSize has been set. This environment
     * variable should be set in Mega bytes.
     */
    private static String checkORBgiopMaxMsgSize() {
        /*
         * JacORB definition (see jacorb.properties file):
         *
         * This is NOT the maximum buffer size that can be used, but just the
         * largest size of buffers that will be kept and managed. This value
         * will be added to an internal constant of 5, so the real value in
         * bytes is 2**(5+maxManagedBufSize-1). You only need to increase this
         * value if you are dealing with LOTS of LARGE data structures. You may
         * decrease it to make the buffer manager release large buffers
         * immediately rather than keeping them for later reuse.
         */
        String str = "20"; // Set to 16 Mbytes

        // Check if environment ask for bigger size.
        final String tmp = System.getProperty("ORBgiopMaxMsgSize");
        if (tmp != null && checkBufferSize(tmp) != null) {
            str = tmp;
        }
        return str;
    }

    private static String checkBufferSize(final String str) {
        String result = null;
        // try to get value
        int nbMega = 0;
        try {
            nbMega = Integer.parseInt(str);
        } catch (final NumberFormatException e) {
        }

        // Compute the real size and the power of 2
        final long size = (long) nbMega * 1024 * 1024;
        long l = size;
        int cnt;
        for (cnt = 0; l > 0; cnt++) {
            l >>= 1;
        }
        cnt--;

        // Check if number ob Mb is not power of 2
        if (Math.pow(2, cnt) < size) {
            cnt++;
        }
        // System.out.println(nb_mega + " Mbytes  (2^" + cnt + ")");

        final int jacorbSize = cnt - 4;
        result = Integer.toString(jacorbSize);
        return result;
    }

    /**
     * Get the ORB
     *
     * @return the ORB
     * @throws DevFailed
     */
    public static ORB getOrb() throws DevFailed {
        if (orb == null) {
            DevFailedUtils.throwDevFailed("ORB not initialized");
        }
        return orb;
    }

    /**
     * Get the POA
     *
     * @return the POA
     * @throws DevFailed
     */
    public static POA getPoa() throws DevFailed {
        if (poa == null) {
            DevFailedUtils.throwDevFailed("ORB not initialized");
        }
        return poa;
    }

    /**
     * Shutdown the ORB
     */
    public static void shutdown() {
        if (orbStart != null) {
            orbStart.shutdown();
        }
        if (orb != null) {
            orb.shutdown(true);
            LOGGER.debug("ORB shutdown");
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy