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

com.ox.bigdata.util.kafka.ZKManager.scala Maven / Gradle / Ivy

The newest version!
package com.ox.bigdata.util.kafka

import com.ox.bigdata.util.log.LogSupport
import org.I0Itec.zkclient.ZkClient
import org.I0Itec.zkclient.exception.{ZkException, ZkInterruptedException, ZkNoNodeException}
import org.apache.zookeeper.data.Stat

import scala.collection.{Map, Seq, mutable}

/*
copied from kafka.utils.ZKUtils
* */
object ZKManager extends LogSupport {

  protected val ConsumersPath = "/consumers"
  protected val BrokerIdsPath = "/brokers/ids"
  protected val BrokerTopicsPath = "/brokers/topics"
  protected val TopicConfigPath = "/config/topics"
  protected val TopicConfigChangesPath = "/config/changes"
  protected val ControllerPath = "/controller"
  protected val ControllerEpochPath = "/controller_epoch"
  protected val ReassignPartitionsPath = "/admin/reassign_partitions"
  protected val DeleteTopicsPath = "/admin/delete_topics"
  protected val PreferredReplicaLeaderElectionPath = "/admin/preferred_replica_election"

  def getTopicPath(topic: String): String = BrokerTopicsPath + "/" + topic

  def getTopicPartitionsPath(topic: String): String = getTopicPath(topic) + "/partitions"

  def getTopicConfigPath(topic: String): String = TopicConfigPath + "/" + topic

  def getDeleteTopicPath(topic: String): String = DeleteTopicsPath + "/" + topic

  def usingZkClient(zk_hosts: String)(op: ZkClient => Unit): Unit = {
    val zk = new ZkClient(zk_hosts, 6000)
    try {
      op(zk)
    } catch {
      case e: Exception => LOG.error(s"ZooKeeper actions failed !zookeeper hosts => $zk_hosts" + e.printStackTrace())
    } finally {
      zk.close()
    }
  }

  /**
    * Create a persistent node and set its ACLs.
    *
    * @param path
    * @param createParents
    * if true all parent dirs are created as well and no { @link ZkNodeExistsException} is thrown in case the
    * path already exists
    * @throws ZkInterruptedException
    * if operation was interrupted, or a required reconnection got interrupted
    * @throws IllegalArgumentException
    * if called from anything except the ZooKeeper event thread
    * @throws ZkException
    * if any ZooKeeper exception occurred
    * @throws RuntimeException
    * if any other exception occurs
    */

  def createPersistent(zk_hosts: String, path: String, createParents: Boolean = true): Unit = {
    usingZkClient(zk_hosts) {
      zkClient =>
        zkClient.createPersistent(path, createParents)
    }
  }

  /**
    * Create an ephemeral node.
    *
    * @param path
    * @throws ZkInterruptedException
    * if operation was interrupted, or a required reconnection got interrupted
    * @throws IllegalArgumentException
    * if called from anything except the ZooKeeper event thread
    * @throws ZkException
    * if any ZooKeeper exception occurred
    * @throws RuntimeException
    * if any other exception occurs
    */
  def createEphemeral(zk_hosts: String, path: String): Unit = {
    usingZkClient(zk_hosts) {
      zkClient =>
        zkClient.createEphemeral(path)
    }
  }

  def getChildren(zk_hosts: String, path: String): Seq[String] = {
    import scala.collection.JavaConversions._
    var children: Seq[String] = Nil
    usingZkClient(zk_hosts) {
      zkClient =>
        children = zkClient.getChildren(path)
    }
    children
  }

  /**
    * Set the data for the node of the given path if such a node exists and the
    * given version matches the version of the node (if the given version is
    * -1, it matches any node's versions). Return the stat of the node.
    * 

* This operation, if successful, will trigger all the watches on the node * of the given path left by getData calls. *

* A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. *

* A KeeperException with error code KeeperException.BadVersion will be * thrown if the given version does not match the node's version. *

* The maximum allowable size of the data array is 1 MB (1,048,576 bytes). * Arrays larger than this will cause a KeeperException to be thrown. * * @param path * the path of the node * @param data * the data to set * @param version * the expected matching version * @return the state of the node * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero error code. * @throws IllegalArgumentException if an invalid path is specified */ def getPartitionsForTopics(zk_hosts: String, topics: Seq[String]): mutable.Map[String, Seq[Int]] = { val ret = new mutable.HashMap[String, Seq[Int]]() usingZkClient(zk_hosts) { zkClient => getPartitionAssignmentForTopics(zkClient, topics).map { topicAndPartitionMap => val topic = topicAndPartitionMap._1 val partitionMap = topicAndPartitionMap._2 LOG.debug("partition assignment of /brokers/topics/%s is %s".format(topic, partitionMap)) ret += (topic -> partitionMap.keys.toSeq.sortWith((s, t) => s < t)) } } ret } def getPartitionAssignmentForTopics(zkClient: ZkClient, topics: Seq[String]): mutable.Map[String, collection.Map[Int, Seq[Int]]] = { val ret = new mutable.HashMap[String, Map[Int, Seq[Int]]]() topics.foreach { topic => val jsonPartitionMapOpt = readDataMaybeNull(zkClient, getTopicPath(topic))._1 val partitionMap = jsonPartitionMapOpt match { case Some(jsonPartitionMap) => Json.parseFull(jsonPartitionMap) match { case Some(m) => m.asInstanceOf[Map[String, Any]].get("partitions") match { case Some(replicaMap) => val m1 = replicaMap.asInstanceOf[Map[String, Seq[Int]]] m1.map(p => (p._1.toInt, p._2)) case None => Map[Int, Seq[Int]]() } case None => Map[Int, Seq[Int]]() } case None => Map[Int, Seq[Int]]() } LOG.debug("Partition map for /brokers/topics/%s is %s".format(topic, partitionMap)) ret += (topic -> partitionMap) } ret } def readDataMaybeNull(client: ZkClient, path: String): (Option[String], Stat) = { val stat: Stat = new Stat() val dataAndStat = try { (Some(client.readData(path, stat)), stat) } catch { case e: ZkNoNodeException => (None, stat) case e2: Exception => throw e2 } dataAndStat } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy