package com.zillabyte.motherbrain.coordination;
import java.io.Serializable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeoutException;
public interface CoordinationService extends Serializable {
public void initialize() throws CoordinationException;
public void shutdown() throws CoordinationException;
/***
* Gets the value associated with this key from the distributed service.
* @param key
* @param defaultState The default value to return if no state is found
* @return
* @throws CoordinationException
*/
public <T> T getState(String key, T defaultState) throws CoordinationException;
/***
* Sets the value associated with this key
* @param key
* @param value
* @throws CoordinationException
*/
public <T> void setState(String key, T value) throws CoordinationException;
/**
* Return true if the specified key exists
* @param key
* @return
* @throws CoordinationException
*/
public boolean hasState(String key) throws CoordinationException;
/**
* Clears all state beginning with key
* @param key
* @throws CoordinationException
*/
public void removeStateWithPrefix(String key) throws CoordinationException;
/***
* Clears all state AND locks AND watchers
* @throws CoordinationException
*/
public void clear() throws CoordinationException;
/****
* Obtains a global lock on a specified key. Use this when you want to lock a resouce
* between disparate machines.
*
* The return value is a Lock object. You MUST use this object to release the lock later.
* You should always wrap the code after lock() in a try {} finally { lock.release() }
* so we do not have orphaned locks when errors occur.
*
* @param lockPath the lock key
* @param timeout how long to wait before throwing a TimeoutException?
* @param duration how long should this lock exist? This is useful when machines die, otherwise locks exist forever
* @return
* @throws CoordinationException
* @throws TimeoutException
*/
public Lock lock(String lockPath, long timeout, long duration) throws CoordinationException, TimeoutException;
/***
* Sends a message to a remote listener. This method as asynchronous, and does not guarantee delivery
* or acknowledgment.
*
* If you require a 'return reciept' -- that is, you wish to assert that the message was recived by
* the remote host, then use the sendTransactionalMessage() method
*
* If you require a response from the remoteHost, then use the ask(..) method
*
* @param channel
* @param message
* @throws CoordinationException
*/
public void sendMessage(String channel, Object message) throws CoordinationException;
/***
* Sends a message with the added gurantee that it has been acknowledged by the remote host.
* Kind of like certified mail.
*
* @param channel
* @param message
* @param timeout how long to wait before we give up?
* @throws CoordinationException
* @throws TimeoutException
*/
public void sendTransactionalMessage(ExecutorService exec, String channel, Object message, long timeout) throws CoordinationException, TimeoutException;
/***
* like he above sendMessage()s, but also gets a response back from the remote agent.
* @param channel
* @param message
* @param timeout
* @return
* @throws CoordinationException
* @throws TimeoutException
*/
public Object ask(ExecutorService exec, String channel, Object message, long timeout) throws CoordinationException, TimeoutException;
/***
* Watches for messages from remote machines on the cluster.
*
* @param channel
* @param messageHandler the callback to handle message
* @return
* @throws CoordinationException
*/
public Watcher watchForMessage(ExecutorService exec, String channel, MessageHandler messageHandler) throws CoordinationException;
/***
* Watches for remote 'asks' from remote machines on the cluster.
*
* And 'ask' is simply a message that requires a response.
*
* @param channel
* @param askHandler
* @return
* @throws CoordinationException
*/
public Watcher watchForAsk(ExecutorService exec, String channel, AskHandler askHandler) throws CoordinationException;
}