Package org.eclipse.ecf.provider.zookeeper.core

Source Code of org.eclipse.ecf.provider.zookeeper.core.ZooDiscoveryContainer

/*******************************************************************************
*  Copyright (c)2010 REMAIN B.V. The Netherlands. (http://www.remainsoftware.com).
*  All rights reserved. This program and the accompanying materials
*  are made available under the terms of the Eclipse Public License v1.0
*  which accompanies this distribution, and is available at
*  http://www.eclipse.org/legal/epl-v10.html
*
*  Contributors:
*     Wim Jongman - initial API and implementation
*     Ahmed Aadel - initial API and implementation    
*******************************************************************************/
package org.eclipse.ecf.provider.zookeeper.core;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.zookeeper.server.NIOServerCnxn;
import org.apache.zookeeper.server.NIOServerCnxn.Factory;
import org.apache.zookeeper.server.PurgeTxnLog;
import org.apache.zookeeper.server.ServerConfig;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.server.quorum.QuorumPeer;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ecf.core.ContainerConnectException;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.ecf.core.identity.Namespace;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter;
import org.eclipse.ecf.discovery.IServiceInfo;
import org.eclipse.ecf.discovery.IServiceListener;
import org.eclipse.ecf.discovery.IServiceTypeListener;
import org.eclipse.ecf.discovery.identity.IServiceID;
import org.eclipse.ecf.discovery.identity.IServiceTypeID;
import org.eclipse.ecf.provider.zookeeper.core.internal.Advertiser;
import org.eclipse.ecf.provider.zookeeper.core.internal.Configuration;
import org.eclipse.ecf.provider.zookeeper.core.internal.Configurator;
import org.eclipse.ecf.provider.zookeeper.core.internal.Localizer;
import org.eclipse.ecf.provider.zookeeper.core.internal.Notification;
import org.eclipse.ecf.provider.zookeeper.node.internal.WatchManager;
import org.eclipse.ecf.provider.zookeeper.util.Geo;
import org.eclipse.ecf.provider.zookeeper.util.Logger;
import org.eclipse.ecf.provider.zookeeper.util.PrettyPrinter;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;

public class ZooDiscoveryContainer extends AbstractDiscoveryContainerAdapter {

  private static ZooDiscoveryContainer discovery;
  public static ExecutorService CACHED_THREAD_POOL = Executors.newCachedThreadPool();
  private QuorumPeer quorumPeer;
  private Properties DiscoveryProperties;
  protected Advertiser advertiser;
  protected Localizer localizer;
  private static ZooKeeperServer zooKeeperServer;
  private ID targetId;
  protected boolean isQuorumPeerReady;
  private boolean isConnected;
  private boolean isDisposed;
  private WatchManager watchManager;

  public enum FLAVOR {
    STANDALONE, CENTRALIZED, REPLICATED;

    public String toString() {
      switch (this) {
      case STANDALONE:
        return DefaultDiscoveryConfig.ZOODISCOVERY_FLAVOR_STANDALONE;
      case CENTRALIZED:
        return DefaultDiscoveryConfig.ZOODISCOVERY_FLAVOR_CENTRALIZED;
      case REPLICATED:
        return DefaultDiscoveryConfig.ZOODISCOVERY_FLAVOR_REPLICATED;
      }
      throw new AssertionError("Unsupported configuration");
    }
  }

  private ZooDiscoveryContainer() {
    super(ZooDiscoveryNamespace.NAME, Configurator.INSTANCE);
    DiscoveryProperties = new Properties();
   
    if (autoStart()) {
      try {
        this.targetId = this.getConnectNamespace().createInstance(new String[] { DefaultDiscoveryConfig.getDefaultTarget() });
        init(targetId);

      } catch (Exception e) {
        Logger.log(LogService.LOG_ERROR, e.getMessage(), e);
      }
    }

    Logger.log(LogService.LOG_INFO, PrettyPrinter.prompt(PrettyPrinter.ACTIVATED, null), null);

  }

  /**
   * @return true if the service is in autoStart mode.
   */
  public static boolean autoStart() {
    return System.getProperty(DefaultDiscoveryConfig.ZOODISCOVERY_PREFIX + DefaultDiscoveryConfig.ZOOKEEPER_AUTOSTART) != null;
  }

  public synchronized static ZooDiscoveryContainer getSingleton() {
    if (discovery == null) {
      discovery = new ZooDiscoveryContainer();
    }
    discovery.setDisposed(false);
    return discovery;
  }

  public void init(ServiceReference reference) {
    Configuration conf = Configurator.INSTANCE.createConfig(reference).configure();
    doStart(conf);
  }

  private void init(ID targetID) {
    Configuration conf = Configurator.INSTANCE.createConfig(targetID).configure();
    doStart(conf);
  }

  private void doStart(final Configuration conf) {
    if (watchManager != null && !watchManager.isDisposed())
      return;

    watchManager = new WatchManager(conf);
    this.advertiser = Advertiser.getSingleton(watchManager);
    this.localizer = Localizer.getSingleton();
    if (conf.isCentralized()) {
      if (Geo.getHost().equals(conf.getServerIps().split(":")[0])) { //$NON-NLS-1$
        CACHED_THREAD_POOL.execute(new Runnable() {
          public void run() {
            startStandAlone(conf);
            watchManager.watch();
            ZooDiscoveryContainer.this.localizer.init();
          }
        });

      } else {
        watchManager.watch();
        this.localizer.init();
      }

    } else if (conf.isQuorum()) {
      CACHED_THREAD_POOL.execute(new Runnable() {
        public void run() {
          startQuorumPeer(conf);
          watchManager.watch();
          ZooDiscoveryContainer.this.localizer.init();
        }
      });
    }

    else if (conf.isStandAlone()) {
      CACHED_THREAD_POOL.execute(new Runnable() {
        public void run() {
          startStandAlone(conf);
          watchManager.watch();
          ZooDiscoveryContainer.this.localizer.init();
        }
      });
    }
  }

  /**
   * Start a ZooKeeer server locally to write nodes to. Implied by
   * {@link IDiscoveryConfig#ZOODISCOVERY_FLAVOR_STANDALONE} configuration.
   *
   * @param conf
   */
  void startStandAlone(final Configuration conf) {

    if (ZooDiscoveryContainer.zooKeeperServer != null && ZooDiscoveryContainer.zooKeeperServer.isRunning())
      return;
    else if (ZooDiscoveryContainer.zooKeeperServer != null && !ZooDiscoveryContainer.zooKeeperServer.isRunning())
      try {
        ZooDiscoveryContainer.zooKeeperServer.startup();
        return;
      } catch (Exception e) {
        Logger.log(LogService.LOG_DEBUG, "Zookeeper server cannot be started! ", e);//$NON-NLS-1$       
      }

    try {
      ZooDiscoveryContainer.zooKeeperServer = new ZooKeeperServer();
      FileTxnSnapLog fileTxnSnapLog = new FileTxnSnapLog(conf.getZookeeperDataFile(), conf.getZookeeperDataFile());
      ZooDiscoveryContainer.zooKeeperServer.setTxnLogFactory(fileTxnSnapLog);
      ZooDiscoveryContainer.zooKeeperServer.setTickTime(conf.getTickTime());
      Factory cnxnFactory = new NIOServerCnxn.Factory(new InetSocketAddress(conf.getClientPort()));
      cnxnFactory.startup(ZooDiscoveryContainer.zooKeeperServer);
    } catch (Exception e) {
      Logger.log(LogService.LOG_ERROR,
          "Zookeeper server cannot be started! Possibly another instance is already running on the same port. ", e);
    }

  }

  /**
   * Start a local ZooKeeer server to write nodes to. It plays as a peer
   * within a replicated servers configuration. Implied by
   * {@link IDiscoveryConfig#ZOODISCOVERY_FLAVOR_REPLICATED} configuration.
   *
   * @param conf
   */
  void startQuorumPeer(final Configuration conf) {
    if (this.quorumPeer != null && this.quorumPeer.isAlive()) {
      return;
    } else if (this.quorumPeer != null && !this.quorumPeer.isAlive()) {
      this.quorumPeer.start();
      return;
    }
    try {
      final QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
      quorumPeerConfig.parse(conf.getConfFile());
      QuorumPeer.Factory qpFactory = new QuorumPeer.Factory() {
        public QuorumPeer create(NIOServerCnxn.Factory cnxnFactory) throws IOException {
          ServerConfig serverConfig = new ServerConfig();
          serverConfig.readFrom(quorumPeerConfig);
          QuorumPeer peer = new QuorumPeer(quorumPeerConfig.getServers(), new File(serverConfig.getDataDir()), new File(
              serverConfig.getDataLogDir()), quorumPeerConfig.getElectionAlg(), quorumPeerConfig.getServerId(),
              quorumPeerConfig.getTickTime(), quorumPeerConfig.getInitLimit(), quorumPeerConfig.getSyncLimit(), cnxnFactory,
              quorumPeerConfig.getQuorumVerifier());
          ZooDiscoveryContainer.this.quorumPeer = peer;
          return peer;
        }

        public NIOServerCnxn.Factory createConnectionFactory() throws IOException {
          return new NIOServerCnxn.Factory(quorumPeerConfig.getClientPortAddress());
        }
      };
      quorumPeer = qpFactory.create(qpFactory.createConnectionFactory());
      quorumPeer.start();
      quorumPeer.setDaemon(true);
      isQuorumPeerReady = true;
    } catch (Exception e) {
      Logger.log(LogService.LOG_ERROR, "Zookeeper quorum cannot be started! ", e); //$NON-NLS-1$
      isQuorumPeerReady = false;
    }
  }

  public void setDiscoveryProperties(Properties discoveryProperties) {
    this.DiscoveryProperties = discoveryProperties;
  }

  public Properties getDiscoveryProperties() {
    return this.DiscoveryProperties;
  }

  public synchronized void shutdown() {
    if (isDisposed)
      return;

    try {
      if (watchManager != null) {
        watchManager.dispose();
      }

      if (this.localizer != null) {
        this.localizer.close();
      }
      if (ZooDiscoveryContainer.zooKeeperServer != null) {
        // purge snaps and logs. Keep only last three of each
        PurgeTxnLog.purge(ZooDiscoveryContainer.zooKeeperServer.getTxnLogFactory().getDataDir(), ZooDiscoveryContainer.zooKeeperServer.getTxnLogFactory()
            .getSnapDir(), 3);
        ZooDiscoveryContainer.zooKeeperServer.shutdown();
      }
      if (this.quorumPeer != null) {
        // purge snaps and logs. Keep only last three of each
        PurgeTxnLog.purge(this.quorumPeer.getTxnFactory().getDataDir(), this.quorumPeer.getTxnFactory().getSnapDir(), 3);
        // shut down server
        if (this.quorumPeer.isAlive()) {
          this.quorumPeer.shutdown();
        }
        // shutdown sockets
        this.quorumPeer.getCnxnFactory().shutdown();
      }

    } catch (Throwable t) {
      Logger.log(LogService.LOG_ERROR, t.getMessage(), t);
    }

    targetId = null;
    isConnected = false;
    isDisposed = true;
    discovery = null;
  }

  public ZooKeeperServer getLocalServer() {
    return ZooDiscoveryContainer.zooKeeperServer;
  }

  public void connect(ID id, IConnectContext connectContext) throws ContainerConnectException {
    if (isDisposed)
      throw new ContainerConnectException("Container already disposed!");
    if (this.isConnected)
      throw new ContainerConnectException("Container already connected!");
    this.targetId = id;
    if (this.targetId == null) {
      this.targetId = this.getConnectNamespace().createInstance(new String[] { DefaultDiscoveryConfig.getDefaultTarget() });
    }
    init(this.targetId);
    isConnected = true;
  }

  public void disconnect() {
    if (watchManager != null) {
      watchManager.dispose();
    }

    isConnected = false;
    targetId = null;
  }

  public Namespace getConnectNamespace() {
    return super.getConnectNamespace();
  }

  public ID getConnectedID() {
    if (!isConnected || isDisposed)
      return null;

    return this.targetId;
  }

  public IServiceInfo getServiceInfo(IServiceID serviceID) {
    Assert.isNotNull(serviceID);
    return watchManager.getAllKnownServices().get(serviceID.getName());
  }

  public IServiceTypeID[] getServiceTypes() {
    IServiceTypeID ids[] = new IServiceTypeID[getServices().length];
    for (int i = 0; i < ids.length; i++) {
      ids[i] = getServices()[i].getServiceID().getServiceTypeID();
    }
    return ids;
  }

  public IServiceInfo[] getServices() {
    if (watchManager == null) {
      return new IServiceInfo[0];
    }
    return watchManager.getAllKnownServices().values().toArray(new IServiceInfo[watchManager.getAllKnownServices().size()]);
  }

  public IServiceInfo[] getServices(IServiceTypeID type) {
    Assert.isNotNull(type);
    if (watchManager == null) {
      return new IServiceInfo[0];
    }
    List<IServiceInfo> services = new ArrayList<IServiceInfo>();
    for (IServiceInfo sinfo : watchManager.getAllKnownServices().values()) {
      if (sinfo.getServiceID().getServiceTypeID().getInternal() == type.getInternal())
        services.add(sinfo);
    }
    return services.toArray(new IServiceInfo[services.size()]);
  }

  public Namespace getServicesNamespace() {
    return super.getServicesNamespace();
  }

  public synchronized void registerService(IServiceInfo serviceInfo) {
    Assert.isNotNull(serviceInfo);
    if (targetId == null) {
      this.targetId = this.getConnectNamespace().createInstance(new String[] { DefaultDiscoveryConfig.getDefaultTarget() });
      init(this.targetId);
    }

    if (serviceInfo instanceof AdvertisedService) {
      watchManager.publish((AdvertisedService) serviceInfo);
    } else {
      watchManager.publish(new AdvertisedService(serviceInfo));
    }
    Localizer.getSingleton().localize(new Notification(serviceInfo, Notification.AVAILABLE));

  }

  public void unregisterAllServices() {
    watchManager.unpublishAll();
  }

  public void unregisterService(IServiceInfo serviceInfo) {
    Assert.isNotNull(serviceInfo);
    watchManager.unpublish(serviceInfo.getServiceID().getName());

    Localizer.getSingleton().localize(new Notification(serviceInfo, Notification.UNAVAILABLE));
  }

  public Collection<IServiceListener> getAllServiceListeners() {
    return super.allServiceListeners;
  }

  public Collection<IServiceListener> getServiceListenersForType(IServiceTypeID type) {
    return super.getListeners(type);
  }

  public Collection<IServiceTypeListener> getServiceTypeListeners() {
    return super.serviceTypeListeners;
  }

  public void dispose() {
    shutdown();
    super.dispose();
  }

  public ID getID() {
    return Configurator.INSTANCE.getID();
  }

  public boolean isDisposed() {
    return this.isDisposed;
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#getContainerName
   * ()
   */
  public String getContainerName() {
    return ZooDiscoveryContainerInstantiator.NAME;
  }

  private void setDisposed(boolean d) {
    this.isDisposed = d;
  }
}
TOP

Related Classes of org.eclipse.ecf.provider.zookeeper.core.ZooDiscoveryContainer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.