Package org.goldenorb.zookeeper

Source Code of org.goldenorb.zookeeper.LeaderGroup

/**
* Licensed to Ravel, Inc. under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  Ravel, Inc. licenses this file
* to you 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 org.goldenorb.zookeeper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.goldenorb.conf.OrbConfigurable;
import org.goldenorb.conf.OrbConfiguration;
import org.goldenorb.event.LeadershipChangeEvent;
import org.goldenorb.event.LostMemberEvent;
import org.goldenorb.event.MemberDataChangeEvent;
import org.goldenorb.event.NewMemberEvent;
import org.goldenorb.event.OrbCallback;
import org.goldenorb.event.OrbEvent;
import org.goldenorb.event.OrbExceptionEvent;

/**
* This class defines LeaderGroup, which forms the abstract structure used to coordinate between members.
*
*/
public class LeaderGroup<MEMBER_TYPE extends Member> implements OrbConfigurable {
 
  private OrbConfiguration orbConf;
  private OrbCallback orbCallback;
  private String basePath;
  private String myPath;
  private MEMBER_TYPE member;
  private Class<? extends Member> memberClass;
  private ZooKeeper zk;
  private boolean processWatchedEvents = true;
  private volatile SortedMap<String,MEMBER_TYPE> members = Collections.synchronizedSortedMap(new TreeMap<String,MEMBER_TYPE>());
  private SortedMap<String,MemberDataWatcher> watchers = Collections.synchronizedSortedMap(new TreeMap<String,MemberDataWatcher>());
  private boolean fireEvents = false;
 
  /**
   * Constructor
   *
   * @param zk
   *          - ZooKeeper
   * @param orbCallback
   *          - OrbCallback
   *
   * @param path
   *          - String
   *
   * @param member
   *          - MEMBER_TYPE
   *
   * @param memberClass
   *          - Class <? extends Member>
   */
  public LeaderGroup(ZooKeeper zk,
                     OrbCallback orbCallback,
                     String path,
                     MEMBER_TYPE member,
                     Class<? extends Member> memberClass) {
    this.memberClass = memberClass;
    this.orbCallback = orbCallback;
    this.basePath = path;
    this.member = member;
    this.zk = zk;
    init();
  }
 
  /**
   * Initializes the LeaderGroup.
   */
  public void init() {
    try {
      ZookeeperUtils.notExistCreateNode(zk, basePath);
      myPath = ZookeeperUtils.tryToCreateNode(zk, basePath + "/member", member,
        CreateMode.EPHEMERAL_SEQUENTIAL);
      members.put(myPath, member);
      updateMembers();
      fireEvents = true;
    } catch (OrbZKFailure e) {
      fireEvent(new OrbExceptionEvent(e));
    }
  }
 
  /**
   * Updates members in the group.
   */
  @SuppressWarnings("unchecked")
  public void updateMembers() throws OrbZKFailure {
    synchronized (members) {
      int numOfMembers = getNumOfMembers();
      MEMBER_TYPE leaderMember;
      if (numOfMembers != 0) {
        leaderMember = getLeader();
      } else {
        leaderMember = null;
      }
      List<String> memberList;
      try {
        memberList = zk.getChildren(basePath, new WatchMembers());
      } catch (KeeperException e) {
        e.printStackTrace();
        throw new OrbZKFailure(e);
      } catch (InterruptedException e) {
        e.printStackTrace();
        throw new OrbZKFailure(e);
      }
     
      members.clear();
      MEMBER_TYPE memberW = null;
      for (String memberPath : memberList) {
        MemberDataWatcher watcher = null;
        if (watchers.containsKey(memberPath)) {
          memberW = (MEMBER_TYPE) ZookeeperUtils.getNodeWritable(zk, basePath + "/" + memberPath,
            memberClass, orbConf);
        } else { // set watcher for new node
          watcher = new MemberDataWatcher(memberPath);
          memberW = (MEMBER_TYPE) ZookeeperUtils.getNodeWritable(zk, basePath + "/" + memberPath,
            memberClass, orbConf, watcher);
          if (memberW != null) {
            watchers.put(memberPath, watcher);
          }
        }
        if (memberW != null) {
          members.put(memberPath, memberW);
        }
      }
      // check for watchers that need to be made inactive and removed
      Set<String> watcherSet = watchers.keySet();
      ArrayList<String> toRemove = new ArrayList<String>();
      if (watcherSet != null) {
        for (String memberPath : watcherSet) {
          if (!members.containsKey(memberPath)) {
            watchers.get(memberPath).makeInactive();
            toRemove.add(memberPath);
          }
        }
      }
      for (String memberPath : toRemove) {
        watchers.remove(memberPath);
      }
     
      if (numOfMembers > getNumOfMembers()) {
        fireEvent(new LostMemberEvent());
      } else if (numOfMembers < getNumOfMembers()) {
        fireEvent(new NewMemberEvent());
      }
      if (numOfMembers != 0 && getNumOfMembers() != 0) {
        if (!leaderMember.equals(getLeader())) {
          fireEvent(new LeadershipChangeEvent());
        }
      }
    }
  }
 
  /**
   * This class defines a Watcher for use with each member.
   *
   */
  public class WatchMembers implements Watcher {
   
    /**
     * Updates members based on receiving a Watcher event.
     *
     * @param event
     *          - WatchedEvent
     */
    public void process(WatchedEvent event) {
      if (LeaderGroup.this.isProcessWatchedEvents()) {
        try {
          updateMembers();
        } catch (OrbZKFailure e) {
          fireEvent(new OrbExceptionEvent(e));
        }
      }
    }
  }
 
  /**
   * This class defines a Watch for use with the data in each member.
   *
   */
  public class MemberDataWatcher implements Watcher {
   
    private String nodePath;
    private String nodeName;
    private boolean active;
   
    /**
     * Constructor
     *
     * @param nodeName
     *          - String
     */
    public MemberDataWatcher(String nodeName) {
      this.nodePath = basePath + "/" + nodeName;
      this.nodeName = nodeName;
      // System.err.println("Watcher Created by:  for Node : " + nodePath);
      active = true;
    }
   
    /**
     * Makes this member inactive.
     */
    public void makeInactive() {
      active = false;
    }
   
    /**
     *
     * @param event
     *          - WatchedEvent
     */
    @SuppressWarnings("unchecked")
    @Override
    public void process(WatchedEvent event) {
      if ((event.getType() != Event.EventType.NodeDeleted) && LeaderGroup.this.isProcessWatchedEvents()
          && active) {
        try {
          MEMBER_TYPE node = (MEMBER_TYPE) ZookeeperUtils.getNodeWritable(zk, nodePath, memberClass, orbConf,
            this);
          if (event.getType() == Event.EventType.NodeDataChanged) {
            LeaderGroup.this.updateMembersData(nodeName, node);
          }
        } catch (OrbZKFailure e) {
          e.printStackTrace();
          LeaderGroup.this.fireEvent(new OrbExceptionEvent(e));
        }
      }
    }
  }
 
  /**
   * Updates a member's data.
   *
   * @param memberPath
   *          - String
   * @param update
   *          - MEMBER_TYPE
   */
  public void updateMembersData(String memberPath, MEMBER_TYPE update) {
    if (update != null) {
      members.put(memberPath, update);
      fireEvent(new MemberDataChangeEvent());
    }
  }
 
  /**
   * Return the members
   */
  public Collection<MEMBER_TYPE> getMembers() {
    synchronized (members) {
      return members.values();
    }
  }
 
  /**
   * Return the numOfMembers
   */
  public int getNumOfMembers() {
    synchronized (members) {
      return members.size();
    }
  }
 
  /**
   * Return the true if the calling member is the leader.
   */
  public boolean isLeader() {
    synchronized (members) {
      return member.equals(members.get(members.firstKey()));
    }
  }
 
  /**
   * Return the leader
   */
  public MEMBER_TYPE getLeader() {
    synchronized (members) {
      return members.get(members.firstKey());
    }
  }
 
  /**
   *
   * @param e
   *          - OrbEvent
   */
  public void fireEvent(OrbEvent e) {
    if (fireEvents) {
      orbCallback.process(e);
    }
  }
 
  /**
   * Set the orbConf
   *
   * @param orbConf
   *          - OrbConfiguration
   */
  public void setOrbConf(OrbConfiguration orbConf) {
    this.orbConf = orbConf;
  }
 
  /**
   * Return the orbConf
   */
  public OrbConfiguration getOrbConf() {
    return orbConf;
  }
 
  /**
   * Return the membersPath
   */
  public List<String> getMembersPath() {
    ArrayList<String> paths = new ArrayList<String>();
    Set<String> memberPaths = members.keySet();
    for (String memberPath : memberPaths) {
      paths.add(basePath + "/" + memberPath);
    }
    return paths;
  }
 
  /**
   * Return the myPath
   */
  public String getMyPath() {
    return myPath;
  }
 
  /**
   * Leaves the LeaderGroup.
   */
  public void leave() {
    this.processWatchedEvents = false;
    try {
      ZookeeperUtils.deleteNodeIfEmpty(zk, myPath);
    } catch (OrbZKFailure e) {
      fireEvent(new OrbExceptionEvent(e));
    }
  }
 
  /**
   * Return the rocessWatchedEvents
   */
  protected boolean isProcessWatchedEvents() {
    return processWatchedEvents;
  }
 
  /**
   * Set the processWatchedEvents
   *
   * @param processWatchedEvents
   *          - boolean
   */
  protected void setProcessWatchedEvents(boolean processWatchedEvents) {
    this.processWatchedEvents = processWatchedEvents;
  }
}
TOP

Related Classes of org.goldenorb.zookeeper.LeaderGroup

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.