diff options
author | Jonathan Bauer | 2015-03-04 17:02:45 +0100 |
---|---|---|
committer | Jonathan Bauer | 2015-03-04 17:02:45 +0100 |
commit | d871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb (patch) | |
tree | c40e57d523e6f5b9eda15281e60f27a088502220 /src/main/java/org/openslx/thrifthelper | |
parent | Add Dozmod Version file (diff) | |
download | master-sync-shared-d871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb.tar.gz master-sync-shared-d871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb.tar.xz master-sync-shared-d871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb.zip |
moved ThriftManager and ThriftHandler to master-sync-shared
Diffstat (limited to 'src/main/java/org/openslx/thrifthelper')
-rw-r--r-- | src/main/java/org/openslx/thrifthelper/ThriftHandler.java | 101 | ||||
-rw-r--r-- | src/main/java/org/openslx/thrifthelper/ThriftManager.java | 147 |
2 files changed, 248 insertions, 0 deletions
diff --git a/src/main/java/org/openslx/thrifthelper/ThriftHandler.java b/src/main/java/org/openslx/thrifthelper/ThriftHandler.java new file mode 100644 index 0000000..ed66678 --- /dev/null +++ b/src/main/java/org/openslx/thrifthelper/ThriftHandler.java @@ -0,0 +1,101 @@ +package org.openslx.thrifthelper; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.apache.thrift.TException; +import org.apache.thrift.transport.TTransportException; + +public class ThriftHandler<T extends Object> implements InvocationHandler { + + private final static Logger LOGGER = Logger.getLogger(ThriftHandler.class); + + public interface ClientCreationCallback<T> { + public T get(); + } + + private final ThreadLocal<T> clients = new ThreadLocal<T>(); + private final ClientCreationCallback<T> callback; + + public ThriftHandler(final Class<T> clazz, ClientCreationCallback<T> cb) { + callback = cb; + thriftMethods = Collections.unmodifiableSet(new HashSet<String>() { + private static final long serialVersionUID = 8983506538154055231L; + { + Method[] methods = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + boolean thrift = false; + Class<?>[] type = methods[i].getExceptionTypes(); + for (int e = 0; e < type.length; e++) { + if (TException.class.isAssignableFrom(type[e])) + thrift = true; + + } + String name = methods[i].getName(); + if (thrift && !name.startsWith("send_") && !name.startsWith("recv_")) { + add(name); + } + } + } + }); + } + + private final Set<String> thriftMethods; + + public Object invoke(Object tproxy, Method method, Object[] args) throws Throwable { + + // first find the thrift methods + if (!thriftMethods.contains(method.getName())) { + try { + return method.invoke(method, args); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + Throwable cause = e.getCause(); + if (cause == null) { + throw new RuntimeException(); + } + throw cause; + } + } + LOGGER.debug("Proxying '" + method.getName() + "'"); + + T client = getClient(false); + Throwable cause = null; + for (int i = 0; i < 3; i++) { + try { + return method.invoke(client, args); + } catch (InvocationTargetException e) { + cause = e.getCause(); + if (cause instanceof TTransportException) { + LOGGER.debug("Transport error - re-initialising ..."); + // new client + client = getClient(true); + } + } + } + + if (cause != null) + throw cause; + return null; + + } + + private T getClient(boolean forceNew) { + T client = clients.get(); + if (client != null && !forceNew) { + return client; + } + client = callback.get(); + if (client == null) { + // TODO own exception + throw new RuntimeException(); + } + clients.set(client); + return client; + } +} diff --git a/src/main/java/org/openslx/thrifthelper/ThriftManager.java b/src/main/java/org/openslx/thrifthelper/ThriftManager.java new file mode 100644 index 0000000..c6d8986 --- /dev/null +++ b/src/main/java/org/openslx/thrifthelper/ThriftManager.java @@ -0,0 +1,147 @@ +package org.openslx.thrifthelper; + +import java.lang.reflect.Proxy; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TFramedTransport; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TTransportException; +import org.openslx.imagemaster.thrift.iface.ImageServer; +import org.openslx.sat.thrift.iface.Server; +import org.openslx.thrifthelper.ThriftHandler.ClientCreationCallback; + +public class ThriftManager { + + private final static Logger LOGGER = Logger.getLogger(ThriftManager.class); + + /** + * Public variables to represent client types + * TODO: Public needed? + */ + public static enum ClientType { + MASTER, SATELLITE + } + /** + * Private singleton instances of itself and the satellite/master clients + */ + private static Server.Iface _satClient = (Server.Iface) Proxy.newProxyInstance( + Server.Iface.class.getClassLoader(), + new Class[] { Server.Iface.class }, new ThriftHandler<Server.Client>(Server.Client.class, new ClientCreationCallback<Server.Client>() { + + @Override + public Server.Client get() { + // first check if we have a sat ip + if (SATELLITE_IP == null) { + LOGGER.error("Satellite ip adress was not set prior to getting the sat client. Use setSatellite(<ip>)."); + return null; + } + // ok lets do it + TTransport transport = + new TSocket(SATELLITE_IP, SATELLITE_PORT, SATELLITE_TIMEOUT); + try { + transport.open(); + } catch (TTransportException e) { + LOGGER.error("Could not open transport to thrift's server with IP: " + SATELLITE_IP); + return null; + } + final TProtocol protocol = new TBinaryProtocol(transport); + // now we are ready to create the client, according to ClientType! + LOGGER.info("Satellite '" + SATELLITE_IP + "' reachable. Client initialised."); + return new Server.Client(protocol); + } + })); + + private static ImageServer.Iface _masterClient = (ImageServer.Iface) Proxy.newProxyInstance( + ImageServer.Iface.class.getClassLoader(), + new Class[] { ImageServer.Iface.class }, new ThriftHandler<ImageServer.Client>(ImageServer.Client.class, new ClientCreationCallback<ImageServer.Client>() { + + @Override + public ImageServer.Client get() { + // ok lets do it + TTransport transport = + new TFramedTransport(new TSocket(MASTERSERVER_IP, MASTERSERVER_PORT, MASTERSERVER_TIMEOUT)); + try { + transport.open(); + } catch (TTransportException e) { + LOGGER.error("Could not open transport to thrift's server with IP: " + MASTERSERVER_IP); + return null; + } + final TProtocol protocol = new TBinaryProtocol(transport); + // now we are ready to create the client, according to ClientType! + return new ImageServer.Client(protocol); + + } + })); + /** + * Private members for master connection information + */ + private static final String MASTERSERVER_IP = "132.230.4.16"; + private static final int MASTERSERVER_PORT = 9090; + private static final int MASTERSERVER_TIMEOUT = 30000; + + + /** + * Private members for satellite connection information + */ + private static String SATELLITE_IP = null; + private static final int SATELLITE_PORT = 9090; + private static final int SATELLITE_TIMEOUT = 10000; + + /** + * IP Validation Regex + */ + private static final String IP_VALID_PATTERN = + "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"; + + /** + * Sets the IP of the satellite to connect to + * @param ip the ip of the satellite as String + * @return true if setting the ip worked, false otherwise + */ + public static boolean setSatellite(String ip) { + if (ip.isEmpty()) { + LOGGER.error("Given IP for satellite is empty."); + return false; + } + // validate + Matcher matcher = Pattern.compile(IP_VALID_PATTERN).matcher(ip); + if (!matcher.matches()) { + LOGGER.error("Given form of IP is invalid: " + ip); + return false; + } + // finally set it + SATELLITE_IP = ip; + + // last check: try to connect + if (getSatClient() == null) { + // init failed + LOGGER.error("Could not initialise new client to satellite: " + SATELLITE_IP); + return false; + } + // TODO final last: get version from server + return true; + } + /** + * Returns the singleton client of the thrift connection to the satellite + * @return the thrift client to the satellite server + */ + public static Server.Iface getSatClient() { + return _satClient; + } + + /** + * Returns the singleton client of the master thrift connection + * @return the thrift client to the master server + */ + public static ImageServer.Iface getMasterClient() { + return _masterClient; + } +} |