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

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

The 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.
 */
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{@code (/arcus/cache_list/)}.
 */
public class CacheMonitor extends SpyObject implements Watcher,
        ChildrenCallback {

  private final ZooKeeper zk;

  private final String cacheListZPath;

  private final String serviceCode;

  private volatile boolean dead;

  private final CacheMonitorListener listener;

  /**
   * Constructor
   *
   * @param zk              ZooKeeper connection
   * @param cacheListZPath  path of cache list znode
   * @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.
     *
     * @param children new children node list
     */
    void commandCacheListChange(List children);

    List getPrevCacheList();

    /**
     * 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.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.commandCacheListChange(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, this, this, null);
  }

  /**
   * Shutdown the CacheMonitor.
   */
  public void shutdown() {
    if (!dead) {
      getLogger().info("Shutting down the CacheMonitor. " + getInfo());
      dead = true;
      listener.closing();
    }
  }

  /**
   * Check if the cache monitor is dead.
   */
  public boolean isDead() {
    return dead;
  }

  private String getInfo() {
    String zkSessionId = null;
    if (zk != null) {
      zkSessionId = "0x" + Long.toHexString(zk.getSessionId());
    }
    return "[serviceCode=" + serviceCode + ", adminSessionId=" + zkSessionId + "]";
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy