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

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

/*
 * 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.
 */
package net.spy.memcached;

import java.util.List;

import net.spy.memcached.compat.SpyObject;

import org.apache.zookeeper.AsyncCallback.ChildrenCallback;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

/**
 * CacheMonitor monitors the changes of the cache server list
 * in the ZooKeeper node(/arcus/cache_list/).
 */
public class CacheMonitor extends SpyObject implements Watcher,
		ChildrenCallback {

	ZooKeeper zk;

	String cacheListZPath;
	
	String serviceCode;

	volatile boolean dead;

	CacheMonitorListener listener;

	/**
	 * Constructor
	 * 
	 * @param zk
	 *            ZooKeeper connection
	 * @param serviceCode
	 *            service code (or cloud name) to identify each cloud
	 * @param listener
	 *            Callback listener
	 */
	public CacheMonitor(ZooKeeper zk, String cacheListZPath, String serviceCode,
			CacheMonitorListener listener) {
		this.zk = zk;
		this.cacheListZPath = cacheListZPath;
		this.serviceCode = serviceCode;
		this.listener = listener;

		getLogger().info("Initializing the CacheMonitor.");
		
		// Get the cache list from the Arcus admin asynchronously.
		// Returning list would be processed in processResult().
		asyncGetCacheList();
	}

	/**
	 * Other classes use the CacheMonitor by implementing this method
	 */
	public interface CacheMonitorListener {
		/**
		 * The existing children of the node has changed.
		 */
		void commandNodeChange(List children);

		List getPrevChildren();
		/**
		 * The ZooKeeper session is no longer valid.
		 */
		void closing();
	}

	/**
	 * Processes every events from the ZooKeeper.
	 */
	public void process(WatchedEvent event) {
		if (event.getType() == Event.EventType.None) {
			// Processes session events
			switch (event.getState()) {
			case SyncConnected:
				getLogger().warn("Reconnected to the Arcus admin. " + getInfo());
				return;
			case Disconnected:
				getLogger().warn("Disconnected from the Arcus admin. Trying to reconnect. " + getInfo());
				return;
			case Expired:
				// If the session was expired, just shutdown this client to be re-initiated.
				getLogger().warn("Session expired. Trying to reconnect to the Arcus admin." + getInfo());
				shutdown();
				return;
			}
		} else {
			// Set a new watch on the znode when there are any changes in it.
			if (event.getType() == Event.EventType.NodeChildrenChanged) {
				asyncGetCacheList();
			}
		}
	}

	/**
	 * A callback function to process the result of getChildren(watch=true).
	 */
	public void processResult(int rc, String path, Object ctx,
			List children) {
		switch (Code.get(rc)) {
		case OK:
			listener.commandNodeChange(children);
			return;
		case NONODE:
			getLogger().fatal("Cannot find your service code. Please contact Arcus support to solve this problem. " + getInfo());
			return;
		case SESSIONEXPIRED:
			getLogger().warn("Session expired. Trying to reconnect to the Arcus admin. " + getInfo());
			shutdown();
			return;
		case NOAUTH:
			getLogger().fatal("Authorization failed " + getInfo());
			shutdown();
			return;
		case CONNECTIONLOSS:
			getLogger().warn("Connection lost. Trying to reconnect to the Arcus admin." + getInfo());
			asyncGetCacheList();
			return;
		default:
			getLogger().warn("Ignoring an unexpected event from the Arcus admin. code=" + Code.get(rc) + ", " + getInfo());
			asyncGetCacheList();
			return;
		}
	}

	/**
	 * Get the cache list asynchronously from the Arcus admin.
	 */
	void asyncGetCacheList() {
		if (getLogger().isDebugEnabled()) {
			getLogger().debug("Set a new watch on " + (cacheListZPath + serviceCode));
		}
		
		zk.getChildren(cacheListZPath + serviceCode, true, this, null);
	}

	/**
	 * Shutdown the CacheMonitor.
	 */
	public void shutdown() {
		getLogger().info("Shutting down the CacheMonitor. " + getInfo());
		dead = true;
		listener.closing();
	}
	
	private String getInfo() {
		String zkSessionId = null;
		if (zk != null) {
			zkSessionId = "0x" + Long.toHexString(zk.getSessionId());
		}
		return "[serviceCode=" + serviceCode + ", adminSessionId=" + zkSessionId + "]";
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy