Package com.linkedin.helix.participant

Source Code of com.linkedin.helix.participant.DistClusterControllerElection

/**
* Copyright (C) 2012 LinkedIn Inc <opensource@linkedin.com>
*
* 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.
*/
package com.linkedin.helix.participant;

import java.lang.management.ManagementFactory;

import org.apache.log4j.Logger;

import com.linkedin.helix.ControllerChangeListener;
import com.linkedin.helix.HelixDataAccessor;
import com.linkedin.helix.HelixManager;
import com.linkedin.helix.HelixManagerFactory;
import com.linkedin.helix.InstanceType;
import com.linkedin.helix.NotificationContext;
import com.linkedin.helix.PropertyKey.Builder;
import com.linkedin.helix.PropertyType;
import com.linkedin.helix.controller.GenericHelixController;
import com.linkedin.helix.controller.HelixControllerMain;
import com.linkedin.helix.controller.restlet.ZKPropertyTransferServer;
import com.linkedin.helix.model.LeaderHistory;
import com.linkedin.helix.model.LiveInstance;

// TODO: merge with GenericHelixController
public class DistClusterControllerElection implements ControllerChangeListener
{
  private static Logger                LOG         =
                                                       Logger.getLogger(DistClusterControllerElection.class);
  private final String                 _zkAddr;
  private final GenericHelixController _controller = new GenericHelixController();
  private HelixManager                 _leader;

  public DistClusterControllerElection(String zkAddr)
  {
    _zkAddr = zkAddr;
  }

  /**
   * may be accessed by multiple threads: zk-client thread and
   * ZkHelixManager.disconnect()->reset() TODO: Refactor accessing HelixMaangerMain class
   * statically
   */
  @Override
  public synchronized void onControllerChange(NotificationContext changeContext)
  {
    HelixManager manager = changeContext.getManager();
    if (manager == null)
    {
      LOG.error("missing attributes in changeContext. requires HelixManager");
      return;
    }

    InstanceType type = manager.getInstanceType();
    if (type != InstanceType.CONTROLLER && type != InstanceType.CONTROLLER_PARTICIPANT)
    {
      LOG.error("fail to become controller because incorrect instanceType (was "
          + type.toString() + ", requires CONTROLLER | CONTROLLER_PARTICIPANT)");
      return;
    }

    try
    {
      if (changeContext.getType().equals(NotificationContext.Type.INIT)
          || changeContext.getType().equals(NotificationContext.Type.CALLBACK))
      {
        // DataAccessor dataAccessor = manager.getDataAccessor();
        HelixDataAccessor accessor = manager.getHelixDataAccessor();
        Builder keyBuilder = accessor.keyBuilder();

        while (accessor.getProperty(keyBuilder.controllerLeader()) == null)
        {
          boolean success = tryUpdateController(manager);
          if (success)
          {
            updateHistory(manager);
            if (type == InstanceType.CONTROLLER)
            {
              HelixControllerMain.addListenersToController(manager, _controller);
              manager.startTimerTasks();
            }
            else if (type == InstanceType.CONTROLLER_PARTICIPANT)
            {
              String clusterName = manager.getClusterName();
              String controllerName = manager.getInstanceName();
              _leader =
                  HelixManagerFactory.getZKHelixManager(clusterName,
                                                        controllerName,
                                                        InstanceType.CONTROLLER,
                                                        _zkAddr);

              _leader.connect();
              _leader.startTimerTasks();
              HelixControllerMain.addListenersToController(_leader, _controller);
            }

          }
        }
      }
      else if (changeContext.getType().equals(NotificationContext.Type.FINALIZE))
      {

        if (_leader != null)
        {
          _leader.disconnect();
        }
      }

    }
    catch (Exception e)
    {
      LOG.error("Exception when trying to become leader", e);
    }
  }

  private boolean tryUpdateController(HelixManager manager)
  {
    // DataAccessor dataAccessor = manager.getDataAccessor();
    HelixDataAccessor accessor = manager.getHelixDataAccessor();
    Builder keyBuilder = accessor.keyBuilder();

    LiveInstance leader = new LiveInstance(manager.getInstanceName());
    try
    {
      leader.setLiveInstance(ManagementFactory.getRuntimeMXBean().getName());
      // TODO: this session id is not the leader's session id in distributed mode
      leader.setSessionId(manager.getSessionId());
      leader.setHelixVersion(manager.getVersion());
      if(ZKPropertyTransferServer.getInstance() != null)
      {
        String zkPropertyTransferServiceUrl = ZKPropertyTransferServer.getInstance().getWebserviceUrl();
        if(zkPropertyTransferServiceUrl != null)
        {
          leader.setWebserviceUrl(zkPropertyTransferServiceUrl);
        }
      }
      else
      {
        LOG.warn("ZKPropertyTransferServer instnace is null");
      }
      boolean success = accessor.createProperty(keyBuilder.controllerLeader(), leader);
      if (success)
      {
        return true;
      }
      else
      {
        LOG.info("Unable to become leader probably because some other controller becames the leader");
      }
    }
    catch (Exception e)
    {
      LOG.error("Exception when trying to updating leader record in cluster:"
                    + manager.getClusterName()
                    + ". Need to check again whether leader node has been created or not",
                e);
    }

    leader = accessor.getProperty(keyBuilder.controllerLeader());
    if (leader != null)
    {
      String leaderName = leader.getInstanceName(); // leader.getLeader();
      LOG.info("Leader exists for cluster:" + manager.getClusterName()
          + ", currentLeader:" + leaderName);

      if (leaderName != null && leaderName.equals(manager.getInstanceName()))
      {
        return true;
      }
    }

    return false;
  }

  private void updateHistory(HelixManager manager)
  {
    HelixDataAccessor accessor = manager.getHelixDataAccessor();
    Builder keyBuilder = accessor.keyBuilder();

    LeaderHistory history = accessor.getProperty(keyBuilder.controllerLeaderHistory());
    if (history == null)
    {
      history = new LeaderHistory(PropertyType.HISTORY.toString());
    }
    history.updateHistory(manager.getClusterName(), manager.getInstanceName());
    accessor.setProperty(keyBuilder.controllerLeaderHistory(), history);
  }
}
TOP

Related Classes of com.linkedin.helix.participant.DistClusterControllerElection

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.