Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.jc.zk.dpw; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.apache.zookeeper.AsyncCallback; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; import org.jc.zk.util.Utils; /** * * @author cespedjo */ public class DataMonitor implements Watcher, AsyncCallback.StatCallback, AsyncCallback.StringCallback, AsyncCallback.DataCallback, AsyncCallback.VoidCallback { private static final Logger logger = Logger.getLogger(DataMonitor.class); ZooKeeper zk; String znodeMaster; String znodeTime; String znodeProcessObserved; String znodeToCreateForUpdates; Watcher chainedWatcher; DataMonitorListenerMaster listener; private final String ownCMWFailoverZnode; private final List<String> cmwUpdateZnodes; private final String safeZnodeRemovalNotificationZnode; private final String processHeartBeatZnode; private boolean isActiveMaster; private final String amwRequestKillZnode; private static final String AMW_REQUEST_KILL_NODE = "amwrkn"; //Context key to store the MW requesting an operation. private static final String REQSTR_MASTER_ID = "rqmsid"; //Context key to store the type of znode is being: created, read from, updated or removed. private static final String ZNODE_TYPE = "zntype"; //Context value for key ZNODE_TYPE, indicating that it refers to KEEP ALIVE ZNODE (znodeMaster). private static final String KEEP_ALIVE_NODE = "kaln"; //Context value for key ZNODE_TYPE, indicating that it refers to PROCESS KEEP ALIVE NODE (znodeProcessObserved) private static final String PROCESS_KEEP_ALIVE_NODE = "pkaln"; //Context value for key ZNODE_TYPE, indicating that it refers to TIME ZNODE (znodeTime). private static final String TIME_NODE = "tmnode"; //Context key to store a znode's payload encoded as a string. private static final String ZNODE_PAYLOAD = "znpyl"; //Context value for key ZNODE_TYPE, indicating that it refers to UPDATE ZNODE (znodeToCreateForUpdates) private static final String CMW_UPDATE_NODE = "cmwupn"; //Context value for key ZNODE_TYPE, indicating that it refers to NOTIFICATION ZNODE (safeZnodeRemovalNotificationZnode) private static final String NOTIFICATION_ZNODE = "nozn"; //Context key to store the type of event associated to CMW_UPDATE_NODE. private static final String UPDATE_NODE_EVENT = "upnev"; //Context value for key UPDATE_NODE_EVENT, indicating that CMW_UPDATE_NODE is being created. private static final String UPDATE_EVENT_IS_CREATE = "upiscrt"; //Context value for key UPDATE_NODE_EVENT, indicating that CMW_UPDATE_NODE is being changed. private static final String UPDATE_EVENT_IS_CHANGED = "upischn"; /** * Masters' Data Monitor constructor. * @param zk instance of zookeeper. * @param znodeMaster path to masters' znode. * @param znodeTime path to time masters' time update znode. * @param znodeProcessObserved path to observed znode. * @param znodeToCreateForUpdates path to znode that a CMW will have to update * when requested by ATM. This is null when instantiating a monitor for a MW. * @param ownCMWFailoverZnode failover znode that will be created by active * CMW to indicate its inactive pair to activate itself. * @param safeZnodeRemovalNotificationZnode * @param cmwUpdateZnodes * @param processHeartBeatZnode path to znode that CMW will create to request * heart beat from ProcessWrappers. * @param chainedWatcher another watcher to which events will be forwarded * after processing locally. * @param listener instance of class implementing listener interface. */ public DataMonitor(ZooKeeper zk, String znodeMaster, String znodeTime, String znodeProcessObserved, String znodeToCreateForUpdates, String ownCMWFailoverZnode, String safeZnodeRemovalNotificationZnode, List<String> cmwUpdateZnodes, String processHeartBeatZnode, String amwRequestKillZnode, Watcher chainedWatcher, DataMonitorListenerMaster listener) { this.zk = zk; this.znodeTime = znodeTime; this.znodeMaster = znodeMaster; this.chainedWatcher = chainedWatcher; this.listener = listener; this.znodeProcessObserved = znodeProcessObserved; this.znodeToCreateForUpdates = znodeToCreateForUpdates; this.ownCMWFailoverZnode = ownCMWFailoverZnode; this.cmwUpdateZnodes = cmwUpdateZnodes; this.safeZnodeRemovalNotificationZnode = safeZnodeRemovalNotificationZnode; this.processHeartBeatZnode = processHeartBeatZnode; this.isActiveMaster = false; this.amwRequestKillZnode = amwRequestKillZnode; } public interface DataMonitorListenerMaster { /** * Invoke this method to handle an event like session expired or some error. * @param rc reason code for closing. */ //void closing(int rc); /** * The first time an active master writes to a znode, this is the method * invoked by callback to notify status of first write. * @param error true if something went wrong, false otherwise. */ //void dataWrittenToZnode(boolean error); /** * This callback is invoked when data is retrieved from znode. * The master will probably have to take time information from it. * @param data data retrieved from znode. */ void dataReadFromZnode(byte[] data); /** * This callback allows masters find out who the elected master is. * @param masterId Id of the selected master. */ void masterElected(String masterId); /** * This callback is invoked to indicate the result of the masters' keep * alive znode. * @param error true to indicate that there was an error or false otherwise. * @param data byte array containing the data that was used to create znode. * This is null if creation was completed successfully. */ void masterWatcherZnodeCreated(boolean error, byte[] data); /** * This callback is invoked to indicate the result of the znode that * tells CMWs to deploy their processes. * @param error true to indicate that there was an error or false otherwise. * @param data byte array containing the data that was used to create znode. * This is null if creation was completed successfully. */ void processDataNodeCreated(boolean error, byte[] data); /** * This callback is invoked when the znode for time listeners receives * an update from TM. * @param data the data that was written to time znode by the TM. */ void timeUpdated(byte[] data); /** * Callback invoked when data from processes' znode has been read. * @param data byte array representing the data stored in znode. */ void dataReadFromProcessZnode(byte[] data); /** * Callback invoked to notify the result of the update issued by CMW to its update znode * @param znode the znode assigned to CMW that must be created to ack * that a CMW is alive. * @param data the data that was written to znode or null if an error occurred * while creating update znode. */ void childMasterWatcherUpdatedZnode(String znode, byte[] data); //void childMasterWatcherZnodeData(byte[] data); //void znodeRemoved(String path, boolean error); /** * Callback invoked when client is connected to ZooKeeper. */ void connected(); /** * Callback invoked when a client disconnects. * @param rc an int representing reason code. */ void disconnected(int rc); /** * This method will be invoked to notify which MW will be allowed to remove * znodes created by former AMW and who will be able to remove notification znode. * @param allowedToAttemptZnodesRemoval true if the MW will be allowed to remove * znodes or false if it cannot remove znodes. */ void recreateMasterZnode(boolean allowedToAttemptZnodesRemoval); /** * Callback to notify clients that masters' keep alive znode changed. */ void masterZnodeChanged(); /** * Callback to notify clients that masters' keep alive was removed. */ void masterZnodeRemoved(); /** * Callback to notify clients that masters' keep alive znode was created. */ void masterZnodeCreated(); /** * Callback to notify clients that znode for time listeners changed. */ void timeZnodeChanged(); /** * Callback to notify clients that znode for time listeners changed. */ void timeZnodeRemoved(); /** * Callback to notify that CMW created its assigned update znode. * @param znode path to znode. */ void cmwUpdatedUpdateZnode(String znode); /** * Callback to notify clients that update znode was removed. */ void cmwUpdateZnodeRemoved(); /** * Callback invoked when a new failover znode was created. * @param znode failover znode that was created. */ void cmwFailoverZnodeCreated(String znode); /** * Callback invoked when process observed znode was created. */ void processObservedZnodeCreated(); /** * Callback invoked when process observed znode changed. */ void processObservedZnodeChanged(); /** * Callback invoked when process observed znode is removed. */ void processObservedZnodeRemoved(); /** * Callback invoked to notify that data set to masters' keep alive znode * is done. * * @param data byte array representing the data that was written to znode. * @param error boolean indicating if there was an error. True if an error * occurred, false otherwise. */ void masterZnodeDataSetCompleted(byte[] data, boolean error); /** * Callback invoked to notify listeners that znode for time listeners has * been created. */ void timeZnodeCreated(); /** * Callback invoked to notify ProcessWrappers that an update has been * requested by CMW. */ void processHeartBeatZnodeUpdate(); /** * Callback invoked to notify CMWs that the AMW created update znode and * it is expecting CMW to update it. * @param time the time contained in update znode created by AMW. */ void updateZnodeCreated(long time); /** * Callback invoked to notify the AMW the result of the creation of the * update znode. * * @param znode path of znode. * @param data byte array representing the data that must have been written * to znode on creation time. This will probably be null if the creation succeeded. * @param error boolean indicating whether an error occurred or not during * creation of znode. */ void updateZnodeCreatedByMaster(String znode, byte[] data, boolean error); /** * Callback invoked to notify about the result of setting data under * AMW request kill znode. * @param data byte array representing the data to be written. * @param error boolean indicating whether an error occurred or not * while writing to znode. */ void amwRequestKillZnodeUpdated(byte[] data, boolean error); /** * Callback invoked to notify MW about a change in AMW kill request * znode. */ void amwRequestKillZnodeChanged(); /** * Callback invoked to notify MW that data has been retrieved from AMW * kill request znode. * * @param data byte array representing the data that was read from znode. */ void dataReadFromAmwRequestKillZnode(byte[] data); } /** * Method to be invoked to bind/re-bind to existing znodes * Remember that MWs also have CMWs, and depending on which type of MW * will be assigned this DM, some will bind to certain nodes while others * won't. * @param isActiveMaster boolean indicating whether the MW trying to bind is * an active master or not. */ public void bindToZnodes(boolean isActiveMaster) { this.isActiveMaster = isActiveMaster; this.zk.exists(this.znodeMaster, this, this, null); //A null znodeToCreateForUpdates refers to a MW trying to bind to znodes, //a non-null znode, indicates that a CMW is trying to bind. //CMWs only need to bind to their own update znode. if (this.znodeToCreateForUpdates != null) { this.zk.exists(this.ownCMWFailoverZnode, this, this, null); this.zk.exists(this.znodeProcessObserved, this, this, null); this.zk.exists(this.znodeToCreateForUpdates, this, this, null); } else { if (this.isActiveMaster) { for (String znForUpdate : this.cmwUpdateZnodes) { logger.info("MW binding to CMW Update: " + znForUpdate); this.zk.exists(znForUpdate, this, this, null); } } //Bind to AMW kill request znode. this.zk.exists(this.amwRequestKillZnode, this, this, null); } this.zk.exists(this.znodeTime, this, this, null); } /** * Invoke this method to create the notification flag znode. */ public void createTimeZnodeRemovedFlag() { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, NOTIFICATION_ZNODE); this.zk.create(this.safeZnodeRemovalNotificationZnode, "0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, ctx); } /** * Invoke this method when MWs are starting for electing the active master. The * masterId that gets to create the time znode first becomes the active master. * @param masterId String representing the identifier of a MW. * @param znode the znode that will be created for listening to time ticks. * @param data byte array representing the data to be stored under the znode. */ public void createTimeZnode(String masterId, String znode, byte[] data) { HashMap<String, String> ctx = new HashMap<>(); ctx.put(REQSTR_MASTER_ID, masterId); ctx.put(ZNODE_TYPE, TIME_NODE); this.zk.create(znode, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, ctx); } /** * Active MW invokes this method to create the keep alive znode, where it will * report its health status and the IMWs can poll about active's health status * to decide whether a new active master is needed. * @param masterId String representing the identifier of the AMW. * @param znode String representing the znode that will be created for health * status updates. * @param data byte array representing the data */ public void createKeepAliveZnode(String masterId, String znode, byte[] data) { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, KEEP_ALIVE_NODE); ctx.put(ZNODE_PAYLOAD, Utils.masterWatcherZnodeDataToString(data)); this.zk.create(znode, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, ctx); } /** * Active MW invokes this method to create the process observed znode. It signals * active CMWs that it is time for them to deploy their child processes. * @param znode String representing the znode to be used to indicate deployment time. * @param data byte array representing the data to be written to process observed znode. */ public void createProcessKeepAliveZnode(String znode, byte[] data) { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, PROCESS_KEEP_ALIVE_NODE); ctx.put(ZNODE_PAYLOAD, Utils.processObservedZnodeDataToString(data)); this.zk.create(znode, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, ctx); } /** * This method is invoked by Active MW to update data in znode, that is, report * its health status to IMWs. * @param data byte array representing the data to be written to znode. */ public void updateZnodesData(byte[] data) { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, KEEP_ALIVE_NODE); ctx.put(ZNODE_PAYLOAD, Utils.masterWatcherZnodeDataToString(data)); this.zk.setData(this.znodeMaster, data, -1, this, ctx); } /** * This method is invoked to read the last update that was pushed to keep alive * znode by the Active MW. It will allow the current active MW identify whether * it is still the active MW and if it is allow to push a new update. On the other * hand, it will allow IMWs identify whether the current active MW is alive or * not. */ public void readLastUpdate() { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, KEEP_ALIVE_NODE); this.zk.getData(this.znodeMaster, null, this, ctx); } /** * This method is invoked to retrieve the last time tick issued by active * TM. */ public void readTimesZnodeLastUpdate() { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, TIME_NODE); this.zk.getData(this.znodeTime, null, this, ctx); } /** * This method is invoked by CMWs to update the update znode that was assigned * to them and where the AMW is expecting for updates. * @param data byte array representing the data that will be written to update znode. */ public void setChildMasterWatcherZnode(byte[] data) { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, CMW_UPDATE_NODE); ctx.put(ZNODE_PAYLOAD, Utils.childMasterWatcherDataToString(data)); ctx.put(UPDATE_NODE_EVENT, UPDATE_EVENT_IS_CHANGED); //this.zk.create(this.znodeToCreateForUpdates, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, ctx); this.zk.setData(this.znodeToCreateForUpdates, data, -1, this, ctx); } /** * Method invoked by current active MW to create a given update znode and to * allow CMW to report its health status. * @param znode String representing the update znode that will be created. * @param data byte array representing the data that will be set under znode. */ public void createChildMasterWatcherZnodeByActiveMaster(String znode, byte[] data) { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, CMW_UPDATE_NODE); ctx.put(ZNODE_PAYLOAD, Utils.childMasterWatcherDataToString(data)); ctx.put(UPDATE_NODE_EVENT, UPDATE_EVENT_IS_CREATE); this.zk.create(znode, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, ctx); } /** * Method invoked by CMWs to temporarily bind to a given heart beat znode. It * is normally used by a CMW to obtain an update from a ProcessWrapper. * @param heartBeatZnode String representing the znode that will be created. */ public void temporaryBindToHeartBeat(String heartBeatZnode) { this.zk.exists(heartBeatZnode, this, this, null); } /** * Method invoked by CMWs to create the znode that will be used * to signal ProcessWrappers that it is time to report their health statuses. * @param heartBeatZnode String representing the znode where a heart beat will * be placed. * @param dummyData byte array representing the data. It is not so dummy since * it contains a flag indicating whether the CMW is trying to destroy the ProcessWrapper * or just trying to get an update from them. */ public void createProcessHeartBeatZnode(String heartBeatZnode, byte[] dummyData) { Map<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, ""); logger.info("Creating heart beat znode: " + heartBeatZnode); this.zk.create(heartBeatZnode, dummyData, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, ctx); } /** * Method invoked by CMWs to remove heart beat znodes. */ public void removeProcessHeartBeatZnode() { this.zk.delete(this.processHeartBeatZnode, -1, this, null); } /** * Method invoked by current active MW to read the update pushed by CMW to * later add it to its internal global updates queue. NOTE: using this leads * to unexpected behavior. Please use the method readCMWUpdateZnodeData. */ @Deprecated public void readChildMasterWatcherZnode() { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, CMW_UPDATE_NODE); this.zk.getData(this.znodeToCreateForUpdates, null, this, ctx); } /** * Method invoked to remove a znode. * @param path String representing the znode to be removed. */ public void removeZnode(String path) { this.zk.delete(path, -1, this, null); } /* public void createFailoverZnode(String path) { this.zk.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, this, null); }*/ /** * Method invoked by current active MW to read the update pushed by CMW to * later add it to its internal global updates queue. * @param path String representing the znode that MW needs to read from. */ public void readCMWUpdateZnodeData(String path) { HashMap<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, CMW_UPDATE_NODE); ctx.put(UPDATE_NODE_EVENT, UPDATE_EVENT_IS_CHANGED); this.zk.getData(path, this, this, ctx); } /** * Method to retrieve data from AMW kill request znode. */ public void readAmwRequestKillZnodeData() { Map<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, AMW_REQUEST_KILL_NODE); this.zk.getData(this.amwRequestKillZnode, this, this, ctx); } /** * Method invoked to write data to AMW kill request znode. * @param data byte array representing data to be written to znode. */ public void setAmwRequestKillZnodeData(byte[] data) { Map<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, AMW_REQUEST_KILL_NODE); ctx.put(ZNODE_PAYLOAD, Utils.requestAMWKillZnodeDataToString(data)); this.zk.setData(this.amwRequestKillZnode, data, -1, this, ctx); } @Override public void process(WatchedEvent event) { String path = event.getPath(); switch (event.getType()) { case NodeDataChanged: if (path.equals(this.znodeTime)) { //Time has been updated this.listener.timeZnodeChanged(); } else if (path.equals(this.znodeMaster)) { this.listener.masterZnodeChanged(); } else if (path.equals(this.processHeartBeatZnode)) { this.listener.processHeartBeatZnodeUpdate(); } else if (this.znodeToCreateForUpdates == null && this.cmwUpdateZnodes.contains(event.getPath())) { this.listener.cmwUpdatedUpdateZnode(event.getPath()); } else if (this.znodeToCreateForUpdates != null && this.znodeToCreateForUpdates.equals(event.getPath())) { this.bindToZnodes(this.isActiveMaster); } else if (path.equals(this.amwRequestKillZnode)) { this.listener.amwRequestKillZnodeChanged(); } break; case None: if (event.getState() == Event.KeeperState.Expired || event.getState() == Event.KeeperState.Disconnected) { this.listener.disconnected(KeeperException.Code.CONNECTIONLOSS.intValue()); } else if (event.getState() == Event.KeeperState.SyncConnected) { this.listener.connected(); } break; case NodeDeleted: if (event.getPath().equals(this.znodeTime)) { this.listener.timeZnodeRemoved(); } else if (event.getPath().equals(this.znodeProcessObserved)) { this.listener.processObservedZnodeRemoved(); } else if (this.cmwUpdateZnodes.contains(event.getPath())) { this.listener.cmwUpdateZnodeRemoved(); } break; case NodeCreated: if (this.ownCMWFailoverZnode != null && this.ownCMWFailoverZnode.equals(event.getPath())) { this.listener.cmwFailoverZnodeCreated(event.getPath()); } else if (this.znodeToCreateForUpdates != null && this.znodeToCreateForUpdates.equals(event.getPath())) { /** * To comply with the old model, where CMWs created update * znode, instead of waiting for AMW to create them, once CMW * detects that update znode was created by AMW, it will * automatically read the data from znode, that is, instead * of invoking callback to notify about the creation of znode * by master, it will proceed to read the content and later * notify CMW about the new data. */ Map<String, String> ctx = new HashMap<>(); ctx.put(ZNODE_TYPE, CMW_UPDATE_NODE); ctx.put(UPDATE_NODE_EVENT, UPDATE_EVENT_IS_CREATE); this.zk.getData(path, this, this, ctx); } else if (this.znodeToCreateForUpdates == null && this.cmwUpdateZnodes.contains(event.getPath())) { this.bindToZnodes(this.isActiveMaster); } else if (event.getPath().equals(this.znodeMaster)) { this.listener.masterZnodeCreated(); } else if (event.getPath().equals(this.znodeTime)) { this.listener.timeZnodeCreated(); } else if (event.getPath().equals(this.znodeProcessObserved)) { this.listener.processObservedZnodeCreated(); } break; } } /** * Callback when deleting znode. * @param rc * @param path * @param ctx */ @Override public void processResult(int rc, String path, Object ctx) { switch (KeeperException.Code.get(rc)) { case OK: //this.listener.znodeRemoved(path, false); break; case CONNECTIONLOSS: case SESSIONEXPIRED: this.listener.disconnected(rc); break; case OPERATIONTIMEOUT: case AUTHFAILED: //this.listener.znodeRemoved(path, true); break; } } /** * Callback for setting/binding data. * @param rc * @param path * @param ctx * @param stat */ @Override public void processResult(int rc, String path, Object ctx, Stat stat) { switch (KeeperException.Code.get(rc)) { case OK: if (ctx == null) { //We're just binding //Nothing else needs to be done here. } else { HashMap<String, String> mCtx = (HashMap<String, String>) ctx; switch (mCtx.get(ZNODE_TYPE)) { case KEEP_ALIVE_NODE: this.listener.masterZnodeDataSetCompleted( Utils.masterWatcherZnodeDataToBytes(mCtx.get(ZNODE_PAYLOAD)), false); break; case CMW_UPDATE_NODE: //Everything went fine, nothing to do. break; case AMW_REQUEST_KILL_NODE: String amwPartData = Utils.getDataFromRequestAmwKillZnodeData(mCtx.get(ZNODE_PAYLOAD)); String amwPartType = Utils.getTypeFromRequestAmwKillZnodeData(mCtx.get(ZNODE_PAYLOAD)); String amwPartRequester = Utils .getRequesterFromRequestAmwKillZnodeData(mCtx.get(ZNODE_PAYLOAD)); byte[] amwData = Utils.requestAMWKillZnodeDataToBytes(amwPartData, amwPartType, amwPartRequester); this.listener.amwRequestKillZnodeUpdated(amwData, false); break; } } break; case SESSIONEXPIRED: case CONNECTIONLOSS: this.listener.disconnected(rc); break; case OPERATIONTIMEOUT: case AUTHFAILED: if (ctx == null) { //Bind failed, retry. this.bindToZnodes(this.isActiveMaster); } else { HashMap<String, String> mCtx = (HashMap<String, String>) ctx; switch (mCtx.get(ZNODE_TYPE)) { case KEEP_ALIVE_NODE: this.listener.masterZnodeDataSetCompleted( Utils.masterWatcherZnodeDataToBytes(mCtx.get(ZNODE_PAYLOAD)), true); break; case CMW_UPDATE_NODE: this.setChildMasterWatcherZnode(Utils.childMasterWatcherDataToBytes(mCtx.get(ZNODE_PAYLOAD))); break; case AMW_REQUEST_KILL_NODE: String amwPartData = Utils.getDataFromRequestAmwKillZnodeData(mCtx.get(ZNODE_PAYLOAD)); String amwPartType = Utils.getTypeFromRequestAmwKillZnodeData(mCtx.get(ZNODE_PAYLOAD)); String amwPartRequester = Utils .getRequesterFromRequestAmwKillZnodeData(mCtx.get(ZNODE_PAYLOAD)); byte[] amwData = Utils.requestAMWKillZnodeDataToBytes(amwPartData, amwPartType, amwPartRequester); this.listener.amwRequestKillZnodeUpdated(amwData, true); break; } } break; } } /** * Callback when creating a znode * @param rc * @param path * @param ctx * @param name */ @Override public void processResult(int rc, String path, Object ctx, String name) { if (ctx == null) { //Operation result is not important, exiting... return; } Map<String, String> cCtx = (HashMap<String, String>) ctx; switch (KeeperException.Code.get(rc)) { case OK: switch (cCtx.get(ZNODE_TYPE)) { case KEEP_ALIVE_NODE: final byte[] dataKA = ((HashMap<String, String>) ctx).get(ZNODE_PAYLOAD).getBytes(); new Thread(new Runnable() { @Override public void run() { DataMonitor.this.listener.masterWatcherZnodeCreated(false, dataKA); } }).start(); //this.listener.masterWatcherZnodeCreated(false, dataKA); break; case PROCESS_KEEP_ALIVE_NODE: byte[] dataPKA = Utils.processObservedZnodeDataToBytes(cCtx.get(ZNODE_PAYLOAD)); this.listener.processDataNodeCreated(false, dataPKA); break; case TIME_NODE: this.listener.masterElected(cCtx.get(REQSTR_MASTER_ID)); break; case CMW_UPDATE_NODE: //this.zk.getData(path, null, this, ((HashMap<String, String>)ctx)); byte[] dataCMU = Utils .updateZnodeCreatedByMastersDataToBytes(Long.valueOf(cCtx.get(ZNODE_PAYLOAD))); this.listener.updateZnodeCreatedByMaster(path, dataCMU, false); break; case NOTIFICATION_ZNODE: new Thread(new Runnable() { @Override public void run() { DataMonitor.this.listener.recreateMasterZnode(true); } }).start(); break; } break; case NODEEXISTS: //Master already elected, just return a dummy id switch (cCtx.get(ZNODE_TYPE)) { case KEEP_ALIVE_NODE: this.listener.masterElected("-9999999"); break; case NOTIFICATION_ZNODE: new Thread(new Runnable() { @Override public void run() { DataMonitor.this.listener.recreateMasterZnode(false); } }).start(); break; } break; case CONNECTIONLOSS: case SESSIONEXPIRED: this.listener.disconnected(rc); break; case OPERATIONTIMEOUT: case NOAUTH: switch (((HashMap<String, String>) ctx).get(ZNODE_TYPE)) { case KEEP_ALIVE_NODE: byte[] eDataKA = cCtx.get(ZNODE_PAYLOAD).getBytes(); this.listener.masterWatcherZnodeCreated(true, eDataKA); break; case PROCESS_KEEP_ALIVE_NODE: byte[] eDataPKA = cCtx.get(ZNODE_PAYLOAD).getBytes(); this.listener.processDataNodeCreated(true, eDataPKA); break; case TIME_NODE: this.listener.masterElected(null); break; case CMW_UPDATE_NODE: byte[] eDataCMU = Utils .updateZnodeCreatedByMastersDataToBytes(Long.valueOf(cCtx.get(ZNODE_PAYLOAD))); this.listener.updateZnodeCreatedByMaster(path, eDataCMU, true); break; } break; } } /** * Callback when reading data * @param rc * @param path * @param ctx * @param data * @param stat */ @Override public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) { Map<String, String> cCtx = (HashMap<String, String>) ctx; switch (KeeperException.Code.get(rc)) { case OK: switch (cCtx.get(ZNODE_TYPE)) { case KEEP_ALIVE_NODE: this.listener.dataReadFromZnode(data); break; case PROCESS_KEEP_ALIVE_NODE: this.listener.dataReadFromProcessZnode(data); break; case TIME_NODE: /* Note that it is absolutely necessary to wrap this callback into a new thread since the method blocks until all CMWs send a heartbeat. Normally, every callback invocation should be wrapped inside a new thread, however now we can just wrap this unique callback. */ final byte[] fData = data; new Thread(new Runnable() { @Override public void run() { DataMonitor.this.listener.timeUpdated(fData); } }).start(); break; case CMW_UPDATE_NODE: if (cCtx.get(UPDATE_NODE_EVENT).equals(UPDATE_EVENT_IS_CREATE)) { final byte[] uData = data; new Thread(new Runnable() { @Override public void run() { DataMonitor.this.listener.updateZnodeCreated( Long.valueOf(Utils.updateZnodeCreatedByMastersDataToString(uData))); } }).start(); } else if (cCtx.get(UPDATE_NODE_EVENT).equals(UPDATE_EVENT_IS_CHANGED)) { this.listener.childMasterWatcherUpdatedZnode(path, data); } break; case AMW_REQUEST_KILL_NODE: final byte[] fAmwData = data; new Thread(new Runnable() { @Override public void run() { DataMonitor.this.listener.dataReadFromAmwRequestKillZnode(fAmwData); } }).start(); break; } break; case CONNECTIONLOSS: case SESSIONEXPIRED: this.listener.disconnected(rc); break; case OPERATIONTIMEOUT: case NOAUTH: switch (cCtx.get(ZNODE_TYPE)) { case KEEP_ALIVE_NODE: this.listener.dataReadFromZnode(null); break; case PROCESS_KEEP_ALIVE_NODE: this.listener.dataReadFromProcessZnode(null); break; case TIME_NODE: this.listener.timeUpdated(null); break; case CMW_UPDATE_NODE: if (cCtx.get(UPDATE_NODE_EVENT).equals(UPDATE_EVENT_IS_CREATE)) { this.zk.getData(path, this, this, cCtx); } else if (cCtx.get(UPDATE_NODE_EVENT).equals(UPDATE_EVENT_IS_CHANGED)) { this.listener.childMasterWatcherUpdatedZnode(path, null); } break; case AMW_REQUEST_KILL_NODE: this.listener.dataReadFromAmwRequestKillZnode(null); break; } break; } } }