/*
 * Copyright 1999,2004 The Apache Software Foundation.
 * 
 * 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 org.apache.catalina.tribes.membership;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.catalina.tribes.Member;
import java.util.Comparator;

/**
 * A <b>membership</b> implementation using simple multicast.
 * This is the representation of a multicast membership.
 * This class is responsible for maintaining a list of active cluster nodes in the cluster.
 * If a node fails to send out a heartbeat, the node will be dismissed.
 *
 * @author Filip Hanik
 * @author Peter Rossbach
 * @version $Revision: 356540 $, $Date: 2005-12-13 10:53:40 -0600 (Tue, 13 Dec 2005) $
 */
public class Membership
{
    protected static final MemberImpl[] EMPTY_MEMBERS = new MemberImpl[0];
    
    /**
     * The name of this membership, has to be the same as the name for the local
     * member
     */
    protected MemberImpl local;
    
    /**
     * A map of all the members in the cluster.
     */
    protected HashMap map = new HashMap();
    
    /**
     * A list of all the members in the cluster.
     */
    protected MemberImpl[] members = EMPTY_MEMBERS;
    
    /**
      * sort members by alive time
      */
    protected Comparator memberComparator = new MemberComparator();

    public Object clone() {
        synchronized (members) {
            Membership clone = new Membership(local, memberComparator);
            clone.map = (HashMap) map.clone();
            clone.members = new MemberImpl[members.length];
            System.arraycopy(members,0,clone.members,0,members.length);
            return clone;
        }
    }

    /**
     * Constructs a new membership
     * @param name - has to be the name of the local member. Used to filter the local member from the cluster membership
     */
    public Membership(MemberImpl local, boolean includeLocal) {
        this.local = local;
        if ( includeLocal ) addMember(local);
    }

    public Membership(MemberImpl local) {
        this(local,false);
    }

    public Membership(MemberImpl local, Comparator comp) {
        this(local,comp,false);
    }

    public Membership(MemberImpl local, Comparator comp, boolean includeLocal) {
        this(local,includeLocal);
        this.memberComparator = comp;
    }
    /**
     * Reset the membership and start over fresh.
     * Ie, delete all the members and wait for them to ping again and join this membership
     */
    public synchronized void reset() {
        map.clear();
        members = EMPTY_MEMBERS ;
    }

    /**
     * Notify the membership that this member has announced itself.
     *
     * @param member - the member that just pinged us
     * @return - true if this member is new to the cluster, false otherwise.
     * @return - false if this member is the local member or updated.
     */
    public synchronized boolean memberAlive(MemberImpl member) {
        boolean result = false;
        //ignore ourselves
        if (  member.equals(local) ) return result;

        //return true if the membership has changed
        MbrEntry entry = (MbrEntry)map.get(member);
        if ( entry == null ) {
            entry = addMember(member);
            result = true;
       } else {
            //update the member alive time
            MemberImpl updateMember = entry.getMember() ;
            if(updateMember.getMemberAliveTime() != member.getMemberAliveTime()) {
                //update fields that can change
                updateMember.setMemberAliveTime(member.getMemberAliveTime());
                updateMember.setPayload(member.getPayload());
                updateMember.setCommand(member.getCommand());
                Arrays.sort(members, memberComparator);
            }
        }
        entry.accessed();
        return result;
    }

    /**
     * Add a member to this component and sort array with memberComparator
     * @param member The member to add
     */
    public synchronized MbrEntry addMember(MemberImpl member) {
      synchronized (members) {
          MbrEntry entry = new MbrEntry(member);
          if (!map.containsKey(member) ) {
              map.put(member, entry);
              MemberImpl results[] = new MemberImpl[members.length + 1];
              for (int i = 0; i < members.length; i++) results[i] = members[i];
              results[members.length] = member;
              members = results;
              Arrays.sort(members, memberComparator);
          }
          return entry;
      }
    }
    
    /**
     * Remove a member from this component.
     * 
     * @param member The member to remove
     */
    public void removeMember(MemberImpl member) {
        map.remove(member);
        synchronized (members) {
            int n = -1;
            for (int i = 0; i < members.length; i++) {
                if (members[i] == member || members[i].equals(member)) {
                    n = i;
                    break;
                }
            }
            if (n < 0) return;
            MemberImpl results[] = new MemberImpl[members.length - 1];
            int j = 0;
            for (int i = 0; i < members.length; i++) {
                if (i != n)
                    results[j++] = members[i];
            }
            members = results;
        }
    }
    
    /**
     * Runs a refresh cycle and returns a list of members that has expired.
     * This also removes the members from the membership, in such a way that
     * getMembers() = getMembers() - expire()
     * @param maxtime - the max time a member can remain unannounced before it is considered dead.
     * @return the list of expired members
     */
    public synchronized MemberImpl[] expire(long maxtime) {
        if(!hasMembers() )
           return EMPTY_MEMBERS;
       
        ArrayList list = null;
        Iterator i = map.values().iterator();
        while(i.hasNext()) {
            MbrEntry entry = (MbrEntry)i.next();
            if( entry.hasExpired(maxtime) ) {
                if(list == null) // only need a list when members are expired (smaller gc)
                    list = new java.util.ArrayList();
                list.add(entry.getMember());
            }
        }
        
        if(list != null) {
            MemberImpl[] result = new MemberImpl[list.size()];
            list.toArray(result);
            for( int j=0; j<result.length; j++) {
                removeMember(result[j]);
            }
            return result;
        } else {
            return EMPTY_MEMBERS ;
        }
    }

    /**
     * Returning that service has members or not
     */
    public boolean hasMembers() {
        return members.length > 0 ;
    }
    
    
    public MemberImpl getMember(Member mbr) {
        if(hasMembers()) {
            MemberImpl result = null;
            for ( int i=0; i<this.members.length && result==null; i++ ) {
                if ( members[i].equals(mbr) ) result = members[i];
            }//for
            return result;
        } else {
            return null;
        }
    }
    
    public boolean contains(Member mbr) { 
        return getMember(mbr)!=null;
    }
 
    /**
     * Returning a list of all the members in the membership
     * We not need a copy: add and remove generate new arrays.
     */
    public MemberImpl[] getMembers() {
        if(hasMembers()) {
            return members;
        } else {
            return EMPTY_MEMBERS;
        }
    }

    /**
     * get a copy from all member entries
     */
    protected synchronized MbrEntry[] getMemberEntries()
    {
        MbrEntry[] result = new MbrEntry[map.size()];
        java.util.Iterator i = map.entrySet().iterator();
        int pos = 0;
        while ( i.hasNext() )
            result[pos++] = ((MbrEntry)((java.util.Map.Entry)i.next()).getValue());
        return result;
    }
    
    // --------------------------------------------- Inner Class

    private class MemberComparator implements java.util.Comparator {

        public int compare(Object o1, Object o2) {
            try {
                return compare((MemberImpl) o1, (MemberImpl) o2);
            } catch (ClassCastException x) {
                return 0;
            }
        }

        public int compare(MemberImpl m1, MemberImpl m2) {
            //longer alive time, means sort first
            long result = m2.getMemberAliveTime() - m1.getMemberAliveTime();
            if (result < 0)
                return -1;
            else if (result == 0)
                return 0;
            else
                return 1;
        }
    }
    
    /**
     * Inner class that represents a member entry
     */
    protected static class MbrEntry
    {

        protected MemberImpl mbr;
        protected long lastHeardFrom;

        public MbrEntry(MemberImpl mbr) {
           this.mbr = mbr;
        }

        /**
         * Indicate that this member has been accessed.
         */
        public void accessed(){
           lastHeardFrom = System.currentTimeMillis();
        }

        /**
         * Return the actual Member object
         */
        public MemberImpl getMember() {
            return mbr;
        }

        /**
         * Check if this dude has expired
         * @param maxtime The time threshold
         */
        public boolean hasExpired(long maxtime) {
            long delta = System.currentTimeMillis() - lastHeardFrom;
            return delta > maxtime;
        }
    }
}
