orca.shirako.container.ActorLiveness.java Source code

Java tutorial

Introduction

Here is the source code for orca.shirako.container.ActorLiveness.java

Source

/*
* Copyright (c) 2011 RENCI/UNC Chapel Hill 
*
* @author Anirban Mandal
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
* and/or hardware specification (the "Work") to deal in the Work without restriction, including 
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
* sell copies of the Work, and to permit persons to whom the Work is furnished to do so, subject to 
* the following conditions:  
* The above copyright notice and this permission notice shall be included in all copies or 
* substantial portions of the Work.  
*
* THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
* OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS 
* IN THE WORK.
*/

package orca.shirako.container;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import orca.ektorp.actor;
import orca.ektorp.client.OrcaStdHttpClient;
import orca.ektorp.repository.ActorRepository;

import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.ektorp.CouchDbConnector;
import org.ektorp.CouchDbInstance;
import org.ektorp.ReplicationCommand;
import org.ektorp.ReplicationStatus;
import org.ektorp.impl.StdCouchDbInstance;

/**
 *
 * @author anirban
 * @author claris (Add logic for distributed acto registry with Couchdb Backend)
 */
public class ActorLiveness {

    private static ArrayList<Timer> timers = new ArrayList<Timer>();
    private static boolean noStart = false;
    private String act_guid;
    private String registryUrl = null;
    private String registryMethod = null;

    public ActorLiveness(String input_act_guid, String input_registryUrl, String input_registryMethod) {
        act_guid = input_act_guid;
        registryUrl = input_registryUrl;
        registryMethod = input_registryMethod;

        Timer timer = null;
        synchronized (timers) {
            if (noStart)
                return;
            timer = new Timer("ActorLiveness: " + act_guid, true);
            timers.add(timer);
        }
        timer.schedule(new TalkToRegistry(), 60 * 1000, 60 * 1000);
    }

    public ActorLiveness(String input_act_guid, String input_registryUrl) {
        act_guid = input_act_guid;
        registryUrl = input_registryUrl;

        Timer timer = null;
        synchronized (timers) {
            if (noStart)
                return;
            timer = new Timer("ActorLiveness: " + act_guid, true);
            timers.add(timer);
        }
        timer.schedule(new TalkToRegistry2(), 60 * 1000, 60 * 1000);
    }

    public static void allStop() {
        Globals.Log.info("Shutting down liveness threads");
        synchronized (timers) {
            noStart = true;
            for (Timer t : timers) {
                t.cancel();
            }
            timers.clear();
        }
    }

    class TalkToRegistry extends TimerTask {
        private SimpleHttpConnectionManager connMgr;
        private HttpClient httpClient;
        private XmlRpcClient xmlrpcClient;
        private XmlRpcClientConfigImpl xmlrpcClientConfig;
        private XmlRpcCommonsTransportFactory transportFactory;

        protected TalkToRegistry() {
            super();

            // We use our own HttpClient with an HttpConnectionManager
            // configured with timeouts, so we don't block the liveness
            // thread forever.

            // Connect timeout, 10 seconds; Read timeout, 5 seconds; Close timeout, 3 seconds.
            connMgr = new SimpleHttpConnectionManager(true);
            connMgr.getParams().setConnectionTimeout(10 * 1000);
            connMgr.getParams().setSoTimeout(5 * 1000);
            connMgr.getParams().setLinger(3);

            httpClient = new HttpClient(connMgr);

            // We use XmlRpcCommonsTransportFactory, initialized
            // using the HttpClient from above, so that SSLContexts
            // work.
            xmlrpcClient = new XmlRpcClient();
            xmlrpcClientConfig = new XmlRpcClientConfigImpl();
            transportFactory = new XmlRpcCommonsTransportFactory(xmlrpcClient);
            transportFactory.setHttpClient(httpClient);
            xmlrpcClient.setTransportFactory(transportFactory);

            // Finally - since the SimpleHttpConnectionManager only
            // provides one backend HttpConnection, ensure that the
            // XmlRpcClient only has one backend worker available to
            // consume it.
            xmlrpcClient.setMaxThreads(1);
        }

        public boolean cancel() {
            connMgr.shutdown();
            return super.cancel();
        }

        public void run() {
            try {
                Vector<String> params = new Vector<String>();
                // This order of insert is very important, because
                // the xml-rpc server expects the strings in this
                // order
                params.addElement(act_guid);

                try {
                    Globals.Log.debug("Liveness check for Actor:" + act_guid);

                    xmlrpcClientConfig.setServerURL(new URL(registryUrl + "/"));

                    // Set identity for SSL.
                    RemoteRegistryCache.getMultiKeyManager().setCurrentGuid(act_guid);

                    // FIXME: Parse the return? (STATUS: SUCCESS or STATUS: ERROR)
                    String status = (String) xmlrpcClient.execute(xmlrpcClientConfig, registryMethod, params);

                    Globals.Log.info("XMLRPC registry returned  heartbeat status: " + status);
                } catch (MalformedURLException mue) {
                    Globals.Log.error("Registry server URL is invalid.", mue);
                } catch (Exception ex) {
                    Globals.Log.error("Could not connect to the registry server; registry server may be down", ex);
                }
            } catch (Exception e) {
                Globals.Log.error("Registry1: An error occurred while attempting to send heartbeats for actor: "
                        + act_guid + " to external registry", e);
            }
        }
    }

    class TalkToRegistry2 extends TimerTask {
        public void run() {
            try {

                try {
                    String workingActor = DistributedRemoteRegistryCache.getWorkingActorRegistry(Globals
                            .getContainer().getConfiguration().getProperty(OrcaContainer.PropertyRegistryUrl_1));
                    org.ektorp.http.HttpClient sslClient = new OrcaStdHttpClient.Builder()
                            //.url(Globals.getContainer().getConfiguration().getProperty(OrcaContainer.PropertyRegistryUrl_1))
                            .url(workingActor.trim())
                            .username(Globals.getContainer().getConfiguration()
                                    .getProperty(OrcaContainer.PropertyRegistryCouchDBUsername).trim())
                            .password(Globals.getContainer().getConfiguration()
                                    .getProperty(OrcaContainer.PropertyRegistryCouchDBPassword).trim())
                            .enableSSL(true).keyManager(DistributedRemoteRegistryCache.getMultiKeyManager())
                            .trustManager(DistributedRemoteRegistryCache.getTrustManager()).socketTimeout(60000)
                            .relaxedSSLSettings(true).port(6984).build();

                    CouchDbInstance dbInstance = new StdCouchDbInstance(sslClient);
                    CouchDbConnector db = dbInstance.createConnector("actor", true);
                    ActorRepository repo = new ActorRepository(db);
                    actor toupdate = repo.get(act_guid);
                    repo.update(toupdate);
                    String replicationMode = Globals.getContainer().getConfiguration()
                            .getProperty(OrcaContainer.PropertyReplicationMode);

                    if (replicationMode != null && replicationMode.contains("client")) {
                        DistributedRemoteRegistryCache.replicateToAllExcept(
                                Globals.getContainer().getConfiguration()
                                        .getProperty(OrcaContainer.PropertyRegistryUrl_1).trim(),
                                workingActor, act_guid, dbInstance);

                    }

                    sslClient.shutdown();

                } catch (MalformedURLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

            } catch (Exception e) {

                Globals.Log.error("Registry An error occurred while attempting to send heartbeats for actor: "
                        + act_guid + " to external registry", e);
            }
        }
    }
}