// Path: cmraft-core/src/main/java/com/chicm/cmraft/common/Configuration.java
// public interface Configuration {
//   
//   void useResource(String resourceName);
//   
//   String getString(String key);
//   
//   String getString(String key, String defaultValue);
//   
//   int getInt(String key);
//   
//   int getInt(String key, int defaultValue);
//   
//   void set(String key, String value);
//   
//   void clear();
//   
//   void remove(String key);
//   
//   Iterable<String> getKeys();
//   
//   Iterable<String> getKeys(String prefix);
// }
// 
// Path: cmraft-core/src/main/java/com/chicm/cmraft/common/ServerInfo.java
// public class ServerInfo {
//   static final Log LOG = LogFactory.getLog(ServerInfo.class);
//   private final String host;
//   private final int port;
//   
//   public ServerInfo(String host, int port) {
//     this.host = host;
//     this.port = port;
//   }
//   
//   /**
//    * @return the host
//    */
//   public String getHost() {
//     return host;
//   }
// 
//   /**
//    * @return the port
//    */
//   public int getPort() {
//     return port;
//   }
//   
//   public static ServerInfo parseFromString(String hostAddress) {
//     if(hostAddress == null)
//       return null;
//     String[] results = hostAddress.split(":");
//     if(results == null || results.length != 2)
//       return null;
//     int port;
//     try {
//       port = Integer.parseInt(results[1]);
//     } catch(Exception e) {
//       LOG.error("parse port form configuration exception", e);
//       return null;
//     }
//     return new ServerInfo(results[0], port);
//   }
//   /*
//   public static List<ServerInfo> getRemoteServersFromConfiguration(Configuration conf) {
//     List<ServerInfo> servers = new ArrayList<ServerInfo>();
//     for (String key: conf.getKeys("raft.server.remote")) {
//       ServerInfo server = ServerInfo.parseFromString(conf.getString(key));
//       servers.add(server);
//     }
//     return servers;
//   }*/
//   
//   public ServerId toServerId() {
//     ServerId.Builder builder = ServerId.newBuilder();
//     if(getHost() != null)
//       builder.setHostName(getHost());
//     builder.setPort(getPort());
//     
//     return builder.build();
//   }
//   
//   public static ServerInfo copyFrom(ServerId serverId) {
//     if(serverId == null)
//       return null;
//     ServerInfo server = new ServerInfo(serverId.getHostName(), serverId.getPort());
//     return server;
//   }
//   
//   @Override
//   public String toString() {
//     return String.format("[%s:%d]", getHost(), getPort());
//   }
// 
//   
//   private int memoizedHashCode = 0;
//   
//   @Override
//   public int hashCode() {
//     if (memoizedHashCode != 0) {
//       return memoizedHashCode;
//     }
//     int hash = 41;
//     hash = (19 * hash) + getPort();
//     if(getHost()!=null) {
//       hash = (53 * hash) + getHost().hashCode();
//     }
//     memoizedHashCode = hash;
//     return hash;
//   }
//   
//   @Override
//   public boolean equals(Object obj) {
//     if (obj == this) {
//       return true;
//     }
//     if(obj == null) {
//       LOG.debug("equals (null)");
//       return false;
//     }
//     if (!(obj instanceof ServerInfo)) {
//        return super.equals(obj);
//     }
//     ServerInfo other = (ServerInfo)obj;
//     boolean result = true;
//     result = result && ((getHost()!=null) == (other.getHost()!=null));
//     if (getHost()!=null) {
//       result = result && getHost()
//           .equals(other.getHost());
//     }
//     
//     result = result && (getPort()==other.getPort());
//     
//     return result;
//   }
// }


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.chicm.cmraft.common.Configuration;
import com.chicm.cmraft.common.ServerInfo;
import com.google.common.base.Preconditions;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Copyright 2014 The CmRaft Project
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF 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 com.chicm.cmraft.core;




public class ClusterMemberManager {
  static final Log LOG = LogFactory.getLog(ClusterMemberManager.class);
  private static final String RAFT_SERVER_KEY_PREFIX = "raft.server";
  private static final String RAFT_LOCAL_SERVER_KEY = "raft.local.server";
  
  private Set<ServerInfo> remoteServers = new HashSet<ServerInfo>();
  private ServerInfo localServer;
  private Set<String> localAddresses = new HashSet<String>();
  
  public ClusterMemberManager(Configuration conf) {
    initLocalAddresses();
    LOG.debug("local addresses: " + localAddresses.toString());
    loadServerInfoFromConf(conf);
  }
  
  public ServerInfo getLocalServer() {
    return localServer;
  }
  
  public Set<ServerInfo> getRemoteServers() {
    return remoteServers;
  }
  
  // For Raft client to iterate all raft servers
// Path: cmraft-core/src/main/java/com/chicm/cmraft/common/Configuration.java
// public interface Configuration {
//   
//   void useResource(String resourceName);
//   
//   String getString(String key);
//   
//   String getString(String key, String defaultValue);
//   
//   int getInt(String key);
//   
//   int getInt(String key, int defaultValue);
//   
//   void set(String key, String value);
//   
//   void clear();
//   
//   void remove(String key);
//   
//   Iterable<String> getKeys();
//   
//   Iterable<String> getKeys(String prefix);
// }
// 
// Path: cmraft-core/src/main/java/com/chicm/cmraft/common/ServerInfo.java
// public class ServerInfo {
//   static final Log LOG = LogFactory.getLog(ServerInfo.class);
//   private final String host;
//   private final int port;
//   
//   public ServerInfo(String host, int port) {
//     this.host = host;
//     this.port = port;
//   }
//   
//   /**
//    * @return the host
//    */
//   public String getHost() {
//     return host;
//   }
// 
//   /**
//    * @return the port
//    */
//   public int getPort() {
//     return port;
//   }
//   
//   public static ServerInfo parseFromString(String hostAddress) {
//     if(hostAddress == null)
//       return null;
//     String[] results = hostAddress.split(":");
//     if(results == null || results.length != 2)
//       return null;
//     int port;
//     try {
//       port = Integer.parseInt(results[1]);
//     } catch(Exception e) {
//       LOG.error("parse port form configuration exception", e);
//       return null;
//     }
//     return new ServerInfo(results[0], port);
//   }
//   /*
//   public static List<ServerInfo> getRemoteServersFromConfiguration(Configuration conf) {
//     List<ServerInfo> servers = new ArrayList<ServerInfo>();
//     for (String key: conf.getKeys("raft.server.remote")) {
//       ServerInfo server = ServerInfo.parseFromString(conf.getString(key));
//       servers.add(server);
//     }
//     return servers;
//   }*/
//   
//   public ServerId toServerId() {
//     ServerId.Builder builder = ServerId.newBuilder();
//     if(getHost() != null)
//       builder.setHostName(getHost());
//     builder.setPort(getPort());
//     
//     return builder.build();
//   }
//   
//   public static ServerInfo copyFrom(ServerId serverId) {
//     if(serverId == null)
//       return null;
//     ServerInfo server = new ServerInfo(serverId.getHostName(), serverId.getPort());
//     return server;
//   }
//   
//   @Override
//   public String toString() {
//     return String.format("[%s:%d]", getHost(), getPort());
//   }
// 
//   
//   private int memoizedHashCode = 0;
//   
//   @Override
//   public int hashCode() {
//     if (memoizedHashCode != 0) {
//       return memoizedHashCode;
//     }
//     int hash = 41;
//     hash = (19 * hash) + getPort();
//     if(getHost()!=null) {
//       hash = (53 * hash) + getHost().hashCode();
//     }
//     memoizedHashCode = hash;
//     return hash;
//   }
//   
//   @Override
//   public boolean equals(Object obj) {
//     if (obj == this) {
//       return true;
//     }
//     if(obj == null) {
//       LOG.debug("equals (null)");
//       return false;
//     }
//     if (!(obj instanceof ServerInfo)) {
//        return super.equals(obj);
//     }
//     ServerInfo other = (ServerInfo)obj;
//     boolean result = true;
//     result = result && ((getHost()!=null) == (other.getHost()!=null));
//     if (getHost()!=null) {
//       result = result && getHost()
//           .equals(other.getHost());
//     }
//     
//     result = result && (getPort()==other.getPort());
//     
//     return result;
//   }
// }


// Path: cmraft-core/src/main/java/com/chicm/cmraft/core/ClusterMemberManager.java
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.chicm.cmraft.common.Configuration;
import com.chicm.cmraft.common.ServerInfo;
import com.google.common.base.Preconditions;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* Copyright 2014 The CmRaft Project
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF 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 com.chicm.cmraft.core;




public class ClusterMemberManager {
  static final Log LOG = LogFactory.getLog(ClusterMemberManager.class);
  private static final String RAFT_SERVER_KEY_PREFIX = "raft.server";
  private static final String RAFT_LOCAL_SERVER_KEY = "raft.local.server";
  
  private Set<ServerInfo> remoteServers = new HashSet<ServerInfo>();
  private ServerInfo localServer;
  private Set<String> localAddresses = new HashSet<String>();
  
  public ClusterMemberManager(Configuration conf) {
    initLocalAddresses();
    LOG.debug("local addresses: " + localAddresses.toString());
    loadServerInfoFromConf(conf);
  }
  
  public ServerInfo getLocalServer() {
    return localServer;
  }
  
  public Set<ServerInfo> getRemoteServers() {
    return remoteServers;
  }
  
  // For Raft client to iterate all raft servers
  public static Set<ServerInfo> getRaftServers(Configuration conf) {