Package com.linkedin.databus.client.registration

Source Code of com.linkedin.databus.client.registration.DatabusV2ClusterRegistrationImpl$Status

package com.linkedin.databus.client.registration;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.management.MBeanServer;

import org.apache.log4j.Logger;

import com.linkedin.databus.client.DatabusHttpClientImpl;
import com.linkedin.databus.client.DbusPartitionInfoImpl;
import com.linkedin.databus.client.pub.CheckpointPersistenceProvider;
import com.linkedin.databus.client.pub.ClusterCheckpointPersistenceProvider;
import com.linkedin.databus.client.pub.ClusterCheckpointPersistenceProvider.ClusterCheckpointException;
import com.linkedin.databus.client.pub.DatabusClientException;
import com.linkedin.databus.client.pub.DatabusCombinedConsumer;
import com.linkedin.databus.client.pub.DatabusRegistration;
import com.linkedin.databus.client.pub.DbusClusterConsumerFactory;
import com.linkedin.databus.client.pub.DbusClusterInfo;
import com.linkedin.databus.client.pub.DbusPartitionInfo;
import com.linkedin.databus.client.pub.DbusPartitionListener;
import com.linkedin.databus.client.pub.DbusServerSideFilterFactory;
import com.linkedin.databus.client.pub.FetchMaxSCNRequest;
import com.linkedin.databus.client.pub.FlushRequest;
import com.linkedin.databus.client.pub.RegistrationId;
import com.linkedin.databus.client.pub.RelayFindMaxSCNResult;
import com.linkedin.databus.client.pub.RelayFlushMaxSCNResult;
import com.linkedin.databus.client.pub.mbean.ConsumerCallbackStats;
import com.linkedin.databus.client.pub.mbean.ConsumerCallbackStatsMBean;
import com.linkedin.databus.client.pub.mbean.UnifiedClientStats;
import com.linkedin.databus.client.pub.mbean.UnifiedClientStatsMBean;
import com.linkedin.databus.client.pub.monitoring.events.ConsumerCallbackStatsEvent;
import com.linkedin.databus.client.pub.monitoring.events.UnifiedClientStatsEvent;
import com.linkedin.databus.cluster.DatabusCluster;
import com.linkedin.databus.cluster.DatabusCluster.DatabusClusterMember;
import com.linkedin.databus.cluster.DatabusClusterDataNotifier;
import com.linkedin.databus.cluster.DatabusClusterNotifier;
import com.linkedin.databus.core.Checkpoint;
import com.linkedin.databus.core.DatabusComponentStatus;
import com.linkedin.databus.core.data_model.DatabusSubscription;
import com.linkedin.databus.core.monitoring.mbean.AggregatedDbusEventsStatisticsCollector;
import com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector;
import com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollectorMBean;
import com.linkedin.databus.core.monitoring.mbean.StatsCollectors;
import com.linkedin.databus.core.util.InvalidConfigException;
import com.linkedin.databus2.core.DatabusException;
import com.linkedin.databus2.core.filter.DbusKeyCompositeFilterConfig;

