Package org.apache.helix

Source Code of org.apache.helix.ZkTestHelper

package org.apache.helix;

/*
* 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.
*/

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.IZkStateListener;
import org.I0Itec.zkclient.ZkConnection;
import org.apache.helix.InstanceType;
import org.apache.helix.ZNRecord;
import org.apache.helix.PropertyKey.Builder;
import org.apache.helix.manager.zk.CallbackHandler;
import org.apache.helix.manager.zk.ZKHelixDataAccessor;
import org.apache.helix.manager.zk.ZKHelixManager;
import org.apache.helix.manager.zk.ZkBaseDataAccessor;
import org.apache.helix.manager.zk.ZkClient;
import org.apache.helix.model.ExternalView;
import org.apache.log4j.Logger;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooKeeper.States;


public class ZkTestHelper
{
  private static Logger LOG = Logger.getLogger(ZkTestHelper.class);

  static
  {
    // Logger.getRootLogger().setLevel(Level.DEBUG);
  }
 
  public static void disconnectSession(final ZkClient zkClient) throws Exception
  {
    IZkStateListener listener = new IZkStateListener()
    {
      @Override
      public void handleStateChanged(KeeperState state) throws Exception
      {
//         System.err.println("disconnectSession handleStateChanged. state: " + state);
      }

      @Override
      public void handleNewSession() throws Exception
      {
        // make sure zkclient is connected again
        zkClient.waitUntilConnected();

        ZkConnection connection = ((ZkConnection) zkClient.getConnection());
        ZooKeeper curZookeeper = connection.getZookeeper();

        LOG.info("handleNewSession. sessionId: "
            + Long.toHexString(curZookeeper.getSessionId()));
      }
    };

    zkClient.subscribeStateChanges(listener);
    ZkConnection connection = ((ZkConnection) zkClient.getConnection());
    ZooKeeper curZookeeper = connection.getZookeeper();
    LOG.info("Before expiry. sessionId: " + Long.toHexString(curZookeeper.getSessionId()));

    Watcher watcher = new Watcher()
    {
      @Override
      public void process(WatchedEvent event)
      {
        LOG.info("Process watchEvent: " + event);
      }
    };

    final ZooKeeper dupZookeeper =
        new ZooKeeper(connection.getServers(),
                      curZookeeper.getSessionTimeout(),
                      watcher,
                      curZookeeper.getSessionId(),
                      curZookeeper.getSessionPasswd());
    // wait until connected, then close
    while (dupZookeeper.getState() != States.CONNECTED)
    {
      Thread.sleep(10);
    }
    dupZookeeper.close();

    connection = (ZkConnection) zkClient.getConnection();
    curZookeeper = connection.getZookeeper();
    zkClient.unsubscribeStateChanges(listener);

    // System.err.println("zk: " + oldZookeeper);
    LOG.info("After expiry. sessionId: " + Long.toHexString(curZookeeper.getSessionId()));
  }

  public static void expireSession(final ZkClient zkClient) throws Exception
  {
    final CountDownLatch waitExpire = new CountDownLatch(1);

    IZkStateListener listener = new IZkStateListener()
    {
      @Override
      public void handleStateChanged(KeeperState state) throws Exception
      {
//         System.err.println("handleStateChanged. state: " + state);
      }

      @Override
      public void handleNewSession() throws Exception
      {
        // make sure zkclient is connected again
        zkClient.waitUntilConnected();

        ZkConnection connection = ((ZkConnection) zkClient.getConnection());
        ZooKeeper curZookeeper = connection.getZookeeper();

        LOG.info("handleNewSession. sessionId: "
            + Long.toHexString(curZookeeper.getSessionId()));
        waitExpire.countDown();
      }
    };

    zkClient.subscribeStateChanges(listener);

    ZkConnection connection = ((ZkConnection) zkClient.getConnection());
    ZooKeeper curZookeeper = connection.getZookeeper();
    LOG.info("Before expiry. sessionId: " + Long.toHexString(curZookeeper.getSessionId()));

    Watcher watcher = new Watcher()
    {
      @Override
      public void process(WatchedEvent event)
      {
        LOG.info("Process watchEvent: " + event);
      }
    };

    final ZooKeeper dupZookeeper =
        new ZooKeeper(connection.getServers(),
                      curZookeeper.getSessionTimeout(),
                      watcher,
                      curZookeeper.getSessionId(),
                      curZookeeper.getSessionPasswd());
    // wait until connected, then close
    while (dupZookeeper.getState() != States.CONNECTED)
    {
      Thread.sleep(10);
    }
    dupZookeeper.close();

    // make sure session expiry really happens
    waitExpire.await();
    zkClient.unsubscribeStateChanges(listener);

    connection = (ZkConnection) zkClient.getConnection();
    curZookeeper = connection.getZookeeper();

    // System.err.println("zk: " + oldZookeeper);
    LOG.info("After expiry. sessionId: " + Long.toHexString(curZookeeper.getSessionId()));
  }

  /*
   * stateMap: partition->instance->state
   */
  public static boolean verifyState(ZkClient zkclient,
                                    String clusterName,
                                    String resourceName,
                                    Map<String, Map<String, String>> expectStateMap,
                                    String op)
  {
    boolean result = true;
    ZkBaseDataAccessor<ZNRecord> baseAccessor =
        new ZkBaseDataAccessor<ZNRecord>(zkclient);
    ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, baseAccessor);
    Builder keyBuilder = accessor.keyBuilder();

    ExternalView extView = accessor.getProperty(keyBuilder.externalView(resourceName));
    Map<String, Map<String, String>> actualStateMap = extView.getRecord().getMapFields();
    for (String partition : actualStateMap.keySet())
    {
      for (String expectPartiton : expectStateMap.keySet())
      {
        if (!partition.matches(expectPartiton))
        {
          continue;
        }

        Map<String, String> actualInstanceStateMap = actualStateMap.get(partition);
        Map<String, String> expectInstanceStateMap = expectStateMap.get(expectPartiton);
        for (String instance : actualInstanceStateMap.keySet())
        {
          for (String expectInstance : expectStateMap.get(expectPartiton).keySet())
          {
            if (!instance.matches(expectInstance))
            {
              continue;
            }

            String actualState = actualInstanceStateMap.get(instance);
            String expectState = expectInstanceStateMap.get(expectInstance);
            boolean equals = expectState.equals(actualState);
            if (op.equals("==") && !equals || op.equals("!=") && equals)
            {
              System.out.println(partition + "/" + instance
                  + " state mismatch. actual state: " + actualState + ", but expect: "
                  + expectState + ", op: " + op);
              result = false;
            }
          }
        }
      }
    }
    return result;
  }
 
  /**
   * return the number of listeners on given zk-path
   * @param zkAddr
   * @param path
   * @return
   * @throws Exception
   */
  public static int numberOfListeners(String zkAddr, String path) throws Exception
  {
    Map<String, Set<String>> listenerMap = getListenersByZkPath(zkAddr);
    if (listenerMap.containsKey(path)) {
      return listenerMap.get(path).size();
    }
    return 0;
  }
 
  /**
   * return a map from zk-path to a set of zk-session-id that put watches on the zk-path
   *
   * @param zkAddr
   * @return
   * @throws Exception
   */
  public static Map<String, Set<String>> getListenersByZkPath(String zkAddr) throws Exception
  {
    String splits[] = zkAddr.split(":");
    Map<String, Set<String>> listenerMap = new TreeMap<String, Set<String>>();
    Socket sock = null;
    int retry = 5;
   
    while (retry > 0) {
      try {
        sock = new Socket(splits[0], Integer.parseInt(splits[1]));
        PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
        BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
   
        out.println("wchp");
   
        listenerMap.clear();
        String lastPath = null;
        String line = in.readLine();
        while (line != null)
        {
          line = line.trim();
         
          if (line.startsWith("/")) {
            lastPath = line;
            if (!listenerMap.containsKey(lastPath)) {
              listenerMap.put(lastPath, new TreeSet<String>());
            }
          } else if (line.startsWith("0x")) {
            if (lastPath != null && listenerMap.containsKey(lastPath) ) {
              listenerMap.get(lastPath).add(line);
            } else
            {
              LOG.error("Not path associated with listener sessionId: " + line + ", lastPath: " + lastPath);
            }
          } else
          {
    //        LOG.error("unrecognized line: " + line);
          }
          line = in.readLine();
        }
        break;
      } catch (Exception e) {
        // sometimes in test, we see connection-reset exceptions when in.readLine()
        // so add this retry logic
        retry--;
      } finally
      {
      if (sock != null)
        sock.close();
      }
    }
    return listenerMap;
  }

  /**
   * return a map from session-id to a set of zk-path that the session has watches on
   *
   * @return
   */
  public static Map<String, Set<String>> getListenersBySession(String zkAddr) throws Exception {
    Map<String, Set<String>> listenerMapByInstance = getListenersByZkPath(zkAddr);
   
    // convert to index by sessionId
    Map<String, Set<String>> listenerMapBySession = new TreeMap<String, Set<String>>();
    for (String path : listenerMapByInstance.keySet()) {
      for (String sessionId : listenerMapByInstance.get(path)) {
        if (!listenerMapBySession.containsKey(sessionId)) {
          listenerMapBySession.put(sessionId, new TreeSet<String>());
        }
        listenerMapBySession.get(sessionId).add(path);
      }
    }

    return listenerMapBySession;
  }
    static java.lang.reflect.Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            Class superClass = clazz.getSuperclass();
            if (superClass == null) {
                throw e;
            } else {
                return getField(superClass, fieldName);
            }
        }
    }

    public static Map<String, List<String>> getZkWatch(ZkClient client) throws Exception {
        Map<String, List<String>> lists = new HashMap<String, List<String>>();
        ZkConnection connection = ((ZkConnection) client.getConnection());
        ZooKeeper zk = connection.getZookeeper();

        java.lang.reflect.Field field = getField(zk.getClass(), "watchManager");
        field.setAccessible(true);
        Object watchManager = field.get(zk);

        java.lang.reflect.Field field2 = getField(watchManager.getClass(), "dataWatches");
        field2.setAccessible(true);
        HashMap<String, Set<Watcher>> dataWatches = (HashMap<String, Set<Watcher>>) field2.get(watchManager);

        field2 = getField(watchManager.getClass(), "existWatches");
        field2.setAccessible(true);
        HashMap<String, Set<Watcher>> existWatches = (HashMap<String, Set<Watcher>>) field2.get(watchManager);

        field2 = getField(watchManager.getClass(), "childWatches");
        field2.setAccessible(true);
        HashMap<String, Set<Watcher>> childWatches = (HashMap<String, Set<Watcher>>) field2.get(watchManager);

        lists.put("dataWatches", new ArrayList<String>(dataWatches.keySet()));
        lists.put("existWatches", new ArrayList<String>(existWatches.keySet()));
        lists.put("childWatches", new ArrayList<String>(childWatches.keySet()));

        return lists;
    }

    public static Map<String, Set<IZkDataListener>> getZkDataListener(ZkClient client) throws Exception {
        java.lang.reflect.Field field = getField(client.getClass(), "_dataListener");
        field.setAccessible(true);
        Map<String, Set<IZkDataListener>> dataListener = (Map<String, Set<IZkDataListener>>)field.get(client);
        return dataListener;
    }

    public static Map<String, Set<IZkChildListener>> getZkChildListener(ZkClient client) throws Exception {
        java.lang.reflect.Field field = getField(client.getClass(), "_childListener");
        field.setAccessible(true);
        Map<String, Set<IZkChildListener>> childListener = (Map<String, Set<IZkChildListener>>)field.get(client);
        return childListener;
    }


    public static boolean tryWaitZkEventsCleaned(ZkClient zkclient) throws Exception {
        java.lang.reflect.Field field = getField(zkclient.getClass(), "_eventThread");
        field.setAccessible(true);
        Object eventThread = field.get(zkclient);
        // System.out.println("field: " + eventThread);

        java.lang.reflect.Field field2 = getField(eventThread.getClass(), "_events");
        field2.setAccessible(true);
        BlockingQueue queue = (BlockingQueue) field2.get(eventThread);
        // System.out.println("field2: " + queue + ", " + queue.size());


        if (queue == null) {
            LOG.error("fail to get event-queue from zkclient. skip waiting");
            return false;
        }

        for (int i = 0; i < 20; i++) {
            if (queue.size() == 0) {
                return true;
            }
            Thread.sleep(100);
            System.out.println("pending zk-events in queue: " + queue);
        }
        return false;
    }
}
TOP

Related Classes of org.apache.helix.ZkTestHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.