All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.spy.memcached.ArcusReplNodeAddress Maven / Gradle / Ivy

There is a newer version: 1.13.2
Show newest version
/*
 * arcus-java-client : Arcus Java client
 * Copyright 2010-2014 NAVER Corp.
 *
 * 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.
 */
/* ENABLE_REPLICATION if */
package net.spy.memcached;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ArcusReplNodeAddress extends InetSocketAddress {

	private static final long serialVersionUID = -1555690881482453720L;
	boolean master;
	String group;
	String ip;
	int port;

	private ArcusReplNodeAddress(String group, boolean master, String ip, int port) {
		super(ip, port);
		this.group = group;
		this.master = master;
		this.ip = ip;
		this.port = port;
	}
	
	public ArcusReplNodeAddress(ArcusReplNodeAddress addr) {
		this(addr.group, addr.master, addr.ip, addr.port);
	}

	public String toString() {
		return "Group(" + group + ") Address(" + ip + ":" + port + ") " + (master ? "MASTER" : "SLAVE");
	}

	public String getIPPort() {
		return this.ip + ":" + this.port;
	}

	public String getGroupName() {
		return group;
	}

	static ArcusReplNodeAddress create(String group, boolean master, String ipport) {
		String[] temp = ipport.split(":");
		String ip = temp[0];
		int port = Integer.parseInt(temp[1]);
		return new ArcusReplNodeAddress(group, master, ip, port);
	}

	static ArcusReplNodeAddress createFake(String groupName) {
		return create(groupName == null ? "invalid" : groupName,
					  true, CacheManager.FAKE_SERVER_NODE);
	}

	private static List parseNodeNames(String s) throws Exception {
		List addrs = new ArrayList();

		for (String node : s.split(",")) {
			ArcusReplNodeAddress a = null;
			if (node.equals(CacheManager.FAKE_SERVER_NODE)) {
				a = ArcusReplNodeAddress.createFake(null);
			} else {
				String[] temp = node.split("\\^");
				String group = temp[0];
				boolean master = temp[1].equals("M") ? true : false;
				String ipport = temp[2];
				// We may throw null pointer exception if the string has
				// an unexpected format.  Abort the whole method instead of
				// trying to ignore malformed strings.
				// Is this the right behavior?  FIXME
	
				a = ArcusReplNodeAddress.create(group, master, ipport);
			}
			addrs.add(a);
		}
		return addrs;
	}

	// Similar to AddrUtil.getAddresses.  This version parses replicaton znode names.
	// Znode names are group^{M,S}^ip:port-hostname
	static List getAddresses(String s) {
		List list = null;

		try {
			list = parseNodeNames(s);
		} catch (Exception e) {
			// May see an exception if nodes do not follow the replication naming convention
			ArcusClient.arcusLogger.error("Exception caught while parsing node" +
									" addresses. cache_list=" + s + "\n" + e);
			e.printStackTrace();
			list = null;
		}
		// Return at least one node in all cases.  Otherwise we may see unexpected null pointer
		// exceptions throughout this client library...
		if (list == null || list.size() == 0) {
			list = new ArrayList(1);
			list.add((InetSocketAddress)ArcusReplNodeAddress.createFake(null));
		}
		return list;
	}

	static Map> makeGroupAddrsList (
											List addrs) {

		Map> newAllGroups =
				new HashMap>();

		for (int i = 0; i < addrs.size(); i++) {
			ArcusReplNodeAddress a = (ArcusReplNodeAddress)addrs.get(i);
			String groupName = a.getGroupName();
			List gNodeList = newAllGroups.get(groupName);
			if (gNodeList == null) {
				gNodeList = new ArrayList();
				newAllGroups.put(groupName, gNodeList);
			}
			/* Make a master node the first element of node list. */
			if (a.master) /* shifts the element currently at that position */
				gNodeList.add(0, a);
			else /* Don't care the index, just add. */
				gNodeList.add(a);
		}

		for (Map.Entry> entry : newAllGroups.entrySet()) {
			/* If newGroupNodes is validate
			 * then newGroupNodes is sorted by master / slave
			 */
			List newGroupNodes = entry.getValue();

			if (newGroupNodes.size() >= 3) {
				ArcusClient.arcusLogger.error(entry.getKey()
						+ " group have too many node. " + newGroupNodes);
				entry.setValue(new ArrayList());
			}
			else if (newGroupNodes.size() == 2 &&
					newGroupNodes.get(0).getIPPort().equals(newGroupNodes.get(1).getIPPort())) {
				/*
				 * Two nodes have the same ip and port
				 */
				ArcusClient.arcusLogger.error("Group " + entry.getKey() + " have invalid state. "
						+ "Master and Slave nodes have the same ip and port. "
						+ newGroupNodes);
				entry.setValue(new ArrayList());
			}
			else if (newGroupNodes.size() == 2 &&
					newGroupNodes.get(0).master && newGroupNodes.get(1).master) {
				/*
				 * Two nodes are master
				 */
				ArcusClient.arcusLogger.error("Group " + entry.getKey() + " have invalid state. "
						+ "This group have two master node. "
						+ newGroupNodes);
				entry.setValue(new ArrayList());
			}
			else if (!newGroupNodes.get(0).master) {
				/*
				 * Fake group (node) is always master...
				 * 
				 * Maybe! this group have slave and slave node
				 * or slave node only
				 */
			 	ArcusClient.arcusLogger.info("Group " + entry.getKey() + " have invalid state. "
						+ "This group don't have master node. "
						+ newGroupNodes);
				entry.setValue(new ArrayList());
			}
		}
		return newAllGroups;
	}
}
/* ENABLE_REPLICATION end */




© 2015 - 2025 Weber Informatics LLC | Privacy Policy