public class DatabusV2ClusterRegistrationImpl implements
    DatabusMultiPartitionRegistration, DatabusClusterNotifier, DatabusClusterDataNotifier
{
  public class Status extends DatabusComponentStatus
  {
    public Status()
    {
      super(getStatusName());
    }

    @Override
    public void start()
    {
      try {
        DatabusV2ClusterRegistrationImpl.this.start();
      } catch (Exception e) {
        _log.error("Got exception while trying to start the registration", e);
        throw new RuntimeException(e);
      }
      super.start();
    }

    @Override
    public void shutdown()
    {
      DatabusV2ClusterRegistrationImpl.this.shutdown();
      super.shutdown();
    }

    @Override
    public void pause()
    {
      DatabusV2ClusterRegistrationImpl.this.pause();
      super.pause();
    }

    @Override
    public void resume()
    {
      DatabusV2ClusterRegistrationImpl.this.resume();
      super.resume();
    }

    @Override
    public void suspendOnError(Throwable error)
    {
      DatabusV2ClusterRegistrationImpl.this.suspendOnError(error);
      super.suspendOnError(error);
    }
  }

    /** State of the registration **/
  private RegistrationState _state;

  /** Client-instance wide unique id to locate the registration **/
  private RegistrationId _id;

  /** Client instance **/
  private final DatabusHttpClientImpl _client;

  /** Databus Componenent Status for this registration **/
  private Status _status = new Status();

  /** Child Registrations container **/
  public final Map<DbusPartitionInfo, DatabusRegistration> regMap =
      new HashMap<DbusPartitionInfo, DatabusRegistration>();

  /** Checkpoint Persisitence Provider Config **/
  private final ClusterCheckpointPersistenceProvider.StaticConfig _ckptPersistenceProviderConfig;

  /** Aggregator for relay callback statistics across all partitions */
  private StatsCollectors<ConsumerCallbackStats> _relayCallbackStatsMerger;

  /** Aggregator for bootstrap callback statistics across all partitions */
  private StatsCollectors<ConsumerCallbackStats> _bootstrapCallbackStatsMerger;

  /** Aggregator for unified (and simplified) relay/bootstrap client statistics across all partitions */
  private StatsCollectors<UnifiedClientStats> _unifiedClientStatsMerger;

  /** Aggregator for relay event statistics across all partitions */
  private StatsCollectors<DbusEventsStatisticsCollector> _relayEventStatsMerger;

  /** Aggregator for bootstrap event statistics across all partitions */
  private StatsCollectors<DbusEventsStatisticsCollector> _bootstrapEventStatsMerger;

  /** Registration specific Logger */
  private Logger _log;

  /** Server Side Filter Factory **/
  private final DbusServerSideFilterFactory _serverSideFilterFactory;

  /** Consumer Factory **/
  private final DbusClusterConsumerFactory _consumerFactory;

  /** Partition Listener **/
  private final DbusPartitionListener _partitionListener;

  /** Set of Partitions **/
  private final Set<DbusPartitionInfo> _partitionSet;

  /** Databus Cluster Config **/
  private final DbusClusterInfo _clusterInfo;

  /** Sources list **/
  private final List<String> _sources;

  /** Current Active Nodes **/
  private List<String> _currentActiveNodes;

  /** Partition to node map **/
  private Map<Integer, String> _activePartitionMap;

  private final ClusterRegistrationStaticConfig _clientClusterConfig;

  /** Databus Cluster **/
  private DatabusCluster _cluster;
  private DatabusClusterMember _clusterMember;

  public DatabusV2ClusterRegistrationImpl(RegistrationId id,
                      DatabusHttpClientImpl client,
                      ClusterCheckpointPersistenceProvider.StaticConfig ckptPersistenceProviderConfig,
                      DbusClusterInfo clusterInfo,
                      DbusClusterConsumerFactory consumerFactory,
                      DbusServerSideFilterFactory filterFactory,
                      DbusPartitionListener partitionListener,
                      String[] sources)
  {
    _client = client;
    _id = id;
    _ckptPersistenceProviderConfig = ckptPersistenceProviderConfig;
    _state = RegistrationState.INIT;
    _log = Logger.getLogger(getClass().getName() + (null  == _id ? "" : "." + _id.getId()));
    _consumerFactory = consumerFactory;
    _serverSideFilterFactory = filterFactory;
    _partitionListener = partitionListener;
    _partitionSet = new HashSet<DbusPartitionInfo>();
    _sources = new ArrayList<String>();
    _clusterInfo = clusterInfo;
    _clientClusterConfig = client.getClientStaticConfig().getClientCluster(clusterInfo.getName());

    if ( null != sources)
      _sources.addAll(Arrays.asList(sources));
  }

  /**
   * Set Logger for this registration
   * @param log
   */
  public synchronized void setLogger(Logger log)
  {
    _log = log;
  }

  @Override
  public synchronized boolean start()
      throws IllegalStateException, DatabusClientException
  {
    if (_state == RegistrationState.INIT || _state == RegistrationState.DEREGISTERED)
    {
      String errMsg = "Registration (" + _id + ") cannot be started from its current state, which is " + _state +
                      " .It may only be started from REGISTERED or SHUTDOWN state";
      _log.error(errMsg);
      throw new IllegalStateException(errMsg);
    }

    if (_state.isRunning())
    {
      _log.info("Registration (" + _id + ") already started !!");
      return false;
    }

    String host = null;

    try {
      host = InetAddress.getLocalHost().getHostName();
    } catch (UnknownHostException e) {
      _log.error("Unable to fetch the local hostname !! Trying to fetch IP Address !!", e);
      try
      {
        host = InetAddress.getLocalHost().getHostAddress();
      } catch (UnknownHostException e1) {
        _log.error("Unable to fetch the local IP Address too !! Giving up", e1);
        host = "UNKNOWN_HOST";
      }
    }

    /**
     *  The id below has to be unique within a given cluster. HttpPort is used to get a unique name for service colocated in a single box.
     *  The Container id is not necessarily a sufficient differentiating factor.
     */
    String id = host + "-" + _client.getContainerStaticConfig().getHttpPort() + "-" +  _client.getContainerStaticConfig().getId();

    try {
      _cluster = createCluster();
      _cluster.start();
    } catch (Exception e) {
      _log.fatal("Got exception while trying to create the cluster with id (" + id + ")", e);
      throw new DatabusClientException(e);
    }

    initializeStatsCollectors();

    _log.info("Dabatus cluster object created : " + _cluster + " with id :" + id);

    _clusterMember = _cluster.addMember(id,this);

    boolean joined = _clusterMember.join();

    if ( ! joined )
    {
      _log.fatal("Unable to join the cluster "  + _clusterInfo);
      throw new DatabusClientException("Unable to join the cluster :" + _clusterInfo);
    }
    _state =RegistrationState.STARTED;
    activatePartitions();
    return true;
  }

  @Override
  public synchronized void shutdown() throws IllegalStateException
  {
    boolean left = true;

    if (! _state.isRunning())
    {
      _log.warn("Registration (" + _id + ") is not in running state to be shutdown. Current state :" + _state);
      return;
    }

    for (Entry<DbusPartitionInfo, DatabusRegistration> e : regMap.entrySet())
    {
      _log.info("Shutting registration for Partition :" + e.getKey());
      try
      {
        if ( e.getValue().getState().isRunning())
          e.getValue().shutdown();
      } catch (Exception ex) {
        _log.error("Unable to shutdown registration for partition :" + e.getKey(), ex);
      }
    }

    if ( null != _clusterMember)
      left = _clusterMember.leave();

    if ( !left )
      _log.error("Unable to leave the cluster cleanly !!" + _clusterInfo);
    if (null != _cluster)
        {
            _cluster.shutdown();
      ClusterCheckpointPersistenceProvider.close(_cluster.getClusterName());
        }
    _state = RegistrationState.SHUTDOWN;
  }

  @Override
  public synchronized void pause()
      throws IllegalStateException
  {
    if ( _state == RegistrationState.PAUSED)
      return;

    if ( (_state != RegistrationState.STARTED) && ( _state != RegistrationState.RESUMED))
      throw new IllegalStateException(
          "Registration (" + _id + ") is not in correct state to be paused. Current state :" + _state);

    for (Entry<DbusPartitionInfo, DatabusRegistration> e : regMap.entrySet())
    {
      _log.info("Shutting registration for Partition :" + e.getKey());
      try
      {
        e.getValue().pause();
      } catch (Exception ex) {
        _log.error("Unable to pause registration for partition :" + e.getKey(), ex);
      }
    }
    _state = RegistrationState.PAUSED;
  }

  @Override
  public synchronized void suspendOnError(Throwable ex)
      throws IllegalStateException
  {
    if ( _state == RegistrationState.SUSPENDED_ON_ERROR)
      return;

    if ( !_state.isRunning())
      throw new IllegalStateException(
          "Registration (" + _id + ") is not in correct state to be suspended. Current state :" + _state);

    for (Entry<DbusPartitionInfo, DatabusRegistration> e : regMap.entrySet())
    {
      _log.info("Shutting registration for Partition :" + e.getKey());
      try
      {
        e.getValue().suspendOnError(ex);
      } catch (Exception e1) {
        _log.error("Unable to suspend registration for partition :" + e.getKey(), e1);
      }
    }
    _state = RegistrationState.SUSPENDED_ON_ERROR;
  }

  @Override
  public synchronized void resume() throws IllegalStateException
  {
    if ( _state == RegistrationState.RESUMED)
      return;

    if ( (_state != RegistrationState.PAUSED) && (_state != RegistrationState.SUSPENDED_ON_ERROR))
      throw new IllegalStateException(
          "Registration (" + _id + ") is not in correct state to be resumed. Current state :" + _state);

    for (Entry<DbusPartitionInfo, DatabusRegistration> e : regMap.entrySet())
    {
      _log.info("Shutting registration for Partition :" + e.getKey());
      try
      {
        e.getValue().resume();
      } catch (Exception e1) {
        _log.error("Unable to resume registration for partition :" + e.getKey(), e1);
      }
    }
    _state = RegistrationState.RESUMED;
  }

  @Override
  public RegistrationState getState()
  {
    return _state;
  }

  @Override
  public synchronized boolean deregister() throws IllegalStateException
  {
    if ((_state == RegistrationState.DEREGISTERED) || (_state == RegistrationState.INIT))
      return false;

    if ( _state.isRunning())
      shutdown();

    _client.deregister(this);

    // Clear Child registrations
    regMap.clear();

    _state = RegistrationState.DEREGISTERED;
    return true;
  }

  @Override
  public Collection<DatabusSubscription> getSubscriptions()
  {
    Set<DatabusSubscription> subscriptions = new HashSet<DatabusSubscription>();

    for (Entry<DbusPartitionInfo, DatabusRegistration> e : regMap.entrySet())
    {
      subscriptions.addAll(e.getValue().getSubscriptions());
    }

    return subscriptions;
  }

  @Override
  public DatabusComponentStatus getStatus()
  {
    return _status;
  }

  @Override
  public synchronized Logger getLogger() {
    return _log;
  }

  @Override
  public DatabusRegistration getParent()
  {
    return null;
  }

  @Override
  public synchronized DatabusRegistration withRegId(RegistrationId regId)
      throws DatabusClientException, IllegalStateException
  {
    if ( (_id != null) && (_id.equals(regId)))
      return this;

    if (! RegistrationIdGenerator.isIdValid(regId))
      throw new DatabusClientException("Another registration with the same regId (" + regId + ") already present !!");

    if (_state.isRunning())
      throw new IllegalStateException("Cannot update regId when registration is in running state. RegId :" + _id + ", State :" + _state);

    _id = regId;
    _status = new Status(); // Component Status should use the correct component name

    return this;
  }

  @Override
  public synchronized DatabusRegistration withServerSideFilter(
      DbusKeyCompositeFilterConfig filterConfig)
      throws IllegalStateException
    {
    // Nothing to do
    return this;
  }

  @Override
  public Collection<DbusPartitionInfo> getPartitions()
  {
    Set<DbusPartitionInfo> partitions = new HashSet<DbusPartitionInfo>();

    for ( DbusPartitionInfo p : regMap.keySet())
    {
      partitions.add(p);
    }

    return partitions;
  }

  @Override
  public Checkpoint getLastPersistedCheckpoint()
  {
    throw new RuntimeException("Operation Not supported !!");
  }

  @Override
  public boolean storeCheckpoint(Checkpoint ckpt)
      throws IllegalStateException
  {
    throw new RuntimeException("Operation Not supported !!");
  }

  @Override
  public DbusEventsStatisticsCollectorMBean getRelayEventStats()
  {
    return _relayEventStatsMerger.getStatsCollector();
  }

  @Override
  public DbusEventsStatisticsCollectorMBean getBootstrapEventStats()
  {
    return _bootstrapEventStatsMerger.getStatsCollector();
  }

  @Override
  public ConsumerCallbackStatsMBean getRelayCallbackStats()
  {
    return _relayCallbackStatsMerger.getStatsCollector();
  }

  @Override
  public ConsumerCallbackStatsMBean getBootstrapCallbackStats()
  {
    return _bootstrapCallbackStatsMerger.getStatsCollector();
  }

  @Override
  public UnifiedClientStatsMBean getUnifiedClientStats()
  {
    return _unifiedClientStatsMerger.getStatsCollector();
  }

  @Override
  public RelayFindMaxSCNResult fetchMaxSCN(FetchMaxSCNRequest request)
      throws InterruptedException
  {
    throw new RuntimeException("Operation Not supported !!");
  }

  @Override
  public RelayFlushMaxSCNResult flush(RelayFindMaxSCNResult fetchSCNResult,
      FlushRequest flushRequest) throws InterruptedException
  {
    throw new RuntimeException("Operation Not supported !!");
  }

  @Override
  public RelayFlushMaxSCNResult flush(FetchMaxSCNRequest maxScnRequest,
      FlushRequest flushRequest) throws InterruptedException
  {
    throw new RuntimeException("Operation Not supported !!");
  }

  @Override
  public RegistrationId getRegistrationId()
  {
    return _id;
  }

  @Override
  public Map<DbusPartitionInfo, DatabusRegistration> getPartitionRegs()
  {
    return regMap;
  }

  protected String getStatusName()
  {
    return "Status" + ((_id != null ) ? "_" + _id.getId() : "");
  }

  protected synchronized void initializeStatsCollectors()
  {
    //some safety against null pointers coming from unit tests
    MBeanServer mbeanServer = null;
    int ownerId = -1;
    long pullerThreadDeadnessThresholdMs = UnifiedClientStats.DEFAULT_DEADNESS_THRESHOLD_MS;

    if (null != _client)
    {
      mbeanServer = _client.getMbeanServer();
      ownerId = _client.getContainerStaticConfig().getId();
      pullerThreadDeadnessThresholdMs = _client.getClientStaticConfig().getPullerThreadDeadnessThresholdMs();
    }

    String regId = null != _id ? _id.getId() : "unknownReg";

    ConsumerCallbackStats relayConsumerStats =
        new ConsumerCallbackStats(ownerId, regId + ".callback.relay",
                                  regId, true, false, new ConsumerCallbackStatsEvent());
    ConsumerCallbackStats bootstrapConsumerStats =
        new ConsumerCallbackStats(ownerId, regId + ".callback.bootstrap",
                                  regId, true, false, new ConsumerCallbackStatsEvent());
    UnifiedClientStats unifiedClientStats =
        new UnifiedClientStats(ownerId, regId + ".callback.unified",
                               regId, true, false,
                               pullerThreadDeadnessThresholdMs,
                               new UnifiedClientStatsEvent());
    _relayCallbackStatsMerger = new StatsCollectors<ConsumerCallbackStats>(relayConsumerStats);
    _bootstrapCallbackStatsMerger = new StatsCollectors<ConsumerCallbackStats>(bootstrapConsumerStats);
    _unifiedClientStatsMerger = new StatsCollectors<UnifiedClientStats>(unifiedClientStats);
    _relayEventStatsMerger = new StatsCollectors<DbusEventsStatisticsCollector>(
        new AggregatedDbusEventsStatisticsCollector(ownerId, regId + ".inbound", true, false, mbeanServer));
    _bootstrapEventStatsMerger = new StatsCollectors<DbusEventsStatisticsCollector>(
        new AggregatedDbusEventsStatisticsCollector(ownerId, regId + ".inbound.bs", true, false, mbeanServer));

    if (null != _client)
    {
      _client.getBootstrapEventsStats().addStatsCollector(
          regId, _bootstrapEventStatsMerger.getStatsCollector());
      _client.getInBoundStatsCollectors().addStatsCollector(
          regId, _relayEventStatsMerger.getStatsCollector());
      _client.getRelayConsumerStatsCollectors().addStatsCollector(
          regId, _relayCallbackStatsMerger.getStatsCollector());
      _client.getBootstrapConsumerStatsCollectors().addStatsCollector(
          regId, _bootstrapCallbackStatsMerger.getStatsCollector());
      _client.getUnifiedClientStatsCollectors().addStatsCollector(
          regId, _unifiedClientStatsMerger.getStatsCollector() /* a.k.a. getUnifiedClientStats() */);
      _client.getGlobalStatsMerger().registerStatsCollector(_relayEventStatsMerger);
      _client.getGlobalStatsMerger().registerStatsCollector(_bootstrapEventStatsMerger);
      _client.getGlobalStatsMerger().registerStatsCollector(_relayCallbackStatsMerger);
      _client.getGlobalStatsMerger().registerStatsCollector(_bootstrapCallbackStatsMerger);
      _client.getGlobalStatsMerger().registerStatsCollector(_unifiedClientStatsMerger);
    }
  }

  /**
   * Callback for ClusterManage when a partition getting added
   * @param partition
   * @throws IllegalStateException
   */
  private synchronized void addPartition(DbusPartitionInfo partition)
    throws IllegalStateException, DatabusClientException
  {
    if(_state == RegistrationState.REGISTERED)
    {
      _partitionSet.add(partition);
    } else if ( _state.isRunning()) {
      if ( ! _partitionSet.contains(partition))
      {
        _partitionSet.add(partition);
        activateOnePartition(partition);
      } else {
        _log.info("Partition (" + partition + ") already added !!");
      }
    } else {
      throw new IllegalStateException("Registration is not in correct state to add a partition !! State :" + _state);
    }
  }

  /**
   * Callback to activate partitions when quorum is reached.
   *
   * @throws DatabusException
   */
  private synchronized void activatePartitions()
    throws DatabusClientException
  {
    _state = RegistrationState.STARTED;

    for (DbusPartitionInfo p : _partitionSet)
      activateOnePartition(p);
  }

  /**
   * Callback to activate one partition that was added
   * @param partition
   * @throws DatabusException
   */
  private synchronized void activateOnePartition(DbusPartitionInfo partition)
    throws DatabusClientException
  {
    _log.info("Trying to activate partition :" + partition);

    try
    {
      if ( regMap.containsKey(partition))
      {
        _log.info("Partition (" + partition
            + ") is already added and is currently in state : "
            + regMap.get(partition).getState() + " skipping !!");
        return;
      }

      // Call factories to get consumer callbacks and server-side filter config.
      Collection<DatabusCombinedConsumer> consumers = _consumerFactory.createPartitionedConsumers(_clusterInfo, partition);
      DbusKeyCompositeFilterConfig filterConfig = null;

      if (_serverSideFilterFactory != null)
        filterConfig = _serverSideFilterFactory.createServerSideFilter(_clusterInfo, partition);


      if ( (null == consumers) || (consumers.isEmpty()))
      {
        _log.error("ConsumerFactory for cluster (" + _clusterInfo + ") returned null or empty consumers ");
        throw new DatabusClientException("ConsumerFactory for cluster (" + _clusterInfo + ") returned null or empty consumers");
      }

      // Create Registration
      RegistrationId id = new RegistrationId(_id + "-" + partition.getPartitionId());
      CheckpointPersistenceProvider ckptProvider = createCheckpointPersistenceProvider(partition);

      DatabusV2RegistrationImpl reg = createChildRegistration(id, _client, ckptProvider);
      reg.addDatabusConsumers(consumers);

      String[] srcs = new String[_sources.size()];
      srcs = _sources.toArray(srcs);
      reg.addSubscriptions(srcs);

      regMap.put(partition,reg);
      reg.onRegister();

      // Add Server-Side Filter
      if ( null != filterConfig)
        reg.withServerSideFilter(filterConfig);

      // Notify Listener
      if (null != _partitionListener)
        _partitionListener.onAddPartition(partition, reg);

      // Start the registration
      try {
        reg.start();
      } catch (DatabusClientException e) {
        _log.error("Got exception while starting the registration for partition (" + partition + ")", e);
        throw e;
      }

      //Add partition Specific metrics to cluster-merge
      _relayEventStatsMerger.addStatsCollector(id.getId(), (DbusEventsStatisticsCollector)reg.getRelayEventStats());
      _bootstrapEventStatsMerger.addStatsCollector(id.getId(), (DbusEventsStatisticsCollector)reg.getBootstrapEventStats());
      _relayCallbackStatsMerger.addStatsCollector(id.getId(), (ConsumerCallbackStats)reg.getRelayCallbackStats());
      _bootstrapCallbackStatsMerger.addStatsCollector(id.getId(), (ConsumerCallbackStats)reg.getBootstrapCallbackStats());

      _log.info("Partition (" + partition + ") started !!");
    } catch (DatabusException e) {
      _log.error("Got exception while activating partition(" + partition + ")",e);
      throw new DatabusClientException(e);
    } catch (ClusterCheckpointException e) {
      _log.error("Got exception while activating partition(" + partition + ")",e);
      throw new DatabusClientException(e);
    }
  }

  private DatabusV2RegistrationImpl createChildRegistration(RegistrationId id, DatabusHttpClientImpl client, CheckpointPersistenceProvider ckptProvider)
  {
    return new DatabusClusterChildRegistrationImpl(id, client, this, ckptProvider);
  }

  /**
   * Callback to drop one partition
   *
   * @param partition
   * @throws DatabusException
   */
  private synchronized void dropOnePartition(DbusPartitionInfo partition)
    throws DatabusException
  {
    if(_state == RegistrationState.REGISTERED)
    {
      _partitionSet.remove(partition);
    } else if ( _state.isRunning()) {
      if (! regMap.containsKey(partition))
      {
        _log.warn("Partition (" + partition
            + ") not available to be dropped. skipping !! Active Partitions :" + regMap.keySet());
        return;
      }

      DatabusRegistration reg = regMap.get(partition);

      // Deregister the regMap which will shutdown the partition
      reg.deregister();

      regMap.remove(partition);
      _partitionSet.remove(partition);

      // remove dropped partition specific metrics
      _relayEventStatsMerger.removeStatsCollector(reg.getRegistrationId().getId());
      _bootstrapEventStatsMerger.removeStatsCollector(reg.getRegistrationId().getId());
      _relayCallbackStatsMerger.removeStatsCollector(reg.getRegistrationId().getId());
      _bootstrapCallbackStatsMerger.removeStatsCollector(reg.getRegistrationId().getId());

      // Notify Listener
      _partitionListener.onDropPartition(partition, reg);
    } else {
      throw new IllegalStateException("Registration is not in correct state to drop a partition !! State :" + _state);
    }

  }


  private static class DatabusClusterChildRegistrationImpl
     extends DatabusV2RegistrationImpl
  {

    public DatabusClusterChildRegistrationImpl(RegistrationId id,
        DatabusHttpClientImpl client,
        DatabusRegistration parentReg,
        CheckpointPersistenceProvider ckptProvider)
    {
      super(id, client, ckptProvider);
      setParent(parentReg);
    }

    @Override
    protected void deregisterFromClient()
    {
      //do nothing
    }

    /**
     * Enable per-partition stats only if required by config.
     */
    @Override
    protected synchronized void initializeStatsCollectors()
    {
      MBeanServer mbeanServer =  null;

      if ( null != _client )
      {
        mbeanServer = _client.getClientStaticConfig().isEnablePerConnectionStats() ?
            _client.getMbeanServer() : null;
      }

      int ownerId = null == _client ? -1 : _client.getContainerStaticConfig().getId();
      String regId = null != _id ? _id.getId() : "unknownReg";

      initializeStatsCollectors(regId, ownerId, mbeanServer);

      if (null != _client && _client.getClientStaticConfig().isEnablePerConnectionStats())
      {
        _client.getBootstrapEventsStats().addStatsCollector(regId, _bootstrapEventsStatsCollector );
        _client.getInBoundStatsCollectors().addStatsCollector(regId, _inboundEventsStatsCollector);
        _client.getRelayConsumerStatsCollectors().addStatsCollector(regId, _relayConsumerStats);
        _client.getBootstrapConsumerStatsCollectors().addStatsCollector(regId, _bootstrapConsumerStats);
        _client.getUnifiedClientStatsCollectors().addStatsCollector(regId, _unifiedClientStats);
      }
    }
  }

  @Override
  public synchronized void onGainedPartitionOwnership(int partition)
  {
    _log.info("Partition (" + partition + ") getting added !!");

    DbusPartitionInfo partitionInfo = new DbusPartitionInfoImpl(partition);
    try {
      addPartition(partitionInfo);
    } catch (DatabusClientException e) {
      _log.error("Unable to add partition. Shutting down the cluster !!", e);
      deregister();
    }

  }

  @Override
  public synchronized void onLostPartitionOwnership(int partition)
  {
    _log.info("Partition (" + partition + ") getting removed !!");

    DbusPartitionInfo partitionInfo = new DbusPartitionInfoImpl(partition);
    try {
      dropOnePartition(partitionInfo);
    } catch (DatabusException e) {
      _log.error("Unable to drop partition. Shutting down the cluster !!", e);
      deregister();
    }
  }

  @Override
  public synchronized void onError(int partition)
  {
    _log.error("Error notification received for partition");
    onLostPartitionOwnership(partition);
  }

  @Override
  public synchronized void onReset(int partition)
  {
    _log.error("Reset notification received for partition");
    onLostPartitionOwnership(partition);
  }

  /**
   * Add sources to a given registration object
   * Adding an already existent subscription, will be a no-op.
   *
   * This does not create any new the DatabusRegistration object ( only modifies the current one ).
   * Hence the id of the registration remains the same
   *
   * @throws IllegalStateException if this registration has already been started.
   */
  public synchronized void addSubscriptions(String ... sources)
          throws IllegalStateException
  {
    if ( ! _state.isPreStartState())
      throw new IllegalStateException("Cannot add sources when state is running/shutdown. Current State :" + _state);

    for (String s : sources)
      if (! _sources.contains(s))
        _sources.add(s);
  }

  /**
   * Remove subscriptions from a given registration object
   * Removing a non-existent subscription, will be a no-op.
   *
   * @throws IllegalStateException if this registration has already been started
   */
  public synchronized void removeSubscriptions(String ... sources)
          throws IllegalStateException
  {
    if ( ! _state.isRunning())
      throw new IllegalStateException("Cannot remove sources when state is running. Current State :" + _state);

    for (String s : sources)
      _sources.remove(s);
  }

  /**
   * Callback when registration is added to client Registration Set.
   * @param state
   */
  public synchronized void onRegister()
  {
    _state = RegistrationState.REGISTERED;
  }


  @Override
  public synchronized void onInstanceChange(List<String> activeNodes)
  {
    if ( _currentActiveNodes == null)
      _currentActiveNodes = new ArrayList<String>();

    List<String> newOfflineNodes = new ArrayList<String>();
    List<String> newOnlineNodes = new ArrayList<String>();

    findDiff(_currentActiveNodes,activeNodes,newOfflineNodes);
    findDiff(activeNodes,_currentActiveNodes,newOnlineNodes);

    if ( ! newOfflineNodes.isEmpty())
      _log.info("The following nodes went offline :" + newOfflineNodes);

    if ( ! newOnlineNodes.isEmpty())
      _log.info("The following nodes came online :" + newOnlineNodes);

    _currentActiveNodes.clear();
    _currentActiveNodes.addAll(activeNodes);

  }


  private static void findDiff(Collection<String> lhs, Collection<String> rhs, Collection<String> result)
  {
    for (String c : lhs)
    {
      if (! rhs.contains(c))
        result.add(c);
    }
  }


  @Override
  public synchronized void onPartitionMappingChange(Map<Integer, String> activePartitionMap)
  {
    for (int i = 0 ; i < _clusterInfo.getNumTotalPartitions(); i++)
    {
      if (! activePartitionMap.containsKey(i))
        _log.error("No Client listening to partition : " + i);
    }

    if ( null == _activePartitionMap)
    {
      _activePartitionMap = new HashMap<Integer,String>();
    }

    _activePartitionMap.clear();
    _activePartitionMap.putAll(activePartitionMap);

    _log.info("Current Partition to Client mapping :" + activePartitionMap);
  }

  protected DatabusCluster createCluster() throws Exception
  {
    return new DatabusCluster(_clientClusterConfig);
  }

  protected CheckpointPersistenceProvider createCheckpointPersistenceProvider(DbusPartitionInfo partition)
      throws InvalidConfigException,ClusterCheckpointException
  {
    return new ClusterCheckpointPersistenceProvider(partition.getPartitionId(),_ckptPersistenceProviderConfig);
  }

  public List<String> getCurrentActiveNodes()
  {
    return _currentActiveNodes;
  }

  public Map<Integer, String> getActivePartitionMap()
  {
    return _activePartitionMap;
  }

  public DbusClusterInfo getClusterInfo()
  {
    return _clusterInfo;
  }

  @Override
  public DbusKeyCompositeFilterConfig getFilterConfig()
  {
    return null;
  }
}
TOP

Related Classes of com.linkedin.databus.client.registration.DatabusV2ClusterRegistrationImpl$Status

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.