Package ZK

Source Code of ZK.ZKSynch

package ZK;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.curator.RetryPolicy;
import com.netflix.curator.retry.RetryOneTime;
import com.netflix.curator.framework.CuratorFramework;
import com.netflix.curator.framework.CuratorFrameworkFactory;
import com.netflix.curator.framework.recipes.locks.InterProcessReadWriteLock;

public class ZKSynch {
 
  //Instantiate the logger
  private static final Logger logger = LoggerFactory.getLogger(ZKSynch.class);
 
  //Instantiate the lock container
  private static final ConcurrentHashMap<String,InterProcessReadWriteLock> lockStore = new ConcurrentHashMap<String,InterProcessReadWriteLock>();
 
  //Establish a retry policy
  //TODO: pick a good retry policy
  private static RetryPolicy rtPolicy = new RetryOneTime(1000);
 
  //Namespace prefix for this instance
  //TODO: put back for production run
  private static String namespace = "EY";//"RACS";
 
  //Pointer to the client instance
  private static CuratorFramework client;
 
  //Start the client pointing to the specified server (string of address:port)
  public static boolean init(String address){
   
    //Open the new connection to Zookeeper
    try{
      //client = CuratorFrameworkFactory.newClient(address, rtPolicy);
      client = CuratorFrameworkFactory.builder().connectString(address)
          .namespace(namespace).retryPolicy(rtPolicy).build();
    }catch(IOException e){
      logger.error("Failed to create a new ZK client");
      client = null;
      return false;
    }
   
    //Create a new connection state listener
    ZKConnectionMgr manager = new ZKConnectionMgr();
   
    //Register the state listener
    client.getConnectionStateListenable().addListener(manager);
   
    //Start the client
    logger.info("ZK client is starting");
    client.start();
   
    //Creation has succeeded
    return true;
  }
 
  //Stop the client
  public static boolean stop(){
    if(client != null && client.isStarted()){
      //Announce that the client is terminating
      logger.info("ZK client is closing");
      client.close();
     
      return true;
    }else{
      return false;
    }
  }
 
  //Get the static instance of the client
  public static CuratorFramework getClient(){
    return ZKSynch.client;
  }
 
  //Get a reference to the lock
  //Needs to be synched in case new lock isn't yet stored
  //when another thread asks for the same lock
  private static synchronized InterProcessReadWriteLock getLock(String filename){
    //Lock container
    InterProcessReadWriteLock lock;
   
    //Check if the lock is already created and in the store
    //Otherwise generate a new lock and store it
    if(lockStore.containsKey(filename)){
      lock = lockStore.get(filename);
      logger.debug("Reused an old lock");
    }else{
      lock = new InterProcessReadWriteLock(ZKSynch.client,filename);
      lockStore.put(filename, lock);
      logger.debug("Made a new lock");
    }
   
    //Return the pointer to the lock
    return lock;
  }
 
  //Lock operations on the ZK reader/writer locks
  private static boolean lockOp(String filename, char type, char op){
   
    //Null check and make sure client is running
    if(filename == null || !ZKSynch.client.isStarted()){
      return false;
    }
   
    logger.info(op+" a "+type+" lock for /"+filename);
   
    //Sanitize the filename
    filename = "/" + filename;
   
    //Get the lock
    InterProcessReadWriteLock lock = getLock(filename);
   
    //Acquire/release the read/write lock based on parameters
    try{
      if(type == 'R'){
        if(op == 'A'){
          lock.readLock().acquire();
        }else{
          lock.readLock().release();
        }
      }else{
        if(op == 'A'){
          lock.writeLock().acquire();
        }else{
          lock.writeLock().release();
        }
      }
    }catch(Exception e){
      logger.error("Could not {} the specified {} lock",type,op);
      return false;
    }
   
    //If gotten to this point, return true
    return true;
  }
 
  //Release the lock on a selected filename
  public static boolean acquireReader(String filename){
    return lockOp(filename,'R','A');
  }
 
  //Release the lock on a selected filename
  public static boolean releaseReader(String filename){
    return lockOp(filename,'R','R');
  }
 
  //Release the lock on a selected filename
  public static boolean acquireWriter(String filename){
    return lockOp(filename,'W','A');
  }
 
  //Release the lock on a selected filename
  public static boolean releaseWriter(String filename){
    return lockOp(filename,'W','R');
  }
 
  //Create parent nodes if they don't already exist
  private static boolean createParentNodes(String[] nodes){
   
    //Sanity check
    if(nodes == null || !ZKSynch.client.isStarted()){
      return false;
    }
   
    //For every parent node, if it doesn't exist, create it
    try{
      String path = new String();
      for(int i = 0; i < nodes.length-1; i++){
        path += "/" + nodes[i];
        if(client.checkExists().forPath(path) == null){
          client.create().forPath(path);
        }
      }
    } catch (Exception e){
      logger.error("Could not create the parent nodes");
      return false;
    }
   
    return true;
  }
 
  //Store the metadata
  public static boolean putData(String filename, byte[] data){
   
    //Null check and make sure client is running
    if(filename == null || !ZKSynch.client.isStarted()){
      return false;
    }
   
    //If the node exists, store the data
    //Otherwise create a new node
    try{
      if(client.checkExists().forPath("/"+filename) != null){
        client.setData().forPath("/"+filename,data);
      }else{
       
        //Create the parent nodes if they don't exist
        String [] nodes = filename.split("/");
        if(createParentNodes(nodes)){
          //Create the node itself
          client.create().forPath("/"+filename,data);
        }else{
          return false;
        }
      }
     
      logger.info("Wrote {}",filename);
    }catch(Exception e){
      logger.error("Could not write {}",filename);
      return false;
    }
   
    return true;
  }
 
  //Put data in string form
  public static boolean putDataS(String filename, String data){
    return putData(filename,data.getBytes());
  }
 
  //Put data as an integer tuple
  //[0] = version, [1] = file size
  public static boolean putDataI(String filename, int version, int filesize){
    String data = String.format("%d_%d",version,filesize);
    return putData(filename,data.getBytes());
  }
 
  //Get the metadata from the specified node
  public static byte[] getData(String filename){
   
    //Null and connection check
    if(filename == null  || !ZKSynch.client.isStarted()){
      return null;
    }
   
    //Sanitize the filename
    filename = "/" + filename;
   
    try{
      if(client.checkExists().forPath(filename) != null){
        return client.getData().forPath(filename);
      }else{
        return null;
      }
    }catch(Exception e){
      logger.error("Could not get data from {}",filename);
      return null;
    }
  }
 
  //Return the data in string form
  public static String getDataS(String filename){
    byte[] data = getData(filename);
    if(data != null && data.length > 0){
      return new String(data);
    }else{
      return null;
    }
  }
 
  //Return the data as array of integers
  //[0] = version, [1] = file size
  public static int[] getDataI(String filename){
    byte[] data = getData(filename);
   
    if(data != null && data.length > 0){
      String[] d = new String(data).split("_");
      if(d.length < 2){
        return null;
      }
     
      int[] out = new int[2];
      out[0] = Integer.parseInt(d[0]);
      out[1] = Integer.parseInt(d[1]);
      return out;
    }else{
      return null;
    }
  }
 
  //Get a directory listing by fetching the children
  public static String[] getListing(String dirname){
    String[] out;
   
    //Null and connection check
    if(dirname == null  || !ZKSynch.client.isStarted()){
      return null;
    }
   
    try{
      //Fetch the list of children
      List<String> children =  client.getChildren().forPath(dirname.length() == 0 ? dirname : "/" + dirname);
     
      logger.info("The node {} has {} children",(dirname.length() == 0 ?"/":dirname),children.size());
     
      out = new String[children.size()];
     
      //Get the contents of
      int ctr = 0;
      for(String child : children){
        int[] data = getDataI(dirname.length() == 0 ? child : dirname + "/" + child);
        out[ctr] = child + "_" + (data != null ? data[1] : "dir");
        ctr++;
      }
     
      return out; 
    } catch (Exception e){
      logger.error("Could not fetch the directory listing for "+dirname);
      return null;
    }
  }
 
  public static ArrayList<String> getAllListing(){
   
    ArrayList<String> out = new ArrayList<String>();
   
    //Connection check
    if(!ZKSynch.client.isStarted()){
      return null;
    }
   
    //Start at the root
    try{
      List<String> children = client.getChildren().forPath("");
      logger.info("/ has {} children",children.size());
      for(String child : children){
        int[] data = getDataI(child);
        if (data != null){
          out.add(child+"_"+data[1]);
        } else {
          out.addAll(getAllListingRec(child));
        }
      }
      return out;
     
    } catch (Exception e){
      logger.error("Failed to fetch complete directory listing");
      logger.error(e.getMessage());
      return null;
    }
  }
 
  private static ArrayList<String> getAllListingRec(String path) throws Exception{
    ArrayList<String> out = new ArrayList<String>();
   
    List<String> children = client.getChildren().forPath("/" + path);
    logger.info("/"+path+" has {} children", children.size());
    for(String child : children){
      int[] data = getDataI(path + "/" + child);
      if(data != null){
        out.add(path + "/" + child + "_" + data[1]);
      } else {
        out.addAll(getAllListingRec(path + "/" + child));
      }
    }
    return out;
  }
 
  //Delete the specified node
  public static boolean delData(String filename){
   
    //Null and connection check
    if(filename == null  || !ZKSynch.client.isStarted()){
      return false;
    }
   
    //Sanitize the filename
    filename = "/" + filename;
   
    //Issue the delete command
    try{
      client.delete().forPath(filename);
      logger.info("Deleted {}",filename);
      return true;
    } catch (Exception e){
      logger.error("Could not delete {}",filename);
      return false;
    }
  }
 
  //Delete the node and all of its children
  public static boolean purge(String filename){
   
    //Null and connection check
    if(filename == null  || !ZKSynch.client.isStarted()){
      return false;
    }
   
    try{
      //Fetch the list of children
      List<String> children = client.getChildren().forPath("/"+filename);
     
      //If children exist, recursively delete them
      if(!children.isEmpty()){
        for(String child : children){
          purge(filename+"/"+child);
        }
      }
     
      //Delete the node itself
      client.delete().forPath("/"+filename);
      logger.info("Deleted /{}",filename);
     
    } catch (Exception e){
      logger.error("Could not purge /{}",filename);
      return false;
    }
   
    return true;
  }
}
TOP

Related Classes of ZK.ZKSynch

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.