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

com.websudos.phantom.zookeeper.ZkContactPointLookup.scala Maven / Gradle / Ivy

There is a newer version: 1.26.6
Show newest version
/*
 * Copyright 2014-2015 Sphonic Ltd. All Rights Reserved.
 *
 * 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 com.websudos.phantom.zookeeper

import com.datastax.driver.core.Cluster
import com.websudos.phantom.connectors.KeySpaceBuilder
import com.twitter.finagle.exp.zookeeper.ZooKeeper
import com.twitter.finagle.exp.zookeeper.client.ZkClient
import com.twitter.conversions.time._
import com.twitter.util._

import scala.collection.JavaConverters._
import java.net.InetSocketAddress

/**
 * Performs the lookup of Cassandra nodes
 * in Zookeeper. Implemented as function
 * `Cluster.Builder => Cluster.Builder` so that it can
 * be easily plugged into a `KeySpaceBuilder`.
 */
class ZkContactPointLookup(
  host: String,
  port: Int,
  path: String = "/cassandra",
  timeout: Duration = 5.seconds) extends (Cluster.Builder => Cluster.Builder) {

  def apply(builder: Cluster.Builder): Cluster.Builder = {
    val ports = Await.result(retrieveContactPoints, timeout)
    builder.addContactPointsWithPorts(ports.asJava)
  }

  case class LookupException(msg: String) extends RuntimeException(msg) with NoStacktrace

  /**
   * Exposes the instance of the Finagle
   * Zookeeper API that is used to perform the lookup.
   */
  protected[this] lazy val zkClient: ZkClient = {
    val conn = s"$host:$port"
    val client = ZooKeeper.newRichClient(conn)
    Await.result(client.connect(), timeout)
    client
  }

  /**
   * Performs the actual lookup of Cassandra nodes
   * in Zookeeper.
   */
  protected[this] def retrieveContactPoints: Future[Seq[InetSocketAddress]] =
    zkClient.getData(path, watch = false) map {
      res => Try {
        parseContactPoints(new String(res.data))
      } getOrElse Seq.empty[InetSocketAddress]
    }

  /**
   * Parses the specified string into a sequence
   * of InetSocketAddress instances. The default
   * implementation expects a comma
   * separated list of host/port pairs separated by a colon.
   */
  @throws[LookupException]
  protected[this] def parseContactPoints(data: String): Seq[InetSocketAddress] = {
    data.split("\\s*,\\s*").map(_.split(":")).map {
      case Array(hostname, portDef) => new InetSocketAddress(hostname, portDef.toInt)
      case _ => throw LookupException(s"Could not parse contact points from $data")
    }.toSeq
  }

}

/**
 * Entry point for defining a keySpace based
 * on looking up Cassandra nodes in Zookeeper.
 *
 * The default Zookeeper path being used for the lookup
 * is `/cassandra` and the expected format is a comma
 * separated list of host/port pairs separated by a colon.
 */
object ZkContactPointLookup {

  /**
   * Zookeeper's default port.
   */
  val defaultPort = 2181

  /**
   * A keyspace builder based on looking up
   * contact points in Zookeeper running on the default
   * port on localhost.
   */
  lazy val local = apply(defaultPort)

  /**
   * A keyspace builder based on looking up
   * contact points in Zookeeper running on the specified
   * port on localhost.
   */
  def apply(port: Int): KeySpaceBuilder = apply("localhost", port)

  /**
   * A keyspace builder based on looking up
   * contact points in Zookeeper running on the specified
   * host and port.
   */
  def apply(host: String, port: Int): KeySpaceBuilder =
    new KeySpaceBuilder(new ZkContactPointLookup(host,port))

  /**
   * A keyspace builder based on looking up
   * contact points in Zookeeper running on the specified
   * host and port.
   *
   * @param host the host Zookeeper runs on
   * @param port the port Zookeeper runs on
   * @param path the Zookeeper path to use for looking up Cassandra nodes
   * @param timeout the timeout for performing the lookup
   */
  def apply(host: String, port: Int, path: String, timeout: Duration): KeySpaceBuilder =
    new KeySpaceBuilder(new ZkContactPointLookup(host, port, path, timeout))

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy