/**
 * Autogenerated by Thrift Compiler (0.9.2)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package backtype.storm.generated;

import org.apache.thrift.scheme.IScheme;
import org.apache.thrift.scheme.SchemeFactory;
import org.apache.thrift.scheme.StandardScheme;

import org.apache.thrift.scheme.TupleScheme;
import org.apache.thrift.protocol.TTupleProtocol;
import org.apache.thrift.protocol.TProtocolException;
import org.apache.thrift.EncodingUtils;
import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
import org.apache.thrift.server.AbstractNonblockingServer.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Set;
import java.util.HashSet;
import java.util.EnumSet;
import java.util.Collections;
import java.util.BitSet;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.annotation.Generated;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-10-20")
public class Nimbus {

  public interface Iface {

    public void submitTopology(String name, String uploadedJarLocation, String jsonConf, StormTopology topology) throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException;

    public void submitTopologyWithOpts(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, SubmitOptions options) throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException;

    public void killTopology(String name) throws NotAliveException, TException;

    public void killTopologyWithOpts(String name, KillOptions options) throws NotAliveException, TException;

    public void activate(String name) throws NotAliveException, TException;

    public void deactivate(String name) throws NotAliveException, TException;

    public void rebalance(String name, RebalanceOptions options) throws NotAliveException, InvalidTopologyException, TException;

    public void metricMonitor(String name, MonitorOptions options) throws NotAliveException, TException;

    public void restart(String name, String jsonConf) throws NotAliveException, InvalidTopologyException, TopologyAssignException, TException;

    public void beginLibUpload(String libName) throws TException;

    public String beginFileUpload() throws TException;

    public void uploadChunk(String location, ByteBuffer chunk) throws TException;

    public void finishFileUpload(String location) throws TException;

    public String beginFileDownload(String file) throws TException;

    public ByteBuffer downloadChunk(String id) throws TException;

    public void finishFileDownload(String id) throws TException;

    public String getNimbusConf() throws TException;

    public String getTopologyConf(String id) throws NotAliveException, TException;

    public String getTopologyId(String topologyName) throws NotAliveException, TException;

    public ClusterSummary getClusterInfo() throws TException;

    public SupervisorWorkers getSupervisorWorkers(String host) throws NotAliveException, TException;

    public TopologyInfo getTopologyInfo(String id) throws NotAliveException, TException;

    public TopologyInfo getTopologyInfoByName(String topologyName) throws NotAliveException, TException;

    public StormTopology getTopology(String id) throws NotAliveException, TException;

    public StormTopology getUserTopology(String id) throws NotAliveException, TException;

    public void uploadTopologyMetrics(String topologyId, TopologyMetric topologyMetrics) throws TException;

    public Map<String,Long> registerMetrics(String topologyId, Set<String> metrics) throws TException;

    public TopologyMetric getTopologyMetrics(String topologyId) throws TException;

    public List<MetricInfo> getMetrics(String topologyId, int type) throws TException;

    public MetricInfo getNettyMetrics(String topologyId) throws TException;

    public MetricInfo getNettyMetricsByHost(String topologyId, String host) throws TException;

    public MetricInfo getPagingNettyMetrics(String topologyId, String host, int page) throws TException;

    public int getNettyMetricSizeByHost(String topologyId, String host) throws TException;

    public MetricInfo getTaskMetrics(String topologyId, String component) throws TException;

    public List<MetricInfo> getTaskAndStreamMetrics(String topologyId, int taskId) throws TException;

    public List<MetricInfo> getSummarizedTopologyMetrics(String topologyId) throws TException;

    public String getVersion() throws TException;

    public void updateTopology(String name, String uploadedLocation, String updateConf) throws NotAliveException, InvalidTopologyException, TException;

    public void updateTaskHeartbeat(TopologyTaskHbInfo taskHbs) throws TException;

  }

  public interface AsyncIface {

    public void submitTopology(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, AsyncMethodCallback resultHandler) throws TException;

    public void submitTopologyWithOpts(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, SubmitOptions options, AsyncMethodCallback resultHandler) throws TException;

    public void killTopology(String name, AsyncMethodCallback resultHandler) throws TException;

    public void killTopologyWithOpts(String name, KillOptions options, AsyncMethodCallback resultHandler) throws TException;

    public void activate(String name, AsyncMethodCallback resultHandler) throws TException;

    public void deactivate(String name, AsyncMethodCallback resultHandler) throws TException;

    public void rebalance(String name, RebalanceOptions options, AsyncMethodCallback resultHandler) throws TException;

    public void metricMonitor(String name, MonitorOptions options, AsyncMethodCallback resultHandler) throws TException;

    public void restart(String name, String jsonConf, AsyncMethodCallback resultHandler) throws TException;

    public void beginLibUpload(String libName, AsyncMethodCallback resultHandler) throws TException;

    public void beginFileUpload(AsyncMethodCallback resultHandler) throws TException;

    public void uploadChunk(String location, ByteBuffer chunk, AsyncMethodCallback resultHandler) throws TException;

    public void finishFileUpload(String location, AsyncMethodCallback resultHandler) throws TException;

    public void beginFileDownload(String file, AsyncMethodCallback resultHandler) throws TException;

    public void downloadChunk(String id, AsyncMethodCallback resultHandler) throws TException;

    public void finishFileDownload(String id, AsyncMethodCallback resultHandler) throws TException;

    public void getNimbusConf(AsyncMethodCallback resultHandler) throws TException;

    public void getTopologyConf(String id, AsyncMethodCallback resultHandler) throws TException;

    public void getTopologyId(String topologyName, AsyncMethodCallback resultHandler) throws TException;

    public void getClusterInfo(AsyncMethodCallback resultHandler) throws TException;

    public void getSupervisorWorkers(String host, AsyncMethodCallback resultHandler) throws TException;

    public void getTopologyInfo(String id, AsyncMethodCallback resultHandler) throws TException;

    public void getTopologyInfoByName(String topologyName, AsyncMethodCallback resultHandler) throws TException;

    public void getTopology(String id, AsyncMethodCallback resultHandler) throws TException;

    public void getUserTopology(String id, AsyncMethodCallback resultHandler) throws TException;

    public void uploadTopologyMetrics(String topologyId, TopologyMetric topologyMetrics, AsyncMethodCallback resultHandler) throws TException;

    public void registerMetrics(String topologyId, Set<String> metrics, AsyncMethodCallback resultHandler) throws TException;

    public void getTopologyMetrics(String topologyId, AsyncMethodCallback resultHandler) throws TException;

    public void getMetrics(String topologyId, int type, AsyncMethodCallback resultHandler) throws TException;

    public void getNettyMetrics(String topologyId, AsyncMethodCallback resultHandler) throws TException;

    public void getNettyMetricsByHost(String topologyId, String host, AsyncMethodCallback resultHandler) throws TException;

    public void getPagingNettyMetrics(String topologyId, String host, int page, AsyncMethodCallback resultHandler) throws TException;

    public void getNettyMetricSizeByHost(String topologyId, String host, AsyncMethodCallback resultHandler) throws TException;

    public void getTaskMetrics(String topologyId, String component, AsyncMethodCallback resultHandler) throws TException;

    public void getTaskAndStreamMetrics(String topologyId, int taskId, AsyncMethodCallback resultHandler) throws TException;

    public void getSummarizedTopologyMetrics(String topologyId, AsyncMethodCallback resultHandler) throws TException;

    public void getVersion(AsyncMethodCallback resultHandler) throws TException;

    public void updateTopology(String name, String uploadedLocation, String updateConf, AsyncMethodCallback resultHandler) throws TException;

    public void updateTaskHeartbeat(TopologyTaskHbInfo taskHbs, AsyncMethodCallback resultHandler) throws TException;

  }

  public static class Client extends org.apache.thrift.TServiceClient implements Iface {
    public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
      public Factory() {}
      public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
        return new Client(prot);
      }
      public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
        return new Client(iprot, oprot);
      }
    }

    public Client(org.apache.thrift.protocol.TProtocol prot)
    {
      super(prot, prot);
    }

    public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
      super(iprot, oprot);
    }

    public void submitTopology(String name, String uploadedJarLocation, String jsonConf, StormTopology topology) throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException
    {
      send_submitTopology(name, uploadedJarLocation, jsonConf, topology);
      recv_submitTopology();
    }

    public void send_submitTopology(String name, String uploadedJarLocation, String jsonConf, StormTopology topology) throws TException
    {
      submitTopology_args args = new submitTopology_args();
      args.set_name(name);
      args.set_uploadedJarLocation(uploadedJarLocation);
      args.set_jsonConf(jsonConf);
      args.set_topology(topology);
      sendBase("submitTopology", args);
    }

    public void recv_submitTopology() throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException
    {
      submitTopology_result result = new submitTopology_result();
      receiveBase(result, "submitTopology");
      if (result.e != null) {
        throw result.e;
      }
      if (result.ite != null) {
        throw result.ite;
      }
      if (result.tae != null) {
        throw result.tae;
      }
      return;
    }

    public void submitTopologyWithOpts(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, SubmitOptions options) throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException
    {
      send_submitTopologyWithOpts(name, uploadedJarLocation, jsonConf, topology, options);
      recv_submitTopologyWithOpts();
    }

    public void send_submitTopologyWithOpts(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, SubmitOptions options) throws TException
    {
      submitTopologyWithOpts_args args = new submitTopologyWithOpts_args();
      args.set_name(name);
      args.set_uploadedJarLocation(uploadedJarLocation);
      args.set_jsonConf(jsonConf);
      args.set_topology(topology);
      args.set_options(options);
      sendBase("submitTopologyWithOpts", args);
    }

    public void recv_submitTopologyWithOpts() throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException
    {
      submitTopologyWithOpts_result result = new submitTopologyWithOpts_result();
      receiveBase(result, "submitTopologyWithOpts");
      if (result.e != null) {
        throw result.e;
      }
      if (result.ite != null) {
        throw result.ite;
      }
      if (result.tae != null) {
        throw result.tae;
      }
      return;
    }

    public void killTopology(String name) throws NotAliveException, TException
    {
      send_killTopology(name);
      recv_killTopology();
    }

    public void send_killTopology(String name) throws TException
    {
      killTopology_args args = new killTopology_args();
      args.set_name(name);
      sendBase("killTopology", args);
    }

    public void recv_killTopology() throws NotAliveException, TException
    {
      killTopology_result result = new killTopology_result();
      receiveBase(result, "killTopology");
      if (result.e != null) {
        throw result.e;
      }
      return;
    }

    public void killTopologyWithOpts(String name, KillOptions options) throws NotAliveException, TException
    {
      send_killTopologyWithOpts(name, options);
      recv_killTopologyWithOpts();
    }

    public void send_killTopologyWithOpts(String name, KillOptions options) throws TException
    {
      killTopologyWithOpts_args args = new killTopologyWithOpts_args();
      args.set_name(name);
      args.set_options(options);
      sendBase("killTopologyWithOpts", args);
    }

    public void recv_killTopologyWithOpts() throws NotAliveException, TException
    {
      killTopologyWithOpts_result result = new killTopologyWithOpts_result();
      receiveBase(result, "killTopologyWithOpts");
      if (result.e != null) {
        throw result.e;
      }
      return;
    }

    public void activate(String name) throws NotAliveException, TException
    {
      send_activate(name);
      recv_activate();
    }

    public void send_activate(String name) throws TException
    {
      activate_args args = new activate_args();
      args.set_name(name);
      sendBase("activate", args);
    }

    public void recv_activate() throws NotAliveException, TException
    {
      activate_result result = new activate_result();
      receiveBase(result, "activate");
      if (result.e != null) {
        throw result.e;
      }
      return;
    }

    public void deactivate(String name) throws NotAliveException, TException
    {
      send_deactivate(name);
      recv_deactivate();
    }

    public void send_deactivate(String name) throws TException
    {
      deactivate_args args = new deactivate_args();
      args.set_name(name);
      sendBase("deactivate", args);
    }

    public void recv_deactivate() throws NotAliveException, TException
    {
      deactivate_result result = new deactivate_result();
      receiveBase(result, "deactivate");
      if (result.e != null) {
        throw result.e;
      }
      return;
    }

    public void rebalance(String name, RebalanceOptions options) throws NotAliveException, InvalidTopologyException, TException
    {
      send_rebalance(name, options);
      recv_rebalance();
    }

    public void send_rebalance(String name, RebalanceOptions options) throws TException
    {
      rebalance_args args = new rebalance_args();
      args.set_name(name);
      args.set_options(options);
      sendBase("rebalance", args);
    }

    public void recv_rebalance() throws NotAliveException, InvalidTopologyException, TException
    {
      rebalance_result result = new rebalance_result();
      receiveBase(result, "rebalance");
      if (result.e != null) {
        throw result.e;
      }
      if (result.ite != null) {
        throw result.ite;
      }
      return;
    }

    public void metricMonitor(String name, MonitorOptions options) throws NotAliveException, TException
    {
      send_metricMonitor(name, options);
      recv_metricMonitor();
    }

    public void send_metricMonitor(String name, MonitorOptions options) throws TException
    {
      metricMonitor_args args = new metricMonitor_args();
      args.set_name(name);
      args.set_options(options);
      sendBase("metricMonitor", args);
    }

    public void recv_metricMonitor() throws NotAliveException, TException
    {
      metricMonitor_result result = new metricMonitor_result();
      receiveBase(result, "metricMonitor");
      if (result.e != null) {
        throw result.e;
      }
      return;
    }

    public void restart(String name, String jsonConf) throws NotAliveException, InvalidTopologyException, TopologyAssignException, TException
    {
      send_restart(name, jsonConf);
      recv_restart();
    }

    public void send_restart(String name, String jsonConf) throws TException
    {
      restart_args args = new restart_args();
      args.set_name(name);
      args.set_jsonConf(jsonConf);
      sendBase("restart", args);
    }

    public void recv_restart() throws NotAliveException, InvalidTopologyException, TopologyAssignException, TException
    {
      restart_result result = new restart_result();
      receiveBase(result, "restart");
      if (result.e != null) {
        throw result.e;
      }
      if (result.ite != null) {
        throw result.ite;
      }
      if (result.tae != null) {
        throw result.tae;
      }
      return;
    }

    public void beginLibUpload(String libName) throws TException
    {
      send_beginLibUpload(libName);
      recv_beginLibUpload();
    }

    public void send_beginLibUpload(String libName) throws TException
    {
      beginLibUpload_args args = new beginLibUpload_args();
      args.set_libName(libName);
      sendBase("beginLibUpload", args);
    }

    public void recv_beginLibUpload() throws TException
    {
      beginLibUpload_result result = new beginLibUpload_result();
      receiveBase(result, "beginLibUpload");
      return;
    }

    public String beginFileUpload() throws TException
    {
      send_beginFileUpload();
      return recv_beginFileUpload();
    }

    public void send_beginFileUpload() throws TException
    {
      beginFileUpload_args args = new beginFileUpload_args();
      sendBase("beginFileUpload", args);
    }

    public String recv_beginFileUpload() throws TException
    {
      beginFileUpload_result result = new beginFileUpload_result();
      receiveBase(result, "beginFileUpload");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "beginFileUpload failed: unknown result");
    }

    public void uploadChunk(String location, ByteBuffer chunk) throws TException
    {
      send_uploadChunk(location, chunk);
      recv_uploadChunk();
    }

    public void send_uploadChunk(String location, ByteBuffer chunk) throws TException
    {
      uploadChunk_args args = new uploadChunk_args();
      args.set_location(location);
      args.set_chunk(chunk);
      sendBase("uploadChunk", args);
    }

    public void recv_uploadChunk() throws TException
    {
      uploadChunk_result result = new uploadChunk_result();
      receiveBase(result, "uploadChunk");
      return;
    }

    public void finishFileUpload(String location) throws TException
    {
      send_finishFileUpload(location);
      recv_finishFileUpload();
    }

    public void send_finishFileUpload(String location) throws TException
    {
      finishFileUpload_args args = new finishFileUpload_args();
      args.set_location(location);
      sendBase("finishFileUpload", args);
    }

    public void recv_finishFileUpload() throws TException
    {
      finishFileUpload_result result = new finishFileUpload_result();
      receiveBase(result, "finishFileUpload");
      return;
    }

    public String beginFileDownload(String file) throws TException
    {
      send_beginFileDownload(file);
      return recv_beginFileDownload();
    }

    public void send_beginFileDownload(String file) throws TException
    {
      beginFileDownload_args args = new beginFileDownload_args();
      args.set_file(file);
      sendBase("beginFileDownload", args);
    }

    public String recv_beginFileDownload() throws TException
    {
      beginFileDownload_result result = new beginFileDownload_result();
      receiveBase(result, "beginFileDownload");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "beginFileDownload failed: unknown result");
    }

    public ByteBuffer downloadChunk(String id) throws TException
    {
      send_downloadChunk(id);
      return recv_downloadChunk();
    }

    public void send_downloadChunk(String id) throws TException
    {
      downloadChunk_args args = new downloadChunk_args();
      args.set_id(id);
      sendBase("downloadChunk", args);
    }

    public ByteBuffer recv_downloadChunk() throws TException
    {
      downloadChunk_result result = new downloadChunk_result();
      receiveBase(result, "downloadChunk");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "downloadChunk failed: unknown result");
    }

    public void finishFileDownload(String id) throws TException
    {
      send_finishFileDownload(id);
      recv_finishFileDownload();
    }

    public void send_finishFileDownload(String id) throws TException
    {
      finishFileDownload_args args = new finishFileDownload_args();
      args.set_id(id);
      sendBase("finishFileDownload", args);
    }

    public void recv_finishFileDownload() throws TException
    {
      finishFileDownload_result result = new finishFileDownload_result();
      receiveBase(result, "finishFileDownload");
      return;
    }

    public String getNimbusConf() throws TException
    {
      send_getNimbusConf();
      return recv_getNimbusConf();
    }

    public void send_getNimbusConf() throws TException
    {
      getNimbusConf_args args = new getNimbusConf_args();
      sendBase("getNimbusConf", args);
    }

    public String recv_getNimbusConf() throws TException
    {
      getNimbusConf_result result = new getNimbusConf_result();
      receiveBase(result, "getNimbusConf");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getNimbusConf failed: unknown result");
    }

    public String getTopologyConf(String id) throws NotAliveException, TException
    {
      send_getTopologyConf(id);
      return recv_getTopologyConf();
    }

    public void send_getTopologyConf(String id) throws TException
    {
      getTopologyConf_args args = new getTopologyConf_args();
      args.set_id(id);
      sendBase("getTopologyConf", args);
    }

    public String recv_getTopologyConf() throws NotAliveException, TException
    {
      getTopologyConf_result result = new getTopologyConf_result();
      receiveBase(result, "getTopologyConf");
      if (result.is_set_success()) {
        return result.success;
      }
      if (result.e != null) {
        throw result.e;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTopologyConf failed: unknown result");
    }

    public String getTopologyId(String topologyName) throws NotAliveException, TException
    {
      send_getTopologyId(topologyName);
      return recv_getTopologyId();
    }

    public void send_getTopologyId(String topologyName) throws TException
    {
      getTopologyId_args args = new getTopologyId_args();
      args.set_topologyName(topologyName);
      sendBase("getTopologyId", args);
    }

    public String recv_getTopologyId() throws NotAliveException, TException
    {
      getTopologyId_result result = new getTopologyId_result();
      receiveBase(result, "getTopologyId");
      if (result.is_set_success()) {
        return result.success;
      }
      if (result.e != null) {
        throw result.e;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTopologyId failed: unknown result");
    }

    public ClusterSummary getClusterInfo() throws TException
    {
      send_getClusterInfo();
      return recv_getClusterInfo();
    }

    public void send_getClusterInfo() throws TException
    {
      getClusterInfo_args args = new getClusterInfo_args();
      sendBase("getClusterInfo", args);
    }

    public ClusterSummary recv_getClusterInfo() throws TException
    {
      getClusterInfo_result result = new getClusterInfo_result();
      receiveBase(result, "getClusterInfo");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getClusterInfo failed: unknown result");
    }

    public SupervisorWorkers getSupervisorWorkers(String host) throws NotAliveException, TException
    {
      send_getSupervisorWorkers(host);
      return recv_getSupervisorWorkers();
    }

    public void send_getSupervisorWorkers(String host) throws TException
    {
      getSupervisorWorkers_args args = new getSupervisorWorkers_args();
      args.set_host(host);
      sendBase("getSupervisorWorkers", args);
    }

    public SupervisorWorkers recv_getSupervisorWorkers() throws NotAliveException, TException
    {
      getSupervisorWorkers_result result = new getSupervisorWorkers_result();
      receiveBase(result, "getSupervisorWorkers");
      if (result.is_set_success()) {
        return result.success;
      }
      if (result.e != null) {
        throw result.e;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getSupervisorWorkers failed: unknown result");
    }

    public TopologyInfo getTopologyInfo(String id) throws NotAliveException, TException
    {
      send_getTopologyInfo(id);
      return recv_getTopologyInfo();
    }

    public void send_getTopologyInfo(String id) throws TException
    {
      getTopologyInfo_args args = new getTopologyInfo_args();
      args.set_id(id);
      sendBase("getTopologyInfo", args);
    }

    public TopologyInfo recv_getTopologyInfo() throws NotAliveException, TException
    {
      getTopologyInfo_result result = new getTopologyInfo_result();
      receiveBase(result, "getTopologyInfo");
      if (result.is_set_success()) {
        return result.success;
      }
      if (result.e != null) {
        throw result.e;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTopologyInfo failed: unknown result");
    }

    public TopologyInfo getTopologyInfoByName(String topologyName) throws NotAliveException, TException
    {
      send_getTopologyInfoByName(topologyName);
      return recv_getTopologyInfoByName();
    }

    public void send_getTopologyInfoByName(String topologyName) throws TException
    {
      getTopologyInfoByName_args args = new getTopologyInfoByName_args();
      args.set_topologyName(topologyName);
      sendBase("getTopologyInfoByName", args);
    }

    public TopologyInfo recv_getTopologyInfoByName() throws NotAliveException, TException
    {
      getTopologyInfoByName_result result = new getTopologyInfoByName_result();
      receiveBase(result, "getTopologyInfoByName");
      if (result.is_set_success()) {
        return result.success;
      }
      if (result.e != null) {
        throw result.e;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTopologyInfoByName failed: unknown result");
    }

    public StormTopology getTopology(String id) throws NotAliveException, TException
    {
      send_getTopology(id);
      return recv_getTopology();
    }

    public void send_getTopology(String id) throws TException
    {
      getTopology_args args = new getTopology_args();
      args.set_id(id);
      sendBase("getTopology", args);
    }

    public StormTopology recv_getTopology() throws NotAliveException, TException
    {
      getTopology_result result = new getTopology_result();
      receiveBase(result, "getTopology");
      if (result.is_set_success()) {
        return result.success;
      }
      if (result.e != null) {
        throw result.e;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTopology failed: unknown result");
    }

    public StormTopology getUserTopology(String id) throws NotAliveException, TException
    {
      send_getUserTopology(id);
      return recv_getUserTopology();
    }

    public void send_getUserTopology(String id) throws TException
    {
      getUserTopology_args args = new getUserTopology_args();
      args.set_id(id);
      sendBase("getUserTopology", args);
    }

    public StormTopology recv_getUserTopology() throws NotAliveException, TException
    {
      getUserTopology_result result = new getUserTopology_result();
      receiveBase(result, "getUserTopology");
      if (result.is_set_success()) {
        return result.success;
      }
      if (result.e != null) {
        throw result.e;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getUserTopology failed: unknown result");
    }

    public void uploadTopologyMetrics(String topologyId, TopologyMetric topologyMetrics) throws TException
    {
      send_uploadTopologyMetrics(topologyId, topologyMetrics);
      recv_uploadTopologyMetrics();
    }

    public void send_uploadTopologyMetrics(String topologyId, TopologyMetric topologyMetrics) throws TException
    {
      uploadTopologyMetrics_args args = new uploadTopologyMetrics_args();
      args.set_topologyId(topologyId);
      args.set_topologyMetrics(topologyMetrics);
      sendBase("uploadTopologyMetrics", args);
    }

    public void recv_uploadTopologyMetrics() throws TException
    {
      uploadTopologyMetrics_result result = new uploadTopologyMetrics_result();
      receiveBase(result, "uploadTopologyMetrics");
      return;
    }

    public Map<String,Long> registerMetrics(String topologyId, Set<String> metrics) throws TException
    {
      send_registerMetrics(topologyId, metrics);
      return recv_registerMetrics();
    }

    public void send_registerMetrics(String topologyId, Set<String> metrics) throws TException
    {
      registerMetrics_args args = new registerMetrics_args();
      args.set_topologyId(topologyId);
      args.set_metrics(metrics);
      sendBase("registerMetrics", args);
    }

    public Map<String,Long> recv_registerMetrics() throws TException
    {
      registerMetrics_result result = new registerMetrics_result();
      receiveBase(result, "registerMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "registerMetrics failed: unknown result");
    }

    public TopologyMetric getTopologyMetrics(String topologyId) throws TException
    {
      send_getTopologyMetrics(topologyId);
      return recv_getTopologyMetrics();
    }

    public void send_getTopologyMetrics(String topologyId) throws TException
    {
      getTopologyMetrics_args args = new getTopologyMetrics_args();
      args.set_topologyId(topologyId);
      sendBase("getTopologyMetrics", args);
    }

    public TopologyMetric recv_getTopologyMetrics() throws TException
    {
      getTopologyMetrics_result result = new getTopologyMetrics_result();
      receiveBase(result, "getTopologyMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTopologyMetrics failed: unknown result");
    }

    public List<MetricInfo> getMetrics(String topologyId, int type) throws TException
    {
      send_getMetrics(topologyId, type);
      return recv_getMetrics();
    }

    public void send_getMetrics(String topologyId, int type) throws TException
    {
      getMetrics_args args = new getMetrics_args();
      args.set_topologyId(topologyId);
      args.set_type(type);
      sendBase("getMetrics", args);
    }

    public List<MetricInfo> recv_getMetrics() throws TException
    {
      getMetrics_result result = new getMetrics_result();
      receiveBase(result, "getMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getMetrics failed: unknown result");
    }

    public MetricInfo getNettyMetrics(String topologyId) throws TException
    {
      send_getNettyMetrics(topologyId);
      return recv_getNettyMetrics();
    }

    public void send_getNettyMetrics(String topologyId) throws TException
    {
      getNettyMetrics_args args = new getNettyMetrics_args();
      args.set_topologyId(topologyId);
      sendBase("getNettyMetrics", args);
    }

    public MetricInfo recv_getNettyMetrics() throws TException
    {
      getNettyMetrics_result result = new getNettyMetrics_result();
      receiveBase(result, "getNettyMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getNettyMetrics failed: unknown result");
    }

    public MetricInfo getNettyMetricsByHost(String topologyId, String host) throws TException
    {
      send_getNettyMetricsByHost(topologyId, host);
      return recv_getNettyMetricsByHost();
    }

    public void send_getNettyMetricsByHost(String topologyId, String host) throws TException
    {
      getNettyMetricsByHost_args args = new getNettyMetricsByHost_args();
      args.set_topologyId(topologyId);
      args.set_host(host);
      sendBase("getNettyMetricsByHost", args);
    }

    public MetricInfo recv_getNettyMetricsByHost() throws TException
    {
      getNettyMetricsByHost_result result = new getNettyMetricsByHost_result();
      receiveBase(result, "getNettyMetricsByHost");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getNettyMetricsByHost failed: unknown result");
    }

    public MetricInfo getPagingNettyMetrics(String topologyId, String host, int page) throws TException
    {
      send_getPagingNettyMetrics(topologyId, host, page);
      return recv_getPagingNettyMetrics();
    }

    public void send_getPagingNettyMetrics(String topologyId, String host, int page) throws TException
    {
      getPagingNettyMetrics_args args = new getPagingNettyMetrics_args();
      args.set_topologyId(topologyId);
      args.set_host(host);
      args.set_page(page);
      sendBase("getPagingNettyMetrics", args);
    }

    public MetricInfo recv_getPagingNettyMetrics() throws TException
    {
      getPagingNettyMetrics_result result = new getPagingNettyMetrics_result();
      receiveBase(result, "getPagingNettyMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getPagingNettyMetrics failed: unknown result");
    }

    public int getNettyMetricSizeByHost(String topologyId, String host) throws TException
    {
      send_getNettyMetricSizeByHost(topologyId, host);
      return recv_getNettyMetricSizeByHost();
    }

    public void send_getNettyMetricSizeByHost(String topologyId, String host) throws TException
    {
      getNettyMetricSizeByHost_args args = new getNettyMetricSizeByHost_args();
      args.set_topologyId(topologyId);
      args.set_host(host);
      sendBase("getNettyMetricSizeByHost", args);
    }

    public int recv_getNettyMetricSizeByHost() throws TException
    {
      getNettyMetricSizeByHost_result result = new getNettyMetricSizeByHost_result();
      receiveBase(result, "getNettyMetricSizeByHost");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getNettyMetricSizeByHost failed: unknown result");
    }

    public MetricInfo getTaskMetrics(String topologyId, String component) throws TException
    {
      send_getTaskMetrics(topologyId, component);
      return recv_getTaskMetrics();
    }

    public void send_getTaskMetrics(String topologyId, String component) throws TException
    {
      getTaskMetrics_args args = new getTaskMetrics_args();
      args.set_topologyId(topologyId);
      args.set_component(component);
      sendBase("getTaskMetrics", args);
    }

    public MetricInfo recv_getTaskMetrics() throws TException
    {
      getTaskMetrics_result result = new getTaskMetrics_result();
      receiveBase(result, "getTaskMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTaskMetrics failed: unknown result");
    }

    public List<MetricInfo> getTaskAndStreamMetrics(String topologyId, int taskId) throws TException
    {
      send_getTaskAndStreamMetrics(topologyId, taskId);
      return recv_getTaskAndStreamMetrics();
    }

    public void send_getTaskAndStreamMetrics(String topologyId, int taskId) throws TException
    {
      getTaskAndStreamMetrics_args args = new getTaskAndStreamMetrics_args();
      args.set_topologyId(topologyId);
      args.set_taskId(taskId);
      sendBase("getTaskAndStreamMetrics", args);
    }

    public List<MetricInfo> recv_getTaskAndStreamMetrics() throws TException
    {
      getTaskAndStreamMetrics_result result = new getTaskAndStreamMetrics_result();
      receiveBase(result, "getTaskAndStreamMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getTaskAndStreamMetrics failed: unknown result");
    }

    public List<MetricInfo> getSummarizedTopologyMetrics(String topologyId) throws TException
    {
      send_getSummarizedTopologyMetrics(topologyId);
      return recv_getSummarizedTopologyMetrics();
    }

    public void send_getSummarizedTopologyMetrics(String topologyId) throws TException
    {
      getSummarizedTopologyMetrics_args args = new getSummarizedTopologyMetrics_args();
      args.set_topologyId(topologyId);
      sendBase("getSummarizedTopologyMetrics", args);
    }

    public List<MetricInfo> recv_getSummarizedTopologyMetrics() throws TException
    {
      getSummarizedTopologyMetrics_result result = new getSummarizedTopologyMetrics_result();
      receiveBase(result, "getSummarizedTopologyMetrics");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getSummarizedTopologyMetrics failed: unknown result");
    }

    public String getVersion() throws TException
    {
      send_getVersion();
      return recv_getVersion();
    }

    public void send_getVersion() throws TException
    {
      getVersion_args args = new getVersion_args();
      sendBase("getVersion", args);
    }

    public String recv_getVersion() throws TException
    {
      getVersion_result result = new getVersion_result();
      receiveBase(result, "getVersion");
      if (result.is_set_success()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getVersion failed: unknown result");
    }

    public void updateTopology(String name, String uploadedLocation, String updateConf) throws NotAliveException, InvalidTopologyException, TException
    {
      send_updateTopology(name, uploadedLocation, updateConf);
      recv_updateTopology();
    }

    public void send_updateTopology(String name, String uploadedLocation, String updateConf) throws TException
    {
      updateTopology_args args = new updateTopology_args();
      args.set_name(name);
      args.set_uploadedLocation(uploadedLocation);
      args.set_updateConf(updateConf);
      sendBase("updateTopology", args);
    }

    public void recv_updateTopology() throws NotAliveException, InvalidTopologyException, TException
    {
      updateTopology_result result = new updateTopology_result();
      receiveBase(result, "updateTopology");
      if (result.e != null) {
        throw result.e;
      }
      if (result.ite != null) {
        throw result.ite;
      }
      return;
    }

    public void updateTaskHeartbeat(TopologyTaskHbInfo taskHbs) throws TException
    {
      send_updateTaskHeartbeat(taskHbs);
      recv_updateTaskHeartbeat();
    }

    public void send_updateTaskHeartbeat(TopologyTaskHbInfo taskHbs) throws TException
    {
      updateTaskHeartbeat_args args = new updateTaskHeartbeat_args();
      args.set_taskHbs(taskHbs);
      sendBase("updateTaskHeartbeat", args);
    }

    public void recv_updateTaskHeartbeat() throws TException
    {
      updateTaskHeartbeat_result result = new updateTaskHeartbeat_result();
      receiveBase(result, "updateTaskHeartbeat");
      return;
    }

  }
  public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
    public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
      private org.apache.thrift.async.TAsyncClientManager clientManager;
      private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
      public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
        this.clientManager = clientManager;
        this.protocolFactory = protocolFactory;
      }
      public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
        return new AsyncClient(protocolFactory, clientManager, transport);
      }
    }

    public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
      super(protocolFactory, clientManager, transport);
    }

    public void submitTopology(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      submitTopology_call method_call = new submitTopology_call(name, uploadedJarLocation, jsonConf, topology, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class submitTopology_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      private String uploadedJarLocation;
      private String jsonConf;
      private StormTopology topology;
      public submitTopology_call(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
        this.uploadedJarLocation = uploadedJarLocation;
        this.jsonConf = jsonConf;
        this.topology = topology;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("submitTopology", org.apache.thrift.protocol.TMessageType.CALL, 0));
        submitTopology_args args = new submitTopology_args();
        args.set_name(name);
        args.set_uploadedJarLocation(uploadedJarLocation);
        args.set_jsonConf(jsonConf);
        args.set_topology(topology);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_submitTopology();
      }
    }

    public void submitTopologyWithOpts(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, SubmitOptions options, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      submitTopologyWithOpts_call method_call = new submitTopologyWithOpts_call(name, uploadedJarLocation, jsonConf, topology, options, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class submitTopologyWithOpts_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      private String uploadedJarLocation;
      private String jsonConf;
      private StormTopology topology;
      private SubmitOptions options;
      public submitTopologyWithOpts_call(String name, String uploadedJarLocation, String jsonConf, StormTopology topology, SubmitOptions options, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
        this.uploadedJarLocation = uploadedJarLocation;
        this.jsonConf = jsonConf;
        this.topology = topology;
        this.options = options;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("submitTopologyWithOpts", org.apache.thrift.protocol.TMessageType.CALL, 0));
        submitTopologyWithOpts_args args = new submitTopologyWithOpts_args();
        args.set_name(name);
        args.set_uploadedJarLocation(uploadedJarLocation);
        args.set_jsonConf(jsonConf);
        args.set_topology(topology);
        args.set_options(options);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws AlreadyAliveException, InvalidTopologyException, TopologyAssignException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_submitTopologyWithOpts();
      }
    }

    public void killTopology(String name, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      killTopology_call method_call = new killTopology_call(name, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class killTopology_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      public killTopology_call(String name, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("killTopology", org.apache.thrift.protocol.TMessageType.CALL, 0));
        killTopology_args args = new killTopology_args();
        args.set_name(name);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_killTopology();
      }
    }

    public void killTopologyWithOpts(String name, KillOptions options, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      killTopologyWithOpts_call method_call = new killTopologyWithOpts_call(name, options, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class killTopologyWithOpts_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      private KillOptions options;
      public killTopologyWithOpts_call(String name, KillOptions options, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
        this.options = options;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("killTopologyWithOpts", org.apache.thrift.protocol.TMessageType.CALL, 0));
        killTopologyWithOpts_args args = new killTopologyWithOpts_args();
        args.set_name(name);
        args.set_options(options);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_killTopologyWithOpts();
      }
    }

    public void activate(String name, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      activate_call method_call = new activate_call(name, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class activate_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      public activate_call(String name, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("activate", org.apache.thrift.protocol.TMessageType.CALL, 0));
        activate_args args = new activate_args();
        args.set_name(name);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_activate();
      }
    }

    public void deactivate(String name, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      deactivate_call method_call = new deactivate_call(name, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class deactivate_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      public deactivate_call(String name, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deactivate", org.apache.thrift.protocol.TMessageType.CALL, 0));
        deactivate_args args = new deactivate_args();
        args.set_name(name);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_deactivate();
      }
    }

    public void rebalance(String name, RebalanceOptions options, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      rebalance_call method_call = new rebalance_call(name, options, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class rebalance_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      private RebalanceOptions options;
      public rebalance_call(String name, RebalanceOptions options, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
        this.options = options;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("rebalance", org.apache.thrift.protocol.TMessageType.CALL, 0));
        rebalance_args args = new rebalance_args();
        args.set_name(name);
        args.set_options(options);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, InvalidTopologyException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_rebalance();
      }
    }

    public void metricMonitor(String name, MonitorOptions options, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      metricMonitor_call method_call = new metricMonitor_call(name, options, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class metricMonitor_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      private MonitorOptions options;
      public metricMonitor_call(String name, MonitorOptions options, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
        this.options = options;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("metricMonitor", org.apache.thrift.protocol.TMessageType.CALL, 0));
        metricMonitor_args args = new metricMonitor_args();
        args.set_name(name);
        args.set_options(options);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_metricMonitor();
      }
    }

    public void restart(String name, String jsonConf, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      restart_call method_call = new restart_call(name, jsonConf, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class restart_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      private String jsonConf;
      public restart_call(String name, String jsonConf, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
        this.jsonConf = jsonConf;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("restart", org.apache.thrift.protocol.TMessageType.CALL, 0));
        restart_args args = new restart_args();
        args.set_name(name);
        args.set_jsonConf(jsonConf);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, InvalidTopologyException, TopologyAssignException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_restart();
      }
    }

    public void beginLibUpload(String libName, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      beginLibUpload_call method_call = new beginLibUpload_call(libName, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class beginLibUpload_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String libName;
      public beginLibUpload_call(String libName, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.libName = libName;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("beginLibUpload", org.apache.thrift.protocol.TMessageType.CALL, 0));
        beginLibUpload_args args = new beginLibUpload_args();
        args.set_libName(libName);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_beginLibUpload();
      }
    }

    public void beginFileUpload(AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      beginFileUpload_call method_call = new beginFileUpload_call(resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class beginFileUpload_call extends org.apache.thrift.async.TAsyncMethodCall {
      public beginFileUpload_call(AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("beginFileUpload", org.apache.thrift.protocol.TMessageType.CALL, 0));
        beginFileUpload_args args = new beginFileUpload_args();
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_beginFileUpload();
      }
    }

    public void uploadChunk(String location, ByteBuffer chunk, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      uploadChunk_call method_call = new uploadChunk_call(location, chunk, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class uploadChunk_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String location;
      private ByteBuffer chunk;
      public uploadChunk_call(String location, ByteBuffer chunk, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.location = location;
        this.chunk = chunk;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("uploadChunk", org.apache.thrift.protocol.TMessageType.CALL, 0));
        uploadChunk_args args = new uploadChunk_args();
        args.set_location(location);
        args.set_chunk(chunk);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_uploadChunk();
      }
    }

    public void finishFileUpload(String location, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      finishFileUpload_call method_call = new finishFileUpload_call(location, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class finishFileUpload_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String location;
      public finishFileUpload_call(String location, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.location = location;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("finishFileUpload", org.apache.thrift.protocol.TMessageType.CALL, 0));
        finishFileUpload_args args = new finishFileUpload_args();
        args.set_location(location);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_finishFileUpload();
      }
    }

    public void beginFileDownload(String file, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      beginFileDownload_call method_call = new beginFileDownload_call(file, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class beginFileDownload_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String file;
      public beginFileDownload_call(String file, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.file = file;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("beginFileDownload", org.apache.thrift.protocol.TMessageType.CALL, 0));
        beginFileDownload_args args = new beginFileDownload_args();
        args.set_file(file);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_beginFileDownload();
      }
    }

    public void downloadChunk(String id, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      downloadChunk_call method_call = new downloadChunk_call(id, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class downloadChunk_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String id;
      public downloadChunk_call(String id, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.id = id;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("downloadChunk", org.apache.thrift.protocol.TMessageType.CALL, 0));
        downloadChunk_args args = new downloadChunk_args();
        args.set_id(id);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public ByteBuffer getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_downloadChunk();
      }
    }

    public void finishFileDownload(String id, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      finishFileDownload_call method_call = new finishFileDownload_call(id, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class finishFileDownload_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String id;
      public finishFileDownload_call(String id, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.id = id;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("finishFileDownload", org.apache.thrift.protocol.TMessageType.CALL, 0));
        finishFileDownload_args args = new finishFileDownload_args();
        args.set_id(id);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_finishFileDownload();
      }
    }

    public void getNimbusConf(AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getNimbusConf_call method_call = new getNimbusConf_call(resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getNimbusConf_call extends org.apache.thrift.async.TAsyncMethodCall {
      public getNimbusConf_call(AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getNimbusConf", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getNimbusConf_args args = new getNimbusConf_args();
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getNimbusConf();
      }
    }

    public void getTopologyConf(String id, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTopologyConf_call method_call = new getTopologyConf_call(id, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTopologyConf_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String id;
      public getTopologyConf_call(String id, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.id = id;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTopologyConf", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTopologyConf_args args = new getTopologyConf_args();
        args.set_id(id);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTopologyConf();
      }
    }

    public void getTopologyId(String topologyName, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTopologyId_call method_call = new getTopologyId_call(topologyName, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTopologyId_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyName;
      public getTopologyId_call(String topologyName, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyName = topologyName;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTopologyId", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTopologyId_args args = new getTopologyId_args();
        args.set_topologyName(topologyName);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTopologyId();
      }
    }

    public void getClusterInfo(AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getClusterInfo_call method_call = new getClusterInfo_call(resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getClusterInfo_call extends org.apache.thrift.async.TAsyncMethodCall {
      public getClusterInfo_call(AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getClusterInfo", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getClusterInfo_args args = new getClusterInfo_args();
        args.write(prot);
        prot.writeMessageEnd();
      }

      public ClusterSummary getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getClusterInfo();
      }
    }

    public void getSupervisorWorkers(String host, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getSupervisorWorkers_call method_call = new getSupervisorWorkers_call(host, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getSupervisorWorkers_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String host;
      public getSupervisorWorkers_call(String host, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.host = host;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getSupervisorWorkers", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getSupervisorWorkers_args args = new getSupervisorWorkers_args();
        args.set_host(host);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public SupervisorWorkers getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getSupervisorWorkers();
      }
    }

    public void getTopologyInfo(String id, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTopologyInfo_call method_call = new getTopologyInfo_call(id, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTopologyInfo_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String id;
      public getTopologyInfo_call(String id, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.id = id;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTopologyInfo", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTopologyInfo_args args = new getTopologyInfo_args();
        args.set_id(id);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public TopologyInfo getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTopologyInfo();
      }
    }

    public void getTopologyInfoByName(String topologyName, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTopologyInfoByName_call method_call = new getTopologyInfoByName_call(topologyName, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTopologyInfoByName_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyName;
      public getTopologyInfoByName_call(String topologyName, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyName = topologyName;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTopologyInfoByName", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTopologyInfoByName_args args = new getTopologyInfoByName_args();
        args.set_topologyName(topologyName);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public TopologyInfo getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTopologyInfoByName();
      }
    }

    public void getTopology(String id, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTopology_call method_call = new getTopology_call(id, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTopology_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String id;
      public getTopology_call(String id, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.id = id;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTopology", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTopology_args args = new getTopology_args();
        args.set_id(id);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public StormTopology getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTopology();
      }
    }

    public void getUserTopology(String id, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getUserTopology_call method_call = new getUserTopology_call(id, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getUserTopology_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String id;
      public getUserTopology_call(String id, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.id = id;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getUserTopology", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getUserTopology_args args = new getUserTopology_args();
        args.set_id(id);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public StormTopology getResult() throws NotAliveException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getUserTopology();
      }
    }

    public void uploadTopologyMetrics(String topologyId, TopologyMetric topologyMetrics, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      uploadTopologyMetrics_call method_call = new uploadTopologyMetrics_call(topologyId, topologyMetrics, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class uploadTopologyMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private TopologyMetric topologyMetrics;
      public uploadTopologyMetrics_call(String topologyId, TopologyMetric topologyMetrics, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.topologyMetrics = topologyMetrics;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("uploadTopologyMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        uploadTopologyMetrics_args args = new uploadTopologyMetrics_args();
        args.set_topologyId(topologyId);
        args.set_topologyMetrics(topologyMetrics);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_uploadTopologyMetrics();
      }
    }

    public void registerMetrics(String topologyId, Set<String> metrics, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      registerMetrics_call method_call = new registerMetrics_call(topologyId, metrics, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class registerMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private Set<String> metrics;
      public registerMetrics_call(String topologyId, Set<String> metrics, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.metrics = metrics;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("registerMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        registerMetrics_args args = new registerMetrics_args();
        args.set_topologyId(topologyId);
        args.set_metrics(metrics);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public Map<String,Long> getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_registerMetrics();
      }
    }

    public void getTopologyMetrics(String topologyId, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTopologyMetrics_call method_call = new getTopologyMetrics_call(topologyId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTopologyMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      public getTopologyMetrics_call(String topologyId, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTopologyMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTopologyMetrics_args args = new getTopologyMetrics_args();
        args.set_topologyId(topologyId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public TopologyMetric getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTopologyMetrics();
      }
    }

    public void getMetrics(String topologyId, int type, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getMetrics_call method_call = new getMetrics_call(topologyId, type, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private int type;
      public getMetrics_call(String topologyId, int type, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.type = type;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getMetrics_args args = new getMetrics_args();
        args.set_topologyId(topologyId);
        args.set_type(type);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<MetricInfo> getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getMetrics();
      }
    }

    public void getNettyMetrics(String topologyId, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getNettyMetrics_call method_call = new getNettyMetrics_call(topologyId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getNettyMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      public getNettyMetrics_call(String topologyId, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getNettyMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getNettyMetrics_args args = new getNettyMetrics_args();
        args.set_topologyId(topologyId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public MetricInfo getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getNettyMetrics();
      }
    }

    public void getNettyMetricsByHost(String topologyId, String host, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getNettyMetricsByHost_call method_call = new getNettyMetricsByHost_call(topologyId, host, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getNettyMetricsByHost_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private String host;
      public getNettyMetricsByHost_call(String topologyId, String host, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.host = host;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getNettyMetricsByHost", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getNettyMetricsByHost_args args = new getNettyMetricsByHost_args();
        args.set_topologyId(topologyId);
        args.set_host(host);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public MetricInfo getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getNettyMetricsByHost();
      }
    }

    public void getPagingNettyMetrics(String topologyId, String host, int page, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getPagingNettyMetrics_call method_call = new getPagingNettyMetrics_call(topologyId, host, page, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getPagingNettyMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private String host;
      private int page;
      public getPagingNettyMetrics_call(String topologyId, String host, int page, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.host = host;
        this.page = page;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getPagingNettyMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getPagingNettyMetrics_args args = new getPagingNettyMetrics_args();
        args.set_topologyId(topologyId);
        args.set_host(host);
        args.set_page(page);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public MetricInfo getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getPagingNettyMetrics();
      }
    }

    public void getNettyMetricSizeByHost(String topologyId, String host, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getNettyMetricSizeByHost_call method_call = new getNettyMetricSizeByHost_call(topologyId, host, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getNettyMetricSizeByHost_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private String host;
      public getNettyMetricSizeByHost_call(String topologyId, String host, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.host = host;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getNettyMetricSizeByHost", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getNettyMetricSizeByHost_args args = new getNettyMetricSizeByHost_args();
        args.set_topologyId(topologyId);
        args.set_host(host);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public int getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getNettyMetricSizeByHost();
      }
    }

    public void getTaskMetrics(String topologyId, String component, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTaskMetrics_call method_call = new getTaskMetrics_call(topologyId, component, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTaskMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private String component;
      public getTaskMetrics_call(String topologyId, String component, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.component = component;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTaskMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTaskMetrics_args args = new getTaskMetrics_args();
        args.set_topologyId(topologyId);
        args.set_component(component);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public MetricInfo getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTaskMetrics();
      }
    }

    public void getTaskAndStreamMetrics(String topologyId, int taskId, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getTaskAndStreamMetrics_call method_call = new getTaskAndStreamMetrics_call(topologyId, taskId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getTaskAndStreamMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      private int taskId;
      public getTaskAndStreamMetrics_call(String topologyId, int taskId, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
        this.taskId = taskId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getTaskAndStreamMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getTaskAndStreamMetrics_args args = new getTaskAndStreamMetrics_args();
        args.set_topologyId(topologyId);
        args.set_taskId(taskId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<MetricInfo> getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getTaskAndStreamMetrics();
      }
    }

    public void getSummarizedTopologyMetrics(String topologyId, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getSummarizedTopologyMetrics_call method_call = new getSummarizedTopologyMetrics_call(topologyId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getSummarizedTopologyMetrics_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String topologyId;
      public getSummarizedTopologyMetrics_call(String topologyId, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.topologyId = topologyId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getSummarizedTopologyMetrics", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getSummarizedTopologyMetrics_args args = new getSummarizedTopologyMetrics_args();
        args.set_topologyId(topologyId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<MetricInfo> getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getSummarizedTopologyMetrics();
      }
    }

    public void getVersion(AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      getVersion_call method_call = new getVersion_call(resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getVersion_call extends org.apache.thrift.async.TAsyncMethodCall {
      public getVersion_call(AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getVersion", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getVersion_args args = new getVersion_args();
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getVersion();
      }
    }

    public void updateTopology(String name, String uploadedLocation, String updateConf, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      updateTopology_call method_call = new updateTopology_call(name, uploadedLocation, updateConf, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updateTopology_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String name;
      private String uploadedLocation;
      private String updateConf;
      public updateTopology_call(String name, String uploadedLocation, String updateConf, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.name = name;
        this.uploadedLocation = uploadedLocation;
        this.updateConf = updateConf;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updateTopology", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updateTopology_args args = new updateTopology_args();
        args.set_name(name);
        args.set_uploadedLocation(uploadedLocation);
        args.set_updateConf(updateConf);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws NotAliveException, InvalidTopologyException, TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_updateTopology();
      }
    }

    public void updateTaskHeartbeat(TopologyTaskHbInfo taskHbs, AsyncMethodCallback resultHandler) throws TException {
      checkReady();
      updateTaskHeartbeat_call method_call = new updateTaskHeartbeat_call(taskHbs, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updateTaskHeartbeat_call extends org.apache.thrift.async.TAsyncMethodCall {
      private TopologyTaskHbInfo taskHbs;
      public updateTaskHeartbeat_call(TopologyTaskHbInfo taskHbs, AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.taskHbs = taskHbs;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updateTaskHeartbeat", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updateTaskHeartbeat_args args = new updateTaskHeartbeat_args();
        args.set_taskHbs(taskHbs);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public void getResult() throws TException {
        if (getState() != State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        (new Client(prot)).recv_updateTaskHeartbeat();
      }
    }

  }

  public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
    private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
    public Processor(I iface) {
      super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
    }

    protected Processor(I iface, Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
      super(iface, getProcessMap(processMap));
    }

    private static <I extends Iface> Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> getProcessMap(Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
      processMap.put("submitTopology", new submitTopology());
      processMap.put("submitTopologyWithOpts", new submitTopologyWithOpts());
      processMap.put("killTopology", new killTopology());
      processMap.put("killTopologyWithOpts", new killTopologyWithOpts());
      processMap.put("activate", new activate());
      processMap.put("deactivate", new deactivate());
      processMap.put("rebalance", new rebalance());
      processMap.put("metricMonitor", new metricMonitor());
      processMap.put("restart", new restart());
      processMap.put("beginLibUpload", new beginLibUpload());
      processMap.put("beginFileUpload", new beginFileUpload());
      processMap.put("uploadChunk", new uploadChunk());
      processMap.put("finishFileUpload", new finishFileUpload());
      processMap.put("beginFileDownload", new beginFileDownload());
      processMap.put("downloadChunk", new downloadChunk());
      processMap.put("finishFileDownload", new finishFileDownload());
      processMap.put("getNimbusConf", new getNimbusConf());
      processMap.put("getTopologyConf", new getTopologyConf());
      processMap.put("getTopologyId", new getTopologyId());
      processMap.put("getClusterInfo", new getClusterInfo());
      processMap.put("getSupervisorWorkers", new getSupervisorWorkers());
      processMap.put("getTopologyInfo", new getTopologyInfo());
      processMap.put("getTopologyInfoByName", new getTopologyInfoByName());
      processMap.put("getTopology", new getTopology());
      processMap.put("getUserTopology", new getUserTopology());
      processMap.put("uploadTopologyMetrics", new uploadTopologyMetrics());
      processMap.put("registerMetrics", new registerMetrics());
      processMap.put("getTopologyMetrics", new getTopologyMetrics());
      processMap.put("getMetrics", new getMetrics());
      processMap.put("getNettyMetrics", new getNettyMetrics());
      processMap.put("getNettyMetricsByHost", new getNettyMetricsByHost());
      processMap.put("getPagingNettyMetrics", new getPagingNettyMetrics());
      processMap.put("getNettyMetricSizeByHost", new getNettyMetricSizeByHost());
      processMap.put("getTaskMetrics", new getTaskMetrics());
      processMap.put("getTaskAndStreamMetrics", new getTaskAndStreamMetrics());
      processMap.put("getSummarizedTopologyMetrics", new getSummarizedTopologyMetrics());
      processMap.put("getVersion", new getVersion());
      processMap.put("updateTopology", new updateTopology());
      processMap.put("updateTaskHeartbeat", new updateTaskHeartbeat());
      return processMap;
    }

    public static class submitTopology<I extends Iface> extends org.apache.thrift.ProcessFunction<I, submitTopology_args> {
      public submitTopology() {
        super("submitTopology");
      }

      public submitTopology_args getEmptyArgsInstance() {
        return new submitTopology_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public submitTopology_result getResult(I iface, submitTopology_args args) throws TException {
        submitTopology_result result = new submitTopology_result();
        try {
          iface.submitTopology(args.name, args.uploadedJarLocation, args.jsonConf, args.topology);
        } catch (AlreadyAliveException e) {
          result.e = e;
        } catch (InvalidTopologyException ite) {
          result.ite = ite;
        } catch (TopologyAssignException tae) {
          result.tae = tae;
        }
        return result;
      }
    }

    public static class submitTopologyWithOpts<I extends Iface> extends org.apache.thrift.ProcessFunction<I, submitTopologyWithOpts_args> {
      public submitTopologyWithOpts() {
        super("submitTopologyWithOpts");
      }

      public submitTopologyWithOpts_args getEmptyArgsInstance() {
        return new submitTopologyWithOpts_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public submitTopologyWithOpts_result getResult(I iface, submitTopologyWithOpts_args args) throws TException {
        submitTopologyWithOpts_result result = new submitTopologyWithOpts_result();
        try {
          iface.submitTopologyWithOpts(args.name, args.uploadedJarLocation, args.jsonConf, args.topology, args.options);
        } catch (AlreadyAliveException e) {
          result.e = e;
        } catch (InvalidTopologyException ite) {
          result.ite = ite;
        } catch (TopologyAssignException tae) {
          result.tae = tae;
        }
        return result;
      }
    }

    public static class killTopology<I extends Iface> extends org.apache.thrift.ProcessFunction<I, killTopology_args> {
      public killTopology() {
        super("killTopology");
      }

      public killTopology_args getEmptyArgsInstance() {
        return new killTopology_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public killTopology_result getResult(I iface, killTopology_args args) throws TException {
        killTopology_result result = new killTopology_result();
        try {
          iface.killTopology(args.name);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class killTopologyWithOpts<I extends Iface> extends org.apache.thrift.ProcessFunction<I, killTopologyWithOpts_args> {
      public killTopologyWithOpts() {
        super("killTopologyWithOpts");
      }

      public killTopologyWithOpts_args getEmptyArgsInstance() {
        return new killTopologyWithOpts_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public killTopologyWithOpts_result getResult(I iface, killTopologyWithOpts_args args) throws TException {
        killTopologyWithOpts_result result = new killTopologyWithOpts_result();
        try {
          iface.killTopologyWithOpts(args.name, args.options);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class activate<I extends Iface> extends org.apache.thrift.ProcessFunction<I, activate_args> {
      public activate() {
        super("activate");
      }

      public activate_args getEmptyArgsInstance() {
        return new activate_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public activate_result getResult(I iface, activate_args args) throws TException {
        activate_result result = new activate_result();
        try {
          iface.activate(args.name);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class deactivate<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deactivate_args> {
      public deactivate() {
        super("deactivate");
      }

      public deactivate_args getEmptyArgsInstance() {
        return new deactivate_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public deactivate_result getResult(I iface, deactivate_args args) throws TException {
        deactivate_result result = new deactivate_result();
        try {
          iface.deactivate(args.name);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class rebalance<I extends Iface> extends org.apache.thrift.ProcessFunction<I, rebalance_args> {
      public rebalance() {
        super("rebalance");
      }

      public rebalance_args getEmptyArgsInstance() {
        return new rebalance_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public rebalance_result getResult(I iface, rebalance_args args) throws TException {
        rebalance_result result = new rebalance_result();
        try {
          iface.rebalance(args.name, args.options);
        } catch (NotAliveException e) {
          result.e = e;
        } catch (InvalidTopologyException ite) {
          result.ite = ite;
        }
        return result;
      }
    }

    public static class metricMonitor<I extends Iface> extends org.apache.thrift.ProcessFunction<I, metricMonitor_args> {
      public metricMonitor() {
        super("metricMonitor");
      }

      public metricMonitor_args getEmptyArgsInstance() {
        return new metricMonitor_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public metricMonitor_result getResult(I iface, metricMonitor_args args) throws TException {
        metricMonitor_result result = new metricMonitor_result();
        try {
          iface.metricMonitor(args.name, args.options);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class restart<I extends Iface> extends org.apache.thrift.ProcessFunction<I, restart_args> {
      public restart() {
        super("restart");
      }

      public restart_args getEmptyArgsInstance() {
        return new restart_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public restart_result getResult(I iface, restart_args args) throws TException {
        restart_result result = new restart_result();
        try {
          iface.restart(args.name, args.jsonConf);
        } catch (NotAliveException e) {
          result.e = e;
        } catch (InvalidTopologyException ite) {
          result.ite = ite;
        } catch (TopologyAssignException tae) {
          result.tae = tae;
        }
        return result;
      }
    }

    public static class beginLibUpload<I extends Iface> extends org.apache.thrift.ProcessFunction<I, beginLibUpload_args> {
      public beginLibUpload() {
        super("beginLibUpload");
      }

      public beginLibUpload_args getEmptyArgsInstance() {
        return new beginLibUpload_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public beginLibUpload_result getResult(I iface, beginLibUpload_args args) throws TException {
        beginLibUpload_result result = new beginLibUpload_result();
        iface.beginLibUpload(args.libName);
        return result;
      }
    }

    public static class beginFileUpload<I extends Iface> extends org.apache.thrift.ProcessFunction<I, beginFileUpload_args> {
      public beginFileUpload() {
        super("beginFileUpload");
      }

      public beginFileUpload_args getEmptyArgsInstance() {
        return new beginFileUpload_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public beginFileUpload_result getResult(I iface, beginFileUpload_args args) throws TException {
        beginFileUpload_result result = new beginFileUpload_result();
        result.success = iface.beginFileUpload();
        return result;
      }
    }

    public static class uploadChunk<I extends Iface> extends org.apache.thrift.ProcessFunction<I, uploadChunk_args> {
      public uploadChunk() {
        super("uploadChunk");
      }

      public uploadChunk_args getEmptyArgsInstance() {
        return new uploadChunk_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public uploadChunk_result getResult(I iface, uploadChunk_args args) throws TException {
        uploadChunk_result result = new uploadChunk_result();
        iface.uploadChunk(args.location, args.chunk);
        return result;
      }
    }

    public static class finishFileUpload<I extends Iface> extends org.apache.thrift.ProcessFunction<I, finishFileUpload_args> {
      public finishFileUpload() {
        super("finishFileUpload");
      }

      public finishFileUpload_args getEmptyArgsInstance() {
        return new finishFileUpload_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public finishFileUpload_result getResult(I iface, finishFileUpload_args args) throws TException {
        finishFileUpload_result result = new finishFileUpload_result();
        iface.finishFileUpload(args.location);
        return result;
      }
    }

    public static class beginFileDownload<I extends Iface> extends org.apache.thrift.ProcessFunction<I, beginFileDownload_args> {
      public beginFileDownload() {
        super("beginFileDownload");
      }

      public beginFileDownload_args getEmptyArgsInstance() {
        return new beginFileDownload_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public beginFileDownload_result getResult(I iface, beginFileDownload_args args) throws TException {
        beginFileDownload_result result = new beginFileDownload_result();
        result.success = iface.beginFileDownload(args.file);
        return result;
      }
    }

    public static class downloadChunk<I extends Iface> extends org.apache.thrift.ProcessFunction<I, downloadChunk_args> {
      public downloadChunk() {
        super("downloadChunk");
      }

      public downloadChunk_args getEmptyArgsInstance() {
        return new downloadChunk_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public downloadChunk_result getResult(I iface, downloadChunk_args args) throws TException {
        downloadChunk_result result = new downloadChunk_result();
        result.success = iface.downloadChunk(args.id);
        return result;
      }
    }

    public static class finishFileDownload<I extends Iface> extends org.apache.thrift.ProcessFunction<I, finishFileDownload_args> {
      public finishFileDownload() {
        super("finishFileDownload");
      }

      public finishFileDownload_args getEmptyArgsInstance() {
        return new finishFileDownload_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public finishFileDownload_result getResult(I iface, finishFileDownload_args args) throws TException {
        finishFileDownload_result result = new finishFileDownload_result();
        iface.finishFileDownload(args.id);
        return result;
      }
    }

    public static class getNimbusConf<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getNimbusConf_args> {
      public getNimbusConf() {
        super("getNimbusConf");
      }

      public getNimbusConf_args getEmptyArgsInstance() {
        return new getNimbusConf_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getNimbusConf_result getResult(I iface, getNimbusConf_args args) throws TException {
        getNimbusConf_result result = new getNimbusConf_result();
        result.success = iface.getNimbusConf();
        return result;
      }
    }

    public static class getTopologyConf<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTopologyConf_args> {
      public getTopologyConf() {
        super("getTopologyConf");
      }

      public getTopologyConf_args getEmptyArgsInstance() {
        return new getTopologyConf_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTopologyConf_result getResult(I iface, getTopologyConf_args args) throws TException {
        getTopologyConf_result result = new getTopologyConf_result();
        try {
          result.success = iface.getTopologyConf(args.id);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class getTopologyId<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTopologyId_args> {
      public getTopologyId() {
        super("getTopologyId");
      }

      public getTopologyId_args getEmptyArgsInstance() {
        return new getTopologyId_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTopologyId_result getResult(I iface, getTopologyId_args args) throws TException {
        getTopologyId_result result = new getTopologyId_result();
        try {
          result.success = iface.getTopologyId(args.topologyName);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class getClusterInfo<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getClusterInfo_args> {
      public getClusterInfo() {
        super("getClusterInfo");
      }

      public getClusterInfo_args getEmptyArgsInstance() {
        return new getClusterInfo_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getClusterInfo_result getResult(I iface, getClusterInfo_args args) throws TException {
        getClusterInfo_result result = new getClusterInfo_result();
        result.success = iface.getClusterInfo();
        return result;
      }
    }

    public static class getSupervisorWorkers<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getSupervisorWorkers_args> {
      public getSupervisorWorkers() {
        super("getSupervisorWorkers");
      }

      public getSupervisorWorkers_args getEmptyArgsInstance() {
        return new getSupervisorWorkers_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getSupervisorWorkers_result getResult(I iface, getSupervisorWorkers_args args) throws TException {
        getSupervisorWorkers_result result = new getSupervisorWorkers_result();
        try {
          result.success = iface.getSupervisorWorkers(args.host);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class getTopologyInfo<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTopologyInfo_args> {
      public getTopologyInfo() {
        super("getTopologyInfo");
      }

      public getTopologyInfo_args getEmptyArgsInstance() {
        return new getTopologyInfo_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTopologyInfo_result getResult(I iface, getTopologyInfo_args args) throws TException {
        getTopologyInfo_result result = new getTopologyInfo_result();
        try {
          result.success = iface.getTopologyInfo(args.id);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class getTopologyInfoByName<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTopologyInfoByName_args> {
      public getTopologyInfoByName() {
        super("getTopologyInfoByName");
      }

      public getTopologyInfoByName_args getEmptyArgsInstance() {
        return new getTopologyInfoByName_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTopologyInfoByName_result getResult(I iface, getTopologyInfoByName_args args) throws TException {
        getTopologyInfoByName_result result = new getTopologyInfoByName_result();
        try {
          result.success = iface.getTopologyInfoByName(args.topologyName);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class getTopology<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTopology_args> {
      public getTopology() {
        super("getTopology");
      }

      public getTopology_args getEmptyArgsInstance() {
        return new getTopology_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTopology_result getResult(I iface, getTopology_args args) throws TException {
        getTopology_result result = new getTopology_result();
        try {
          result.success = iface.getTopology(args.id);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class getUserTopology<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getUserTopology_args> {
      public getUserTopology() {
        super("getUserTopology");
      }

      public getUserTopology_args getEmptyArgsInstance() {
        return new getUserTopology_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getUserTopology_result getResult(I iface, getUserTopology_args args) throws TException {
        getUserTopology_result result = new getUserTopology_result();
        try {
          result.success = iface.getUserTopology(args.id);
        } catch (NotAliveException e) {
          result.e = e;
        }
        return result;
      }
    }

    public static class uploadTopologyMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, uploadTopologyMetrics_args> {
      public uploadTopologyMetrics() {
        super("uploadTopologyMetrics");
      }

      public uploadTopologyMetrics_args getEmptyArgsInstance() {
        return new uploadTopologyMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public uploadTopologyMetrics_result getResult(I iface, uploadTopologyMetrics_args args) throws TException {
        uploadTopologyMetrics_result result = new uploadTopologyMetrics_result();
        iface.uploadTopologyMetrics(args.topologyId, args.topologyMetrics);
        return result;
      }
    }

    public static class registerMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, registerMetrics_args> {
      public registerMetrics() {
        super("registerMetrics");
      }

      public registerMetrics_args getEmptyArgsInstance() {
        return new registerMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public registerMetrics_result getResult(I iface, registerMetrics_args args) throws TException {
        registerMetrics_result result = new registerMetrics_result();
        result.success = iface.registerMetrics(args.topologyId, args.metrics);
        return result;
      }
    }

    public static class getTopologyMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTopologyMetrics_args> {
      public getTopologyMetrics() {
        super("getTopologyMetrics");
      }

      public getTopologyMetrics_args getEmptyArgsInstance() {
        return new getTopologyMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTopologyMetrics_result getResult(I iface, getTopologyMetrics_args args) throws TException {
        getTopologyMetrics_result result = new getTopologyMetrics_result();
        result.success = iface.getTopologyMetrics(args.topologyId);
        return result;
      }
    }

    public static class getMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getMetrics_args> {
      public getMetrics() {
        super("getMetrics");
      }

      public getMetrics_args getEmptyArgsInstance() {
        return new getMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getMetrics_result getResult(I iface, getMetrics_args args) throws TException {
        getMetrics_result result = new getMetrics_result();
        result.success = iface.getMetrics(args.topologyId, args.type);
        return result;
      }
    }

    public static class getNettyMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getNettyMetrics_args> {
      public getNettyMetrics() {
        super("getNettyMetrics");
      }

      public getNettyMetrics_args getEmptyArgsInstance() {
        return new getNettyMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getNettyMetrics_result getResult(I iface, getNettyMetrics_args args) throws TException {
        getNettyMetrics_result result = new getNettyMetrics_result();
        result.success = iface.getNettyMetrics(args.topologyId);
        return result;
      }
    }

    public static class getNettyMetricsByHost<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getNettyMetricsByHost_args> {
      public getNettyMetricsByHost() {
        super("getNettyMetricsByHost");
      }

      public getNettyMetricsByHost_args getEmptyArgsInstance() {
        return new getNettyMetricsByHost_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getNettyMetricsByHost_result getResult(I iface, getNettyMetricsByHost_args args) throws TException {
        getNettyMetricsByHost_result result = new getNettyMetricsByHost_result();
        result.success = iface.getNettyMetricsByHost(args.topologyId, args.host);
        return result;
      }
    }

    public static class getPagingNettyMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getPagingNettyMetrics_args> {
      public getPagingNettyMetrics() {
        super("getPagingNettyMetrics");
      }

      public getPagingNettyMetrics_args getEmptyArgsInstance() {
        return new getPagingNettyMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getPagingNettyMetrics_result getResult(I iface, getPagingNettyMetrics_args args) throws TException {
        getPagingNettyMetrics_result result = new getPagingNettyMetrics_result();
        result.success = iface.getPagingNettyMetrics(args.topologyId, args.host, args.page);
        return result;
      }
    }

    public static class getNettyMetricSizeByHost<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getNettyMetricSizeByHost_args> {
      public getNettyMetricSizeByHost() {
        super("getNettyMetricSizeByHost");
      }

      public getNettyMetricSizeByHost_args getEmptyArgsInstance() {
        return new getNettyMetricSizeByHost_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getNettyMetricSizeByHost_result getResult(I iface, getNettyMetricSizeByHost_args args) throws TException {
        getNettyMetricSizeByHost_result result = new getNettyMetricSizeByHost_result();
        result.success = iface.getNettyMetricSizeByHost(args.topologyId, args.host);
        result.set_success_isSet(true);
        return result;
      }
    }

    public static class getTaskMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTaskMetrics_args> {
      public getTaskMetrics() {
        super("getTaskMetrics");
      }

      public getTaskMetrics_args getEmptyArgsInstance() {
        return new getTaskMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTaskMetrics_result getResult(I iface, getTaskMetrics_args args) throws TException {
        getTaskMetrics_result result = new getTaskMetrics_result();
        result.success = iface.getTaskMetrics(args.topologyId, args.component);
        return result;
      }
    }

    public static class getTaskAndStreamMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getTaskAndStreamMetrics_args> {
      public getTaskAndStreamMetrics() {
        super("getTaskAndStreamMetrics");
      }

      public getTaskAndStreamMetrics_args getEmptyArgsInstance() {
        return new getTaskAndStreamMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getTaskAndStreamMetrics_result getResult(I iface, getTaskAndStreamMetrics_args args) throws TException {
        getTaskAndStreamMetrics_result result = new getTaskAndStreamMetrics_result();
        result.success = iface.getTaskAndStreamMetrics(args.topologyId, args.taskId);
        return result;
      }
    }

    public static class getSummarizedTopologyMetrics<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getSummarizedTopologyMetrics_args> {
      public getSummarizedTopologyMetrics() {
        super("getSummarizedTopologyMetrics");
      }

      public getSummarizedTopologyMetrics_args getEmptyArgsInstance() {
        return new getSummarizedTopologyMetrics_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getSummarizedTopologyMetrics_result getResult(I iface, getSummarizedTopologyMetrics_args args) throws TException {
        getSummarizedTopologyMetrics_result result = new getSummarizedTopologyMetrics_result();
        result.success = iface.getSummarizedTopologyMetrics(args.topologyId);
        return result;
      }
    }

    public static class getVersion<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getVersion_args> {
      public getVersion() {
        super("getVersion");
      }

      public getVersion_args getEmptyArgsInstance() {
        return new getVersion_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getVersion_result getResult(I iface, getVersion_args args) throws TException {
        getVersion_result result = new getVersion_result();
        result.success = iface.getVersion();
        return result;
      }
    }

    public static class updateTopology<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updateTopology_args> {
      public updateTopology() {
        super("updateTopology");
      }

      public updateTopology_args getEmptyArgsInstance() {
        return new updateTopology_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updateTopology_result getResult(I iface, updateTopology_args args) throws TException {
        updateTopology_result result = new updateTopology_result();
        try {
          iface.updateTopology(args.name, args.uploadedLocation, args.updateConf);
        } catch (NotAliveException e) {
          result.e = e;
        } catch (InvalidTopologyException ite) {
          result.ite = ite;
        }
        return result;
      }
    }

    public static class updateTaskHeartbeat<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updateTaskHeartbeat_args> {
      public updateTaskHeartbeat() {
        super("updateTaskHeartbeat");
      }

      public updateTaskHeartbeat_args getEmptyArgsInstance() {
        return new updateTaskHeartbeat_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updateTaskHeartbeat_result getResult(I iface, updateTaskHeartbeat_args args) throws TException {
        updateTaskHeartbeat_result result = new updateTaskHeartbeat_result();
        iface.updateTaskHeartbeat(args.taskHbs);
        return result;
      }
    }

  }

  public static class AsyncProcessor<I extends AsyncIface> extends org.apache.thrift.TBaseAsyncProcessor<I> {
    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncProcessor.class.getName());
    public AsyncProcessor(I iface) {
      super(iface, getProcessMap(new HashMap<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>>()));
    }

    protected AsyncProcessor(I iface, Map<String,  org.apache.thrift.AsyncProcessFunction<I, ? extends  org.apache.thrift.TBase, ?>> processMap) {
      super(iface, getProcessMap(processMap));
    }

    private static <I extends AsyncIface> Map<String,  org.apache.thrift.AsyncProcessFunction<I, ? extends  org.apache.thrift.TBase,?>> getProcessMap(Map<String,  org.apache.thrift.AsyncProcessFunction<I, ? extends  org.apache.thrift.TBase, ?>> processMap) {
      processMap.put("submitTopology", new submitTopology());
      processMap.put("submitTopologyWithOpts", new submitTopologyWithOpts());
      processMap.put("killTopology", new killTopology());
      processMap.put("killTopologyWithOpts", new killTopologyWithOpts());
      processMap.put("activate", new activate());
      processMap.put("deactivate", new deactivate());
      processMap.put("rebalance", new rebalance());
      processMap.put("metricMonitor", new metricMonitor());
      processMap.put("restart", new restart());
      processMap.put("beginLibUpload", new beginLibUpload());
      processMap.put("beginFileUpload", new beginFileUpload());
      processMap.put("uploadChunk", new uploadChunk());
      processMap.put("finishFileUpload", new finishFileUpload());
      processMap.put("beginFileDownload", new beginFileDownload());
      processMap.put("downloadChunk", new downloadChunk());
      processMap.put("finishFileDownload", new finishFileDownload());
      processMap.put("getNimbusConf", new getNimbusConf());
      processMap.put("getTopologyConf", new getTopologyConf());
      processMap.put("getTopologyId", new getTopologyId());
      processMap.put("getClusterInfo", new getClusterInfo());
      processMap.put("getSupervisorWorkers", new getSupervisorWorkers());
      processMap.put("getTopologyInfo", new getTopologyInfo());
      processMap.put("getTopologyInfoByName", new getTopologyInfoByName());
      processMap.put("getTopology", new getTopology());
      processMap.put("getUserTopology", new getUserTopology());
      processMap.put("uploadTopologyMetrics", new uploadTopologyMetrics());
      processMap.put("registerMetrics", new registerMetrics());
      processMap.put("getTopologyMetrics", new getTopologyMetrics());
      processMap.put("getMetrics", new getMetrics());
      processMap.put("getNettyMetrics", new getNettyMetrics());
      processMap.put("getNettyMetricsByHost", new getNettyMetricsByHost());
      processMap.put("getPagingNettyMetrics", new getPagingNettyMetrics());
      processMap.put("getNettyMetricSizeByHost", new getNettyMetricSizeByHost());
      processMap.put("getTaskMetrics", new getTaskMetrics());
      processMap.put("getTaskAndStreamMetrics", new getTaskAndStreamMetrics());
      processMap.put("getSummarizedTopologyMetrics", new getSummarizedTopologyMetrics());
      processMap.put("getVersion", new getVersion());
      processMap.put("updateTopology", new updateTopology());
      processMap.put("updateTaskHeartbeat", new updateTaskHeartbeat());
      return processMap;
    }

    public static class submitTopology<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, submitTopology_args, Void> {
      public submitTopology() {
        super("submitTopology");
      }

      public submitTopology_args getEmptyArgsInstance() {
        return new submitTopology_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            submitTopology_result result = new submitTopology_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            submitTopology_result result = new submitTopology_result();
            if (e instanceof AlreadyAliveException) {
                        result.e = (AlreadyAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
            else             if (e instanceof InvalidTopologyException) {
                        result.ite = (InvalidTopologyException) e;
                        result.set_ite_isSet(true);
                        msg = result;
            }
            else             if (e instanceof TopologyAssignException) {
                        result.tae = (TopologyAssignException) e;
                        result.set_tae_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, submitTopology_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.submitTopology(args.name, args.uploadedJarLocation, args.jsonConf, args.topology,resultHandler);
      }
    }

    public static class submitTopologyWithOpts<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, submitTopologyWithOpts_args, Void> {
      public submitTopologyWithOpts() {
        super("submitTopologyWithOpts");
      }

      public submitTopologyWithOpts_args getEmptyArgsInstance() {
        return new submitTopologyWithOpts_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            submitTopologyWithOpts_result result = new submitTopologyWithOpts_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            submitTopologyWithOpts_result result = new submitTopologyWithOpts_result();
            if (e instanceof AlreadyAliveException) {
                        result.e = (AlreadyAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
            else             if (e instanceof InvalidTopologyException) {
                        result.ite = (InvalidTopologyException) e;
                        result.set_ite_isSet(true);
                        msg = result;
            }
            else             if (e instanceof TopologyAssignException) {
                        result.tae = (TopologyAssignException) e;
                        result.set_tae_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, submitTopologyWithOpts_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.submitTopologyWithOpts(args.name, args.uploadedJarLocation, args.jsonConf, args.topology, args.options,resultHandler);
      }
    }

    public static class killTopology<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, killTopology_args, Void> {
      public killTopology() {
        super("killTopology");
      }

      public killTopology_args getEmptyArgsInstance() {
        return new killTopology_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            killTopology_result result = new killTopology_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            killTopology_result result = new killTopology_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, killTopology_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.killTopology(args.name,resultHandler);
      }
    }

    public static class killTopologyWithOpts<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, killTopologyWithOpts_args, Void> {
      public killTopologyWithOpts() {
        super("killTopologyWithOpts");
      }

      public killTopologyWithOpts_args getEmptyArgsInstance() {
        return new killTopologyWithOpts_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            killTopologyWithOpts_result result = new killTopologyWithOpts_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            killTopologyWithOpts_result result = new killTopologyWithOpts_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, killTopologyWithOpts_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.killTopologyWithOpts(args.name, args.options,resultHandler);
      }
    }

    public static class activate<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, activate_args, Void> {
      public activate() {
        super("activate");
      }

      public activate_args getEmptyArgsInstance() {
        return new activate_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            activate_result result = new activate_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            activate_result result = new activate_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, activate_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.activate(args.name,resultHandler);
      }
    }

    public static class deactivate<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deactivate_args, Void> {
      public deactivate() {
        super("deactivate");
      }

      public deactivate_args getEmptyArgsInstance() {
        return new deactivate_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            deactivate_result result = new deactivate_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            deactivate_result result = new deactivate_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, deactivate_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.deactivate(args.name,resultHandler);
      }
    }

    public static class rebalance<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, rebalance_args, Void> {
      public rebalance() {
        super("rebalance");
      }

      public rebalance_args getEmptyArgsInstance() {
        return new rebalance_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            rebalance_result result = new rebalance_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            rebalance_result result = new rebalance_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
            else             if (e instanceof InvalidTopologyException) {
                        result.ite = (InvalidTopologyException) e;
                        result.set_ite_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, rebalance_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.rebalance(args.name, args.options,resultHandler);
      }
    }

    public static class metricMonitor<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, metricMonitor_args, Void> {
      public metricMonitor() {
        super("metricMonitor");
      }

      public metricMonitor_args getEmptyArgsInstance() {
        return new metricMonitor_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            metricMonitor_result result = new metricMonitor_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            metricMonitor_result result = new metricMonitor_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, metricMonitor_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.metricMonitor(args.name, args.options,resultHandler);
      }
    }

    public static class restart<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, restart_args, Void> {
      public restart() {
        super("restart");
      }

      public restart_args getEmptyArgsInstance() {
        return new restart_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            restart_result result = new restart_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            restart_result result = new restart_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
            else             if (e instanceof InvalidTopologyException) {
                        result.ite = (InvalidTopologyException) e;
                        result.set_ite_isSet(true);
                        msg = result;
            }
            else             if (e instanceof TopologyAssignException) {
                        result.tae = (TopologyAssignException) e;
                        result.set_tae_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, restart_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.restart(args.name, args.jsonConf,resultHandler);
      }
    }

    public static class beginLibUpload<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, beginLibUpload_args, Void> {
      public beginLibUpload() {
        super("beginLibUpload");
      }

      public beginLibUpload_args getEmptyArgsInstance() {
        return new beginLibUpload_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            beginLibUpload_result result = new beginLibUpload_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            beginLibUpload_result result = new beginLibUpload_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, beginLibUpload_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.beginLibUpload(args.libName,resultHandler);
      }
    }

    public static class beginFileUpload<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, beginFileUpload_args, String> {
      public beginFileUpload() {
        super("beginFileUpload");
      }

      public beginFileUpload_args getEmptyArgsInstance() {
        return new beginFileUpload_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            beginFileUpload_result result = new beginFileUpload_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            beginFileUpload_result result = new beginFileUpload_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, beginFileUpload_args args, AsyncMethodCallback<String> resultHandler) throws TException {
        iface.beginFileUpload(resultHandler);
      }
    }

    public static class uploadChunk<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, uploadChunk_args, Void> {
      public uploadChunk() {
        super("uploadChunk");
      }

      public uploadChunk_args getEmptyArgsInstance() {
        return new uploadChunk_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            uploadChunk_result result = new uploadChunk_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            uploadChunk_result result = new uploadChunk_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, uploadChunk_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.uploadChunk(args.location, args.chunk,resultHandler);
      }
    }

    public static class finishFileUpload<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, finishFileUpload_args, Void> {
      public finishFileUpload() {
        super("finishFileUpload");
      }

      public finishFileUpload_args getEmptyArgsInstance() {
        return new finishFileUpload_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            finishFileUpload_result result = new finishFileUpload_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            finishFileUpload_result result = new finishFileUpload_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, finishFileUpload_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.finishFileUpload(args.location,resultHandler);
      }
    }

    public static class beginFileDownload<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, beginFileDownload_args, String> {
      public beginFileDownload() {
        super("beginFileDownload");
      }

      public beginFileDownload_args getEmptyArgsInstance() {
        return new beginFileDownload_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            beginFileDownload_result result = new beginFileDownload_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            beginFileDownload_result result = new beginFileDownload_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, beginFileDownload_args args, AsyncMethodCallback<String> resultHandler) throws TException {
        iface.beginFileDownload(args.file,resultHandler);
      }
    }

    public static class downloadChunk<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, downloadChunk_args, ByteBuffer> {
      public downloadChunk() {
        super("downloadChunk");
      }

      public downloadChunk_args getEmptyArgsInstance() {
        return new downloadChunk_args();
      }

      public AsyncMethodCallback<ByteBuffer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<ByteBuffer>() { 
          public void onComplete(ByteBuffer o) {
            downloadChunk_result result = new downloadChunk_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            downloadChunk_result result = new downloadChunk_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, downloadChunk_args args, AsyncMethodCallback<ByteBuffer> resultHandler) throws TException {
        iface.downloadChunk(args.id,resultHandler);
      }
    }

    public static class finishFileDownload<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, finishFileDownload_args, Void> {
      public finishFileDownload() {
        super("finishFileDownload");
      }

      public finishFileDownload_args getEmptyArgsInstance() {
        return new finishFileDownload_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            finishFileDownload_result result = new finishFileDownload_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            finishFileDownload_result result = new finishFileDownload_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, finishFileDownload_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.finishFileDownload(args.id,resultHandler);
      }
    }

    public static class getNimbusConf<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getNimbusConf_args, String> {
      public getNimbusConf() {
        super("getNimbusConf");
      }

      public getNimbusConf_args getEmptyArgsInstance() {
        return new getNimbusConf_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            getNimbusConf_result result = new getNimbusConf_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getNimbusConf_result result = new getNimbusConf_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getNimbusConf_args args, AsyncMethodCallback<String> resultHandler) throws TException {
        iface.getNimbusConf(resultHandler);
      }
    }

    public static class getTopologyConf<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTopologyConf_args, String> {
      public getTopologyConf() {
        super("getTopologyConf");
      }

      public getTopologyConf_args getEmptyArgsInstance() {
        return new getTopologyConf_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            getTopologyConf_result result = new getTopologyConf_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTopologyConf_result result = new getTopologyConf_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTopologyConf_args args, AsyncMethodCallback<String> resultHandler) throws TException {
        iface.getTopologyConf(args.id,resultHandler);
      }
    }

    public static class getTopologyId<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTopologyId_args, String> {
      public getTopologyId() {
        super("getTopologyId");
      }

      public getTopologyId_args getEmptyArgsInstance() {
        return new getTopologyId_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            getTopologyId_result result = new getTopologyId_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTopologyId_result result = new getTopologyId_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTopologyId_args args, AsyncMethodCallback<String> resultHandler) throws TException {
        iface.getTopologyId(args.topologyName,resultHandler);
      }
    }

    public static class getClusterInfo<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getClusterInfo_args, ClusterSummary> {
      public getClusterInfo() {
        super("getClusterInfo");
      }

      public getClusterInfo_args getEmptyArgsInstance() {
        return new getClusterInfo_args();
      }

      public AsyncMethodCallback<ClusterSummary> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<ClusterSummary>() { 
          public void onComplete(ClusterSummary o) {
            getClusterInfo_result result = new getClusterInfo_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getClusterInfo_result result = new getClusterInfo_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getClusterInfo_args args, AsyncMethodCallback<ClusterSummary> resultHandler) throws TException {
        iface.getClusterInfo(resultHandler);
      }
    }

    public static class getSupervisorWorkers<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getSupervisorWorkers_args, SupervisorWorkers> {
      public getSupervisorWorkers() {
        super("getSupervisorWorkers");
      }

      public getSupervisorWorkers_args getEmptyArgsInstance() {
        return new getSupervisorWorkers_args();
      }

      public AsyncMethodCallback<SupervisorWorkers> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<SupervisorWorkers>() { 
          public void onComplete(SupervisorWorkers o) {
            getSupervisorWorkers_result result = new getSupervisorWorkers_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getSupervisorWorkers_result result = new getSupervisorWorkers_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getSupervisorWorkers_args args, AsyncMethodCallback<SupervisorWorkers> resultHandler) throws TException {
        iface.getSupervisorWorkers(args.host,resultHandler);
      }
    }

    public static class getTopologyInfo<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTopologyInfo_args, TopologyInfo> {
      public getTopologyInfo() {
        super("getTopologyInfo");
      }

      public getTopologyInfo_args getEmptyArgsInstance() {
        return new getTopologyInfo_args();
      }

      public AsyncMethodCallback<TopologyInfo> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<TopologyInfo>() { 
          public void onComplete(TopologyInfo o) {
            getTopologyInfo_result result = new getTopologyInfo_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTopologyInfo_result result = new getTopologyInfo_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTopologyInfo_args args, AsyncMethodCallback<TopologyInfo> resultHandler) throws TException {
        iface.getTopologyInfo(args.id,resultHandler);
      }
    }

    public static class getTopologyInfoByName<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTopologyInfoByName_args, TopologyInfo> {
      public getTopologyInfoByName() {
        super("getTopologyInfoByName");
      }

      public getTopologyInfoByName_args getEmptyArgsInstance() {
        return new getTopologyInfoByName_args();
      }

      public AsyncMethodCallback<TopologyInfo> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<TopologyInfo>() { 
          public void onComplete(TopologyInfo o) {
            getTopologyInfoByName_result result = new getTopologyInfoByName_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTopologyInfoByName_result result = new getTopologyInfoByName_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTopologyInfoByName_args args, AsyncMethodCallback<TopologyInfo> resultHandler) throws TException {
        iface.getTopologyInfoByName(args.topologyName,resultHandler);
      }
    }

    public static class getTopology<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTopology_args, StormTopology> {
      public getTopology() {
        super("getTopology");
      }

      public getTopology_args getEmptyArgsInstance() {
        return new getTopology_args();
      }

      public AsyncMethodCallback<StormTopology> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<StormTopology>() { 
          public void onComplete(StormTopology o) {
            getTopology_result result = new getTopology_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTopology_result result = new getTopology_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTopology_args args, AsyncMethodCallback<StormTopology> resultHandler) throws TException {
        iface.getTopology(args.id,resultHandler);
      }
    }

    public static class getUserTopology<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getUserTopology_args, StormTopology> {
      public getUserTopology() {
        super("getUserTopology");
      }

      public getUserTopology_args getEmptyArgsInstance() {
        return new getUserTopology_args();
      }

      public AsyncMethodCallback<StormTopology> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<StormTopology>() { 
          public void onComplete(StormTopology o) {
            getUserTopology_result result = new getUserTopology_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getUserTopology_result result = new getUserTopology_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getUserTopology_args args, AsyncMethodCallback<StormTopology> resultHandler) throws TException {
        iface.getUserTopology(args.id,resultHandler);
      }
    }

    public static class uploadTopologyMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, uploadTopologyMetrics_args, Void> {
      public uploadTopologyMetrics() {
        super("uploadTopologyMetrics");
      }

      public uploadTopologyMetrics_args getEmptyArgsInstance() {
        return new uploadTopologyMetrics_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            uploadTopologyMetrics_result result = new uploadTopologyMetrics_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            uploadTopologyMetrics_result result = new uploadTopologyMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, uploadTopologyMetrics_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.uploadTopologyMetrics(args.topologyId, args.topologyMetrics,resultHandler);
      }
    }

    public static class registerMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, registerMetrics_args, Map<String,Long>> {
      public registerMetrics() {
        super("registerMetrics");
      }

      public registerMetrics_args getEmptyArgsInstance() {
        return new registerMetrics_args();
      }

      public AsyncMethodCallback<Map<String,Long>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Map<String,Long>>() { 
          public void onComplete(Map<String,Long> o) {
            registerMetrics_result result = new registerMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            registerMetrics_result result = new registerMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, registerMetrics_args args, AsyncMethodCallback<Map<String,Long>> resultHandler) throws TException {
        iface.registerMetrics(args.topologyId, args.metrics,resultHandler);
      }
    }

    public static class getTopologyMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTopologyMetrics_args, TopologyMetric> {
      public getTopologyMetrics() {
        super("getTopologyMetrics");
      }

      public getTopologyMetrics_args getEmptyArgsInstance() {
        return new getTopologyMetrics_args();
      }

      public AsyncMethodCallback<TopologyMetric> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<TopologyMetric>() { 
          public void onComplete(TopologyMetric o) {
            getTopologyMetrics_result result = new getTopologyMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTopologyMetrics_result result = new getTopologyMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTopologyMetrics_args args, AsyncMethodCallback<TopologyMetric> resultHandler) throws TException {
        iface.getTopologyMetrics(args.topologyId,resultHandler);
      }
    }

    public static class getMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getMetrics_args, List<MetricInfo>> {
      public getMetrics() {
        super("getMetrics");
      }

      public getMetrics_args getEmptyArgsInstance() {
        return new getMetrics_args();
      }

      public AsyncMethodCallback<List<MetricInfo>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<MetricInfo>>() { 
          public void onComplete(List<MetricInfo> o) {
            getMetrics_result result = new getMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getMetrics_result result = new getMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getMetrics_args args, AsyncMethodCallback<List<MetricInfo>> resultHandler) throws TException {
        iface.getMetrics(args.topologyId, args.type,resultHandler);
      }
    }

    public static class getNettyMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getNettyMetrics_args, MetricInfo> {
      public getNettyMetrics() {
        super("getNettyMetrics");
      }

      public getNettyMetrics_args getEmptyArgsInstance() {
        return new getNettyMetrics_args();
      }

      public AsyncMethodCallback<MetricInfo> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<MetricInfo>() { 
          public void onComplete(MetricInfo o) {
            getNettyMetrics_result result = new getNettyMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getNettyMetrics_result result = new getNettyMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getNettyMetrics_args args, AsyncMethodCallback<MetricInfo> resultHandler) throws TException {
        iface.getNettyMetrics(args.topologyId,resultHandler);
      }
    }

    public static class getNettyMetricsByHost<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getNettyMetricsByHost_args, MetricInfo> {
      public getNettyMetricsByHost() {
        super("getNettyMetricsByHost");
      }

      public getNettyMetricsByHost_args getEmptyArgsInstance() {
        return new getNettyMetricsByHost_args();
      }

      public AsyncMethodCallback<MetricInfo> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<MetricInfo>() { 
          public void onComplete(MetricInfo o) {
            getNettyMetricsByHost_result result = new getNettyMetricsByHost_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getNettyMetricsByHost_result result = new getNettyMetricsByHost_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getNettyMetricsByHost_args args, AsyncMethodCallback<MetricInfo> resultHandler) throws TException {
        iface.getNettyMetricsByHost(args.topologyId, args.host,resultHandler);
      }
    }

    public static class getPagingNettyMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getPagingNettyMetrics_args, MetricInfo> {
      public getPagingNettyMetrics() {
        super("getPagingNettyMetrics");
      }

      public getPagingNettyMetrics_args getEmptyArgsInstance() {
        return new getPagingNettyMetrics_args();
      }

      public AsyncMethodCallback<MetricInfo> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<MetricInfo>() { 
          public void onComplete(MetricInfo o) {
            getPagingNettyMetrics_result result = new getPagingNettyMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getPagingNettyMetrics_result result = new getPagingNettyMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getPagingNettyMetrics_args args, AsyncMethodCallback<MetricInfo> resultHandler) throws TException {
        iface.getPagingNettyMetrics(args.topologyId, args.host, args.page,resultHandler);
      }
    }

    public static class getNettyMetricSizeByHost<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getNettyMetricSizeByHost_args, Integer> {
      public getNettyMetricSizeByHost() {
        super("getNettyMetricSizeByHost");
      }

      public getNettyMetricSizeByHost_args getEmptyArgsInstance() {
        return new getNettyMetricSizeByHost_args();
      }

      public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Integer>() { 
          public void onComplete(Integer o) {
            getNettyMetricSizeByHost_result result = new getNettyMetricSizeByHost_result();
            result.success = o;
            result.set_success_isSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getNettyMetricSizeByHost_result result = new getNettyMetricSizeByHost_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getNettyMetricSizeByHost_args args, AsyncMethodCallback<Integer> resultHandler) throws TException {
        iface.getNettyMetricSizeByHost(args.topologyId, args.host,resultHandler);
      }
    }

    public static class getTaskMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTaskMetrics_args, MetricInfo> {
      public getTaskMetrics() {
        super("getTaskMetrics");
      }

      public getTaskMetrics_args getEmptyArgsInstance() {
        return new getTaskMetrics_args();
      }

      public AsyncMethodCallback<MetricInfo> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<MetricInfo>() { 
          public void onComplete(MetricInfo o) {
            getTaskMetrics_result result = new getTaskMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTaskMetrics_result result = new getTaskMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTaskMetrics_args args, AsyncMethodCallback<MetricInfo> resultHandler) throws TException {
        iface.getTaskMetrics(args.topologyId, args.component,resultHandler);
      }
    }

    public static class getTaskAndStreamMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getTaskAndStreamMetrics_args, List<MetricInfo>> {
      public getTaskAndStreamMetrics() {
        super("getTaskAndStreamMetrics");
      }

      public getTaskAndStreamMetrics_args getEmptyArgsInstance() {
        return new getTaskAndStreamMetrics_args();
      }

      public AsyncMethodCallback<List<MetricInfo>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<MetricInfo>>() { 
          public void onComplete(List<MetricInfo> o) {
            getTaskAndStreamMetrics_result result = new getTaskAndStreamMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getTaskAndStreamMetrics_result result = new getTaskAndStreamMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getTaskAndStreamMetrics_args args, AsyncMethodCallback<List<MetricInfo>> resultHandler) throws TException {
        iface.getTaskAndStreamMetrics(args.topologyId, args.taskId,resultHandler);
      }
    }

    public static class getSummarizedTopologyMetrics<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getSummarizedTopologyMetrics_args, List<MetricInfo>> {
      public getSummarizedTopologyMetrics() {
        super("getSummarizedTopologyMetrics");
      }

      public getSummarizedTopologyMetrics_args getEmptyArgsInstance() {
        return new getSummarizedTopologyMetrics_args();
      }

      public AsyncMethodCallback<List<MetricInfo>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<MetricInfo>>() { 
          public void onComplete(List<MetricInfo> o) {
            getSummarizedTopologyMetrics_result result = new getSummarizedTopologyMetrics_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getSummarizedTopologyMetrics_result result = new getSummarizedTopologyMetrics_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getSummarizedTopologyMetrics_args args, AsyncMethodCallback<List<MetricInfo>> resultHandler) throws TException {
        iface.getSummarizedTopologyMetrics(args.topologyId,resultHandler);
      }
    }

    public static class getVersion<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getVersion_args, String> {
      public getVersion() {
        super("getVersion");
      }

      public getVersion_args getEmptyArgsInstance() {
        return new getVersion_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            getVersion_result result = new getVersion_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getVersion_result result = new getVersion_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getVersion_args args, AsyncMethodCallback<String> resultHandler) throws TException {
        iface.getVersion(resultHandler);
      }
    }

    public static class updateTopology<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updateTopology_args, Void> {
      public updateTopology() {
        super("updateTopology");
      }

      public updateTopology_args getEmptyArgsInstance() {
        return new updateTopology_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            updateTopology_result result = new updateTopology_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updateTopology_result result = new updateTopology_result();
            if (e instanceof NotAliveException) {
                        result.e = (NotAliveException) e;
                        result.set_e_isSet(true);
                        msg = result;
            }
            else             if (e instanceof InvalidTopologyException) {
                        result.ite = (InvalidTopologyException) e;
                        result.set_ite_isSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updateTopology_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.updateTopology(args.name, args.uploadedLocation, args.updateConf,resultHandler);
      }
    }

    public static class updateTaskHeartbeat<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updateTaskHeartbeat_args, Void> {
      public updateTaskHeartbeat() {
        super("updateTaskHeartbeat");
      }

      public updateTaskHeartbeat_args getEmptyArgsInstance() {
        return new updateTaskHeartbeat_args();
      }

      public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Void>() { 
          public void onComplete(Void o) {
            updateTaskHeartbeat_result result = new updateTaskHeartbeat_result();
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updateTaskHeartbeat_result result = new updateTaskHeartbeat_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updateTaskHeartbeat_args args, AsyncMethodCallback<Void> resultHandler) throws TException {
        iface.updateTaskHeartbeat(args.taskHbs,resultHandler);
      }
    }

  }

  public static class submitTopology_args implements org.apache.thrift.TBase<submitTopology_args, submitTopology_args._Fields>, java.io.Serializable, Cloneable, Comparable<submitTopology_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("submitTopology_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField UPLOADED_JAR_LOCATION_FIELD_DESC = new org.apache.thrift.protocol.TField("uploadedJarLocation", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField JSON_CONF_FIELD_DESC = new org.apache.thrift.protocol.TField("jsonConf", org.apache.thrift.protocol.TType.STRING, (short)3);
    private static final org.apache.thrift.protocol.TField TOPOLOGY_FIELD_DESC = new org.apache.thrift.protocol.TField("topology", org.apache.thrift.protocol.TType.STRUCT, (short)4);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new submitTopology_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new submitTopology_argsTupleSchemeFactory());
    }

    private String name; // required
    private String uploadedJarLocation; // required
    private String jsonConf; // required
    private StormTopology topology; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name"),
      UPLOADED_JAR_LOCATION((short)2, "uploadedJarLocation"),
      JSON_CONF((short)3, "jsonConf"),
      TOPOLOGY((short)4, "topology");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          case 2: // UPLOADED_JAR_LOCATION
            return UPLOADED_JAR_LOCATION;
          case 3: // JSON_CONF
            return JSON_CONF;
          case 4: // TOPOLOGY
            return TOPOLOGY;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.UPLOADED_JAR_LOCATION, new org.apache.thrift.meta_data.FieldMetaData("uploadedJarLocation", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.JSON_CONF, new org.apache.thrift.meta_data.FieldMetaData("jsonConf", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.TOPOLOGY, new org.apache.thrift.meta_data.FieldMetaData("topology", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, StormTopology.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(submitTopology_args.class, metaDataMap);
    }

    public submitTopology_args() {
    }

    public submitTopology_args(
      String name,
      String uploadedJarLocation,
      String jsonConf,
      StormTopology topology)
    {
      this();
      this.name = name;
      this.uploadedJarLocation = uploadedJarLocation;
      this.jsonConf = jsonConf;
      this.topology = topology;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public submitTopology_args(submitTopology_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
      if (other.is_set_uploadedJarLocation()) {
        this.uploadedJarLocation = other.uploadedJarLocation;
      }
      if (other.is_set_jsonConf()) {
        this.jsonConf = other.jsonConf;
      }
      if (other.is_set_topology()) {
        this.topology = new StormTopology(other.topology);
      }
    }

    public submitTopology_args deepCopy() {
      return new submitTopology_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
      this.uploadedJarLocation = null;
      this.jsonConf = null;
      this.topology = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public String get_uploadedJarLocation() {
      return this.uploadedJarLocation;
    }

    public void set_uploadedJarLocation(String uploadedJarLocation) {
      this.uploadedJarLocation = uploadedJarLocation;
    }

    public void unset_uploadedJarLocation() {
      this.uploadedJarLocation = null;
    }

    /** Returns true if field uploadedJarLocation is set (has been assigned a value) and false otherwise */
    public boolean is_set_uploadedJarLocation() {
      return this.uploadedJarLocation != null;
    }

    public void set_uploadedJarLocation_isSet(boolean value) {
      if (!value) {
        this.uploadedJarLocation = null;
      }
    }

    public String get_jsonConf() {
      return this.jsonConf;
    }

    public void set_jsonConf(String jsonConf) {
      this.jsonConf = jsonConf;
    }

    public void unset_jsonConf() {
      this.jsonConf = null;
    }

    /** Returns true if field jsonConf is set (has been assigned a value) and false otherwise */
    public boolean is_set_jsonConf() {
      return this.jsonConf != null;
    }

    public void set_jsonConf_isSet(boolean value) {
      if (!value) {
        this.jsonConf = null;
      }
    }

    public StormTopology get_topology() {
      return this.topology;
    }

    public void set_topology(StormTopology topology) {
      this.topology = topology;
    }

    public void unset_topology() {
      this.topology = null;
    }

    /** Returns true if field topology is set (has been assigned a value) and false otherwise */
    public boolean is_set_topology() {
      return this.topology != null;
    }

    public void set_topology_isSet(boolean value) {
      if (!value) {
        this.topology = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      case UPLOADED_JAR_LOCATION:
        if (value == null) {
          unset_uploadedJarLocation();
        } else {
          set_uploadedJarLocation((String)value);
        }
        break;

      case JSON_CONF:
        if (value == null) {
          unset_jsonConf();
        } else {
          set_jsonConf((String)value);
        }
        break;

      case TOPOLOGY:
        if (value == null) {
          unset_topology();
        } else {
          set_topology((StormTopology)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      case UPLOADED_JAR_LOCATION:
        return get_uploadedJarLocation();

      case JSON_CONF:
        return get_jsonConf();

      case TOPOLOGY:
        return get_topology();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      case UPLOADED_JAR_LOCATION:
        return is_set_uploadedJarLocation();
      case JSON_CONF:
        return is_set_jsonConf();
      case TOPOLOGY:
        return is_set_topology();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof submitTopology_args)
        return this.equals((submitTopology_args)that);
      return false;
    }

    public boolean equals(submitTopology_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      boolean this_present_uploadedJarLocation = true && this.is_set_uploadedJarLocation();
      boolean that_present_uploadedJarLocation = true && that.is_set_uploadedJarLocation();
      if (this_present_uploadedJarLocation || that_present_uploadedJarLocation) {
        if (!(this_present_uploadedJarLocation && that_present_uploadedJarLocation))
          return false;
        if (!this.uploadedJarLocation.equals(that.uploadedJarLocation))
          return false;
      }

      boolean this_present_jsonConf = true && this.is_set_jsonConf();
      boolean that_present_jsonConf = true && that.is_set_jsonConf();
      if (this_present_jsonConf || that_present_jsonConf) {
        if (!(this_present_jsonConf && that_present_jsonConf))
          return false;
        if (!this.jsonConf.equals(that.jsonConf))
          return false;
      }

      boolean this_present_topology = true && this.is_set_topology();
      boolean that_present_topology = true && that.is_set_topology();
      if (this_present_topology || that_present_topology) {
        if (!(this_present_topology && that_present_topology))
          return false;
        if (!this.topology.equals(that.topology))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      boolean present_uploadedJarLocation = true && (is_set_uploadedJarLocation());
      list.add(present_uploadedJarLocation);
      if (present_uploadedJarLocation)
        list.add(uploadedJarLocation);

      boolean present_jsonConf = true && (is_set_jsonConf());
      list.add(present_jsonConf);
      if (present_jsonConf)
        list.add(jsonConf);

      boolean present_topology = true && (is_set_topology());
      list.add(present_topology);
      if (present_topology)
        list.add(topology);

      return list.hashCode();
    }

    @Override
    public int compareTo(submitTopology_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_uploadedJarLocation()).compareTo(other.is_set_uploadedJarLocation());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_uploadedJarLocation()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.uploadedJarLocation, other.uploadedJarLocation);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_jsonConf()).compareTo(other.is_set_jsonConf());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_jsonConf()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.jsonConf, other.jsonConf);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_topology()).compareTo(other.is_set_topology());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topology()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topology, other.topology);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("submitTopology_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("uploadedJarLocation:");
      if (this.uploadedJarLocation == null) {
        sb.append("null");
      } else {
        sb.append(this.uploadedJarLocation);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("jsonConf:");
      if (this.jsonConf == null) {
        sb.append("null");
      } else {
        sb.append(this.jsonConf);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("topology:");
      if (this.topology == null) {
        sb.append("null");
      } else {
        sb.append(this.topology);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (topology != null) {
        topology.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class submitTopology_argsStandardSchemeFactory implements SchemeFactory {
      public submitTopology_argsStandardScheme getScheme() {
        return new submitTopology_argsStandardScheme();
      }
    }

    private static class submitTopology_argsStandardScheme extends StandardScheme<submitTopology_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, submitTopology_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // UPLOADED_JAR_LOCATION
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.uploadedJarLocation = iprot.readString();
                struct.set_uploadedJarLocation_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // JSON_CONF
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.jsonConf = iprot.readString();
                struct.set_jsonConf_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // TOPOLOGY
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.topology = new StormTopology();
                struct.topology.read(iprot);
                struct.set_topology_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, submitTopology_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        if (struct.uploadedJarLocation != null) {
          oprot.writeFieldBegin(UPLOADED_JAR_LOCATION_FIELD_DESC);
          oprot.writeString(struct.uploadedJarLocation);
          oprot.writeFieldEnd();
        }
        if (struct.jsonConf != null) {
          oprot.writeFieldBegin(JSON_CONF_FIELD_DESC);
          oprot.writeString(struct.jsonConf);
          oprot.writeFieldEnd();
        }
        if (struct.topology != null) {
          oprot.writeFieldBegin(TOPOLOGY_FIELD_DESC);
          struct.topology.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class submitTopology_argsTupleSchemeFactory implements SchemeFactory {
      public submitTopology_argsTupleScheme getScheme() {
        return new submitTopology_argsTupleScheme();
      }
    }

    private static class submitTopology_argsTupleScheme extends TupleScheme<submitTopology_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, submitTopology_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        if (struct.is_set_uploadedJarLocation()) {
          optionals.set(1);
        }
        if (struct.is_set_jsonConf()) {
          optionals.set(2);
        }
        if (struct.is_set_topology()) {
          optionals.set(3);
        }
        oprot.writeBitSet(optionals, 4);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
        if (struct.is_set_uploadedJarLocation()) {
          oprot.writeString(struct.uploadedJarLocation);
        }
        if (struct.is_set_jsonConf()) {
          oprot.writeString(struct.jsonConf);
        }
        if (struct.is_set_topology()) {
          struct.topology.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, submitTopology_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(4);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
        if (incoming.get(1)) {
          struct.uploadedJarLocation = iprot.readString();
          struct.set_uploadedJarLocation_isSet(true);
        }
        if (incoming.get(2)) {
          struct.jsonConf = iprot.readString();
          struct.set_jsonConf_isSet(true);
        }
        if (incoming.get(3)) {
          struct.topology = new StormTopology();
          struct.topology.read(iprot);
          struct.set_topology_isSet(true);
        }
      }
    }

  }

  public static class submitTopology_result implements org.apache.thrift.TBase<submitTopology_result, submitTopology_result._Fields>, java.io.Serializable, Cloneable, Comparable<submitTopology_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("submitTopology_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField ITE_FIELD_DESC = new org.apache.thrift.protocol.TField("ite", org.apache.thrift.protocol.TType.STRUCT, (short)2);
    private static final org.apache.thrift.protocol.TField TAE_FIELD_DESC = new org.apache.thrift.protocol.TField("tae", org.apache.thrift.protocol.TType.STRUCT, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new submitTopology_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new submitTopology_resultTupleSchemeFactory());
    }

    private AlreadyAliveException e; // required
    private InvalidTopologyException ite; // required
    private TopologyAssignException tae; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e"),
      ITE((short)2, "ite"),
      TAE((short)3, "tae");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          case 2: // ITE
            return ITE;
          case 3: // TAE
            return TAE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.ITE, new org.apache.thrift.meta_data.FieldMetaData("ite", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.TAE, new org.apache.thrift.meta_data.FieldMetaData("tae", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(submitTopology_result.class, metaDataMap);
    }

    public submitTopology_result() {
    }

    public submitTopology_result(
      AlreadyAliveException e,
      InvalidTopologyException ite,
      TopologyAssignException tae)
    {
      this();
      this.e = e;
      this.ite = ite;
      this.tae = tae;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public submitTopology_result(submitTopology_result other) {
      if (other.is_set_e()) {
        this.e = new AlreadyAliveException(other.e);
      }
      if (other.is_set_ite()) {
        this.ite = new InvalidTopologyException(other.ite);
      }
      if (other.is_set_tae()) {
        this.tae = new TopologyAssignException(other.tae);
      }
    }

    public submitTopology_result deepCopy() {
      return new submitTopology_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
      this.ite = null;
      this.tae = null;
    }

    public AlreadyAliveException get_e() {
      return this.e;
    }

    public void set_e(AlreadyAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public InvalidTopologyException get_ite() {
      return this.ite;
    }

    public void set_ite(InvalidTopologyException ite) {
      this.ite = ite;
    }

    public void unset_ite() {
      this.ite = null;
    }

    /** Returns true if field ite is set (has been assigned a value) and false otherwise */
    public boolean is_set_ite() {
      return this.ite != null;
    }

    public void set_ite_isSet(boolean value) {
      if (!value) {
        this.ite = null;
      }
    }

    public TopologyAssignException get_tae() {
      return this.tae;
    }

    public void set_tae(TopologyAssignException tae) {
      this.tae = tae;
    }

    public void unset_tae() {
      this.tae = null;
    }

    /** Returns true if field tae is set (has been assigned a value) and false otherwise */
    public boolean is_set_tae() {
      return this.tae != null;
    }

    public void set_tae_isSet(boolean value) {
      if (!value) {
        this.tae = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((AlreadyAliveException)value);
        }
        break;

      case ITE:
        if (value == null) {
          unset_ite();
        } else {
          set_ite((InvalidTopologyException)value);
        }
        break;

      case TAE:
        if (value == null) {
          unset_tae();
        } else {
          set_tae((TopologyAssignException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      case ITE:
        return get_ite();

      case TAE:
        return get_tae();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      case ITE:
        return is_set_ite();
      case TAE:
        return is_set_tae();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof submitTopology_result)
        return this.equals((submitTopology_result)that);
      return false;
    }

    public boolean equals(submitTopology_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      boolean this_present_ite = true && this.is_set_ite();
      boolean that_present_ite = true && that.is_set_ite();
      if (this_present_ite || that_present_ite) {
        if (!(this_present_ite && that_present_ite))
          return false;
        if (!this.ite.equals(that.ite))
          return false;
      }

      boolean this_present_tae = true && this.is_set_tae();
      boolean that_present_tae = true && that.is_set_tae();
      if (this_present_tae || that_present_tae) {
        if (!(this_present_tae && that_present_tae))
          return false;
        if (!this.tae.equals(that.tae))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      boolean present_ite = true && (is_set_ite());
      list.add(present_ite);
      if (present_ite)
        list.add(ite);

      boolean present_tae = true && (is_set_tae());
      list.add(present_tae);
      if (present_tae)
        list.add(tae);

      return list.hashCode();
    }

    @Override
    public int compareTo(submitTopology_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_ite()).compareTo(other.is_set_ite());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_ite()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ite, other.ite);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_tae()).compareTo(other.is_set_tae());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_tae()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tae, other.tae);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("submitTopology_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("ite:");
      if (this.ite == null) {
        sb.append("null");
      } else {
        sb.append(this.ite);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("tae:");
      if (this.tae == null) {
        sb.append("null");
      } else {
        sb.append(this.tae);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class submitTopology_resultStandardSchemeFactory implements SchemeFactory {
      public submitTopology_resultStandardScheme getScheme() {
        return new submitTopology_resultStandardScheme();
      }
    }

    private static class submitTopology_resultStandardScheme extends StandardScheme<submitTopology_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, submitTopology_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new AlreadyAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ITE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.ite = new InvalidTopologyException();
                struct.ite.read(iprot);
                struct.set_ite_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // TAE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.tae = new TopologyAssignException();
                struct.tae.read(iprot);
                struct.set_tae_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, submitTopology_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.ite != null) {
          oprot.writeFieldBegin(ITE_FIELD_DESC);
          struct.ite.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.tae != null) {
          oprot.writeFieldBegin(TAE_FIELD_DESC);
          struct.tae.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class submitTopology_resultTupleSchemeFactory implements SchemeFactory {
      public submitTopology_resultTupleScheme getScheme() {
        return new submitTopology_resultTupleScheme();
      }
    }

    private static class submitTopology_resultTupleScheme extends TupleScheme<submitTopology_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, submitTopology_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        if (struct.is_set_ite()) {
          optionals.set(1);
        }
        if (struct.is_set_tae()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
        if (struct.is_set_ite()) {
          struct.ite.write(oprot);
        }
        if (struct.is_set_tae()) {
          struct.tae.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, submitTopology_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.e = new AlreadyAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
        if (incoming.get(1)) {
          struct.ite = new InvalidTopologyException();
          struct.ite.read(iprot);
          struct.set_ite_isSet(true);
        }
        if (incoming.get(2)) {
          struct.tae = new TopologyAssignException();
          struct.tae.read(iprot);
          struct.set_tae_isSet(true);
        }
      }
    }

  }

  public static class submitTopologyWithOpts_args implements org.apache.thrift.TBase<submitTopologyWithOpts_args, submitTopologyWithOpts_args._Fields>, java.io.Serializable, Cloneable, Comparable<submitTopologyWithOpts_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("submitTopologyWithOpts_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField UPLOADED_JAR_LOCATION_FIELD_DESC = new org.apache.thrift.protocol.TField("uploadedJarLocation", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField JSON_CONF_FIELD_DESC = new org.apache.thrift.protocol.TField("jsonConf", org.apache.thrift.protocol.TType.STRING, (short)3);
    private static final org.apache.thrift.protocol.TField TOPOLOGY_FIELD_DESC = new org.apache.thrift.protocol.TField("topology", org.apache.thrift.protocol.TType.STRUCT, (short)4);
    private static final org.apache.thrift.protocol.TField OPTIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("options", org.apache.thrift.protocol.TType.STRUCT, (short)5);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new submitTopologyWithOpts_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new submitTopologyWithOpts_argsTupleSchemeFactory());
    }

    private String name; // required
    private String uploadedJarLocation; // required
    private String jsonConf; // required
    private StormTopology topology; // required
    private SubmitOptions options; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name"),
      UPLOADED_JAR_LOCATION((short)2, "uploadedJarLocation"),
      JSON_CONF((short)3, "jsonConf"),
      TOPOLOGY((short)4, "topology"),
      OPTIONS((short)5, "options");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          case 2: // UPLOADED_JAR_LOCATION
            return UPLOADED_JAR_LOCATION;
          case 3: // JSON_CONF
            return JSON_CONF;
          case 4: // TOPOLOGY
            return TOPOLOGY;
          case 5: // OPTIONS
            return OPTIONS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.UPLOADED_JAR_LOCATION, new org.apache.thrift.meta_data.FieldMetaData("uploadedJarLocation", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.JSON_CONF, new org.apache.thrift.meta_data.FieldMetaData("jsonConf", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.TOPOLOGY, new org.apache.thrift.meta_data.FieldMetaData("topology", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, StormTopology.class)));
      tmpMap.put(_Fields.OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("options", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, SubmitOptions.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(submitTopologyWithOpts_args.class, metaDataMap);
    }

    public submitTopologyWithOpts_args() {
    }

    public submitTopologyWithOpts_args(
      String name,
      String uploadedJarLocation,
      String jsonConf,
      StormTopology topology,
      SubmitOptions options)
    {
      this();
      this.name = name;
      this.uploadedJarLocation = uploadedJarLocation;
      this.jsonConf = jsonConf;
      this.topology = topology;
      this.options = options;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public submitTopologyWithOpts_args(submitTopologyWithOpts_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
      if (other.is_set_uploadedJarLocation()) {
        this.uploadedJarLocation = other.uploadedJarLocation;
      }
      if (other.is_set_jsonConf()) {
        this.jsonConf = other.jsonConf;
      }
      if (other.is_set_topology()) {
        this.topology = new StormTopology(other.topology);
      }
      if (other.is_set_options()) {
        this.options = new SubmitOptions(other.options);
      }
    }

    public submitTopologyWithOpts_args deepCopy() {
      return new submitTopologyWithOpts_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
      this.uploadedJarLocation = null;
      this.jsonConf = null;
      this.topology = null;
      this.options = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public String get_uploadedJarLocation() {
      return this.uploadedJarLocation;
    }

    public void set_uploadedJarLocation(String uploadedJarLocation) {
      this.uploadedJarLocation = uploadedJarLocation;
    }

    public void unset_uploadedJarLocation() {
      this.uploadedJarLocation = null;
    }

    /** Returns true if field uploadedJarLocation is set (has been assigned a value) and false otherwise */
    public boolean is_set_uploadedJarLocation() {
      return this.uploadedJarLocation != null;
    }

    public void set_uploadedJarLocation_isSet(boolean value) {
      if (!value) {
        this.uploadedJarLocation = null;
      }
    }

    public String get_jsonConf() {
      return this.jsonConf;
    }

    public void set_jsonConf(String jsonConf) {
      this.jsonConf = jsonConf;
    }

    public void unset_jsonConf() {
      this.jsonConf = null;
    }

    /** Returns true if field jsonConf is set (has been assigned a value) and false otherwise */
    public boolean is_set_jsonConf() {
      return this.jsonConf != null;
    }

    public void set_jsonConf_isSet(boolean value) {
      if (!value) {
        this.jsonConf = null;
      }
    }

    public StormTopology get_topology() {
      return this.topology;
    }

    public void set_topology(StormTopology topology) {
      this.topology = topology;
    }

    public void unset_topology() {
      this.topology = null;
    }

    /** Returns true if field topology is set (has been assigned a value) and false otherwise */
    public boolean is_set_topology() {
      return this.topology != null;
    }

    public void set_topology_isSet(boolean value) {
      if (!value) {
        this.topology = null;
      }
    }

    public SubmitOptions get_options() {
      return this.options;
    }

    public void set_options(SubmitOptions options) {
      this.options = options;
    }

    public void unset_options() {
      this.options = null;
    }

    /** Returns true if field options is set (has been assigned a value) and false otherwise */
    public boolean is_set_options() {
      return this.options != null;
    }

    public void set_options_isSet(boolean value) {
      if (!value) {
        this.options = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      case UPLOADED_JAR_LOCATION:
        if (value == null) {
          unset_uploadedJarLocation();
        } else {
          set_uploadedJarLocation((String)value);
        }
        break;

      case JSON_CONF:
        if (value == null) {
          unset_jsonConf();
        } else {
          set_jsonConf((String)value);
        }
        break;

      case TOPOLOGY:
        if (value == null) {
          unset_topology();
        } else {
          set_topology((StormTopology)value);
        }
        break;

      case OPTIONS:
        if (value == null) {
          unset_options();
        } else {
          set_options((SubmitOptions)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      case UPLOADED_JAR_LOCATION:
        return get_uploadedJarLocation();

      case JSON_CONF:
        return get_jsonConf();

      case TOPOLOGY:
        return get_topology();

      case OPTIONS:
        return get_options();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      case UPLOADED_JAR_LOCATION:
        return is_set_uploadedJarLocation();
      case JSON_CONF:
        return is_set_jsonConf();
      case TOPOLOGY:
        return is_set_topology();
      case OPTIONS:
        return is_set_options();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof submitTopologyWithOpts_args)
        return this.equals((submitTopologyWithOpts_args)that);
      return false;
    }

    public boolean equals(submitTopologyWithOpts_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      boolean this_present_uploadedJarLocation = true && this.is_set_uploadedJarLocation();
      boolean that_present_uploadedJarLocation = true && that.is_set_uploadedJarLocation();
      if (this_present_uploadedJarLocation || that_present_uploadedJarLocation) {
        if (!(this_present_uploadedJarLocation && that_present_uploadedJarLocation))
          return false;
        if (!this.uploadedJarLocation.equals(that.uploadedJarLocation))
          return false;
      }

      boolean this_present_jsonConf = true && this.is_set_jsonConf();
      boolean that_present_jsonConf = true && that.is_set_jsonConf();
      if (this_present_jsonConf || that_present_jsonConf) {
        if (!(this_present_jsonConf && that_present_jsonConf))
          return false;
        if (!this.jsonConf.equals(that.jsonConf))
          return false;
      }

      boolean this_present_topology = true && this.is_set_topology();
      boolean that_present_topology = true && that.is_set_topology();
      if (this_present_topology || that_present_topology) {
        if (!(this_present_topology && that_present_topology))
          return false;
        if (!this.topology.equals(that.topology))
          return false;
      }

      boolean this_present_options = true && this.is_set_options();
      boolean that_present_options = true && that.is_set_options();
      if (this_present_options || that_present_options) {
        if (!(this_present_options && that_present_options))
          return false;
        if (!this.options.equals(that.options))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      boolean present_uploadedJarLocation = true && (is_set_uploadedJarLocation());
      list.add(present_uploadedJarLocation);
      if (present_uploadedJarLocation)
        list.add(uploadedJarLocation);

      boolean present_jsonConf = true && (is_set_jsonConf());
      list.add(present_jsonConf);
      if (present_jsonConf)
        list.add(jsonConf);

      boolean present_topology = true && (is_set_topology());
      list.add(present_topology);
      if (present_topology)
        list.add(topology);

      boolean present_options = true && (is_set_options());
      list.add(present_options);
      if (present_options)
        list.add(options);

      return list.hashCode();
    }

    @Override
    public int compareTo(submitTopologyWithOpts_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_uploadedJarLocation()).compareTo(other.is_set_uploadedJarLocation());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_uploadedJarLocation()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.uploadedJarLocation, other.uploadedJarLocation);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_jsonConf()).compareTo(other.is_set_jsonConf());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_jsonConf()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.jsonConf, other.jsonConf);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_topology()).compareTo(other.is_set_topology());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topology()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topology, other.topology);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_options()).compareTo(other.is_set_options());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_options()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.options, other.options);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("submitTopologyWithOpts_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("uploadedJarLocation:");
      if (this.uploadedJarLocation == null) {
        sb.append("null");
      } else {
        sb.append(this.uploadedJarLocation);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("jsonConf:");
      if (this.jsonConf == null) {
        sb.append("null");
      } else {
        sb.append(this.jsonConf);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("topology:");
      if (this.topology == null) {
        sb.append("null");
      } else {
        sb.append(this.topology);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("options:");
      if (this.options == null) {
        sb.append("null");
      } else {
        sb.append(this.options);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (topology != null) {
        topology.validate();
      }
      if (options != null) {
        options.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class submitTopologyWithOpts_argsStandardSchemeFactory implements SchemeFactory {
      public submitTopologyWithOpts_argsStandardScheme getScheme() {
        return new submitTopologyWithOpts_argsStandardScheme();
      }
    }

    private static class submitTopologyWithOpts_argsStandardScheme extends StandardScheme<submitTopologyWithOpts_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, submitTopologyWithOpts_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // UPLOADED_JAR_LOCATION
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.uploadedJarLocation = iprot.readString();
                struct.set_uploadedJarLocation_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // JSON_CONF
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.jsonConf = iprot.readString();
                struct.set_jsonConf_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // TOPOLOGY
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.topology = new StormTopology();
                struct.topology.read(iprot);
                struct.set_topology_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 5: // OPTIONS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.options = new SubmitOptions();
                struct.options.read(iprot);
                struct.set_options_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, submitTopologyWithOpts_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        if (struct.uploadedJarLocation != null) {
          oprot.writeFieldBegin(UPLOADED_JAR_LOCATION_FIELD_DESC);
          oprot.writeString(struct.uploadedJarLocation);
          oprot.writeFieldEnd();
        }
        if (struct.jsonConf != null) {
          oprot.writeFieldBegin(JSON_CONF_FIELD_DESC);
          oprot.writeString(struct.jsonConf);
          oprot.writeFieldEnd();
        }
        if (struct.topology != null) {
          oprot.writeFieldBegin(TOPOLOGY_FIELD_DESC);
          struct.topology.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.options != null) {
          oprot.writeFieldBegin(OPTIONS_FIELD_DESC);
          struct.options.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class submitTopologyWithOpts_argsTupleSchemeFactory implements SchemeFactory {
      public submitTopologyWithOpts_argsTupleScheme getScheme() {
        return new submitTopologyWithOpts_argsTupleScheme();
      }
    }

    private static class submitTopologyWithOpts_argsTupleScheme extends TupleScheme<submitTopologyWithOpts_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, submitTopologyWithOpts_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        if (struct.is_set_uploadedJarLocation()) {
          optionals.set(1);
        }
        if (struct.is_set_jsonConf()) {
          optionals.set(2);
        }
        if (struct.is_set_topology()) {
          optionals.set(3);
        }
        if (struct.is_set_options()) {
          optionals.set(4);
        }
        oprot.writeBitSet(optionals, 5);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
        if (struct.is_set_uploadedJarLocation()) {
          oprot.writeString(struct.uploadedJarLocation);
        }
        if (struct.is_set_jsonConf()) {
          oprot.writeString(struct.jsonConf);
        }
        if (struct.is_set_topology()) {
          struct.topology.write(oprot);
        }
        if (struct.is_set_options()) {
          struct.options.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, submitTopologyWithOpts_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(5);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
        if (incoming.get(1)) {
          struct.uploadedJarLocation = iprot.readString();
          struct.set_uploadedJarLocation_isSet(true);
        }
        if (incoming.get(2)) {
          struct.jsonConf = iprot.readString();
          struct.set_jsonConf_isSet(true);
        }
        if (incoming.get(3)) {
          struct.topology = new StormTopology();
          struct.topology.read(iprot);
          struct.set_topology_isSet(true);
        }
        if (incoming.get(4)) {
          struct.options = new SubmitOptions();
          struct.options.read(iprot);
          struct.set_options_isSet(true);
        }
      }
    }

  }

  public static class submitTopologyWithOpts_result implements org.apache.thrift.TBase<submitTopologyWithOpts_result, submitTopologyWithOpts_result._Fields>, java.io.Serializable, Cloneable, Comparable<submitTopologyWithOpts_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("submitTopologyWithOpts_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField ITE_FIELD_DESC = new org.apache.thrift.protocol.TField("ite", org.apache.thrift.protocol.TType.STRUCT, (short)2);
    private static final org.apache.thrift.protocol.TField TAE_FIELD_DESC = new org.apache.thrift.protocol.TField("tae", org.apache.thrift.protocol.TType.STRUCT, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new submitTopologyWithOpts_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new submitTopologyWithOpts_resultTupleSchemeFactory());
    }

    private AlreadyAliveException e; // required
    private InvalidTopologyException ite; // required
    private TopologyAssignException tae; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e"),
      ITE((short)2, "ite"),
      TAE((short)3, "tae");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          case 2: // ITE
            return ITE;
          case 3: // TAE
            return TAE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.ITE, new org.apache.thrift.meta_data.FieldMetaData("ite", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.TAE, new org.apache.thrift.meta_data.FieldMetaData("tae", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(submitTopologyWithOpts_result.class, metaDataMap);
    }

    public submitTopologyWithOpts_result() {
    }

    public submitTopologyWithOpts_result(
      AlreadyAliveException e,
      InvalidTopologyException ite,
      TopologyAssignException tae)
    {
      this();
      this.e = e;
      this.ite = ite;
      this.tae = tae;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public submitTopologyWithOpts_result(submitTopologyWithOpts_result other) {
      if (other.is_set_e()) {
        this.e = new AlreadyAliveException(other.e);
      }
      if (other.is_set_ite()) {
        this.ite = new InvalidTopologyException(other.ite);
      }
      if (other.is_set_tae()) {
        this.tae = new TopologyAssignException(other.tae);
      }
    }

    public submitTopologyWithOpts_result deepCopy() {
      return new submitTopologyWithOpts_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
      this.ite = null;
      this.tae = null;
    }

    public AlreadyAliveException get_e() {
      return this.e;
    }

    public void set_e(AlreadyAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public InvalidTopologyException get_ite() {
      return this.ite;
    }

    public void set_ite(InvalidTopologyException ite) {
      this.ite = ite;
    }

    public void unset_ite() {
      this.ite = null;
    }

    /** Returns true if field ite is set (has been assigned a value) and false otherwise */
    public boolean is_set_ite() {
      return this.ite != null;
    }

    public void set_ite_isSet(boolean value) {
      if (!value) {
        this.ite = null;
      }
    }

    public TopologyAssignException get_tae() {
      return this.tae;
    }

    public void set_tae(TopologyAssignException tae) {
      this.tae = tae;
    }

    public void unset_tae() {
      this.tae = null;
    }

    /** Returns true if field tae is set (has been assigned a value) and false otherwise */
    public boolean is_set_tae() {
      return this.tae != null;
    }

    public void set_tae_isSet(boolean value) {
      if (!value) {
        this.tae = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((AlreadyAliveException)value);
        }
        break;

      case ITE:
        if (value == null) {
          unset_ite();
        } else {
          set_ite((InvalidTopologyException)value);
        }
        break;

      case TAE:
        if (value == null) {
          unset_tae();
        } else {
          set_tae((TopologyAssignException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      case ITE:
        return get_ite();

      case TAE:
        return get_tae();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      case ITE:
        return is_set_ite();
      case TAE:
        return is_set_tae();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof submitTopologyWithOpts_result)
        return this.equals((submitTopologyWithOpts_result)that);
      return false;
    }

    public boolean equals(submitTopologyWithOpts_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      boolean this_present_ite = true && this.is_set_ite();
      boolean that_present_ite = true && that.is_set_ite();
      if (this_present_ite || that_present_ite) {
        if (!(this_present_ite && that_present_ite))
          return false;
        if (!this.ite.equals(that.ite))
          return false;
      }

      boolean this_present_tae = true && this.is_set_tae();
      boolean that_present_tae = true && that.is_set_tae();
      if (this_present_tae || that_present_tae) {
        if (!(this_present_tae && that_present_tae))
          return false;
        if (!this.tae.equals(that.tae))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      boolean present_ite = true && (is_set_ite());
      list.add(present_ite);
      if (present_ite)
        list.add(ite);

      boolean present_tae = true && (is_set_tae());
      list.add(present_tae);
      if (present_tae)
        list.add(tae);

      return list.hashCode();
    }

    @Override
    public int compareTo(submitTopologyWithOpts_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_ite()).compareTo(other.is_set_ite());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_ite()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ite, other.ite);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_tae()).compareTo(other.is_set_tae());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_tae()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tae, other.tae);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("submitTopologyWithOpts_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("ite:");
      if (this.ite == null) {
        sb.append("null");
      } else {
        sb.append(this.ite);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("tae:");
      if (this.tae == null) {
        sb.append("null");
      } else {
        sb.append(this.tae);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class submitTopologyWithOpts_resultStandardSchemeFactory implements SchemeFactory {
      public submitTopologyWithOpts_resultStandardScheme getScheme() {
        return new submitTopologyWithOpts_resultStandardScheme();
      }
    }

    private static class submitTopologyWithOpts_resultStandardScheme extends StandardScheme<submitTopologyWithOpts_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, submitTopologyWithOpts_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new AlreadyAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ITE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.ite = new InvalidTopologyException();
                struct.ite.read(iprot);
                struct.set_ite_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // TAE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.tae = new TopologyAssignException();
                struct.tae.read(iprot);
                struct.set_tae_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, submitTopologyWithOpts_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.ite != null) {
          oprot.writeFieldBegin(ITE_FIELD_DESC);
          struct.ite.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.tae != null) {
          oprot.writeFieldBegin(TAE_FIELD_DESC);
          struct.tae.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class submitTopologyWithOpts_resultTupleSchemeFactory implements SchemeFactory {
      public submitTopologyWithOpts_resultTupleScheme getScheme() {
        return new submitTopologyWithOpts_resultTupleScheme();
      }
    }

    private static class submitTopologyWithOpts_resultTupleScheme extends TupleScheme<submitTopologyWithOpts_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, submitTopologyWithOpts_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        if (struct.is_set_ite()) {
          optionals.set(1);
        }
        if (struct.is_set_tae()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
        if (struct.is_set_ite()) {
          struct.ite.write(oprot);
        }
        if (struct.is_set_tae()) {
          struct.tae.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, submitTopologyWithOpts_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.e = new AlreadyAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
        if (incoming.get(1)) {
          struct.ite = new InvalidTopologyException();
          struct.ite.read(iprot);
          struct.set_ite_isSet(true);
        }
        if (incoming.get(2)) {
          struct.tae = new TopologyAssignException();
          struct.tae.read(iprot);
          struct.set_tae_isSet(true);
        }
      }
    }

  }

  public static class killTopology_args implements org.apache.thrift.TBase<killTopology_args, killTopology_args._Fields>, java.io.Serializable, Cloneable, Comparable<killTopology_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("killTopology_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new killTopology_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new killTopology_argsTupleSchemeFactory());
    }

    private String name; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(killTopology_args.class, metaDataMap);
    }

    public killTopology_args() {
    }

    public killTopology_args(
      String name)
    {
      this();
      this.name = name;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public killTopology_args(killTopology_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
    }

    public killTopology_args deepCopy() {
      return new killTopology_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof killTopology_args)
        return this.equals((killTopology_args)that);
      return false;
    }

    public boolean equals(killTopology_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      return list.hashCode();
    }

    @Override
    public int compareTo(killTopology_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("killTopology_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class killTopology_argsStandardSchemeFactory implements SchemeFactory {
      public killTopology_argsStandardScheme getScheme() {
        return new killTopology_argsStandardScheme();
      }
    }

    private static class killTopology_argsStandardScheme extends StandardScheme<killTopology_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, killTopology_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, killTopology_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class killTopology_argsTupleSchemeFactory implements SchemeFactory {
      public killTopology_argsTupleScheme getScheme() {
        return new killTopology_argsTupleScheme();
      }
    }

    private static class killTopology_argsTupleScheme extends TupleScheme<killTopology_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, killTopology_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, killTopology_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
      }
    }

  }

  public static class killTopology_result implements org.apache.thrift.TBase<killTopology_result, killTopology_result._Fields>, java.io.Serializable, Cloneable, Comparable<killTopology_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("killTopology_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new killTopology_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new killTopology_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(killTopology_result.class, metaDataMap);
    }

    public killTopology_result() {
    }

    public killTopology_result(
      NotAliveException e)
    {
      this();
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public killTopology_result(killTopology_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public killTopology_result deepCopy() {
      return new killTopology_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof killTopology_result)
        return this.equals((killTopology_result)that);
      return false;
    }

    public boolean equals(killTopology_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(killTopology_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("killTopology_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class killTopology_resultStandardSchemeFactory implements SchemeFactory {
      public killTopology_resultStandardScheme getScheme() {
        return new killTopology_resultStandardScheme();
      }
    }

    private static class killTopology_resultStandardScheme extends StandardScheme<killTopology_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, killTopology_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, killTopology_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class killTopology_resultTupleSchemeFactory implements SchemeFactory {
      public killTopology_resultTupleScheme getScheme() {
        return new killTopology_resultTupleScheme();
      }
    }

    private static class killTopology_resultTupleScheme extends TupleScheme<killTopology_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, killTopology_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, killTopology_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class killTopologyWithOpts_args implements org.apache.thrift.TBase<killTopologyWithOpts_args, killTopologyWithOpts_args._Fields>, java.io.Serializable, Cloneable, Comparable<killTopologyWithOpts_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("killTopologyWithOpts_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField OPTIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("options", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new killTopologyWithOpts_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new killTopologyWithOpts_argsTupleSchemeFactory());
    }

    private String name; // required
    private KillOptions options; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name"),
      OPTIONS((short)2, "options");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          case 2: // OPTIONS
            return OPTIONS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("options", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, KillOptions.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(killTopologyWithOpts_args.class, metaDataMap);
    }

    public killTopologyWithOpts_args() {
    }

    public killTopologyWithOpts_args(
      String name,
      KillOptions options)
    {
      this();
      this.name = name;
      this.options = options;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public killTopologyWithOpts_args(killTopologyWithOpts_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
      if (other.is_set_options()) {
        this.options = new KillOptions(other.options);
      }
    }

    public killTopologyWithOpts_args deepCopy() {
      return new killTopologyWithOpts_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
      this.options = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public KillOptions get_options() {
      return this.options;
    }

    public void set_options(KillOptions options) {
      this.options = options;
    }

    public void unset_options() {
      this.options = null;
    }

    /** Returns true if field options is set (has been assigned a value) and false otherwise */
    public boolean is_set_options() {
      return this.options != null;
    }

    public void set_options_isSet(boolean value) {
      if (!value) {
        this.options = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      case OPTIONS:
        if (value == null) {
          unset_options();
        } else {
          set_options((KillOptions)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      case OPTIONS:
        return get_options();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      case OPTIONS:
        return is_set_options();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof killTopologyWithOpts_args)
        return this.equals((killTopologyWithOpts_args)that);
      return false;
    }

    public boolean equals(killTopologyWithOpts_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      boolean this_present_options = true && this.is_set_options();
      boolean that_present_options = true && that.is_set_options();
      if (this_present_options || that_present_options) {
        if (!(this_present_options && that_present_options))
          return false;
        if (!this.options.equals(that.options))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      boolean present_options = true && (is_set_options());
      list.add(present_options);
      if (present_options)
        list.add(options);

      return list.hashCode();
    }

    @Override
    public int compareTo(killTopologyWithOpts_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_options()).compareTo(other.is_set_options());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_options()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.options, other.options);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("killTopologyWithOpts_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("options:");
      if (this.options == null) {
        sb.append("null");
      } else {
        sb.append(this.options);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (options != null) {
        options.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class killTopologyWithOpts_argsStandardSchemeFactory implements SchemeFactory {
      public killTopologyWithOpts_argsStandardScheme getScheme() {
        return new killTopologyWithOpts_argsStandardScheme();
      }
    }

    private static class killTopologyWithOpts_argsStandardScheme extends StandardScheme<killTopologyWithOpts_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, killTopologyWithOpts_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // OPTIONS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.options = new KillOptions();
                struct.options.read(iprot);
                struct.set_options_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, killTopologyWithOpts_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        if (struct.options != null) {
          oprot.writeFieldBegin(OPTIONS_FIELD_DESC);
          struct.options.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class killTopologyWithOpts_argsTupleSchemeFactory implements SchemeFactory {
      public killTopologyWithOpts_argsTupleScheme getScheme() {
        return new killTopologyWithOpts_argsTupleScheme();
      }
    }

    private static class killTopologyWithOpts_argsTupleScheme extends TupleScheme<killTopologyWithOpts_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, killTopologyWithOpts_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        if (struct.is_set_options()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
        if (struct.is_set_options()) {
          struct.options.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, killTopologyWithOpts_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
        if (incoming.get(1)) {
          struct.options = new KillOptions();
          struct.options.read(iprot);
          struct.set_options_isSet(true);
        }
      }
    }

  }

  public static class killTopologyWithOpts_result implements org.apache.thrift.TBase<killTopologyWithOpts_result, killTopologyWithOpts_result._Fields>, java.io.Serializable, Cloneable, Comparable<killTopologyWithOpts_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("killTopologyWithOpts_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new killTopologyWithOpts_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new killTopologyWithOpts_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(killTopologyWithOpts_result.class, metaDataMap);
    }

    public killTopologyWithOpts_result() {
    }

    public killTopologyWithOpts_result(
      NotAliveException e)
    {
      this();
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public killTopologyWithOpts_result(killTopologyWithOpts_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public killTopologyWithOpts_result deepCopy() {
      return new killTopologyWithOpts_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof killTopologyWithOpts_result)
        return this.equals((killTopologyWithOpts_result)that);
      return false;
    }

    public boolean equals(killTopologyWithOpts_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(killTopologyWithOpts_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("killTopologyWithOpts_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class killTopologyWithOpts_resultStandardSchemeFactory implements SchemeFactory {
      public killTopologyWithOpts_resultStandardScheme getScheme() {
        return new killTopologyWithOpts_resultStandardScheme();
      }
    }

    private static class killTopologyWithOpts_resultStandardScheme extends StandardScheme<killTopologyWithOpts_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, killTopologyWithOpts_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, killTopologyWithOpts_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class killTopologyWithOpts_resultTupleSchemeFactory implements SchemeFactory {
      public killTopologyWithOpts_resultTupleScheme getScheme() {
        return new killTopologyWithOpts_resultTupleScheme();
      }
    }

    private static class killTopologyWithOpts_resultTupleScheme extends TupleScheme<killTopologyWithOpts_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, killTopologyWithOpts_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, killTopologyWithOpts_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class activate_args implements org.apache.thrift.TBase<activate_args, activate_args._Fields>, java.io.Serializable, Cloneable, Comparable<activate_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("activate_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new activate_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new activate_argsTupleSchemeFactory());
    }

    private String name; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(activate_args.class, metaDataMap);
    }

    public activate_args() {
    }

    public activate_args(
      String name)
    {
      this();
      this.name = name;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public activate_args(activate_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
    }

    public activate_args deepCopy() {
      return new activate_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof activate_args)
        return this.equals((activate_args)that);
      return false;
    }

    public boolean equals(activate_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      return list.hashCode();
    }

    @Override
    public int compareTo(activate_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("activate_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class activate_argsStandardSchemeFactory implements SchemeFactory {
      public activate_argsStandardScheme getScheme() {
        return new activate_argsStandardScheme();
      }
    }

    private static class activate_argsStandardScheme extends StandardScheme<activate_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, activate_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, activate_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class activate_argsTupleSchemeFactory implements SchemeFactory {
      public activate_argsTupleScheme getScheme() {
        return new activate_argsTupleScheme();
      }
    }

    private static class activate_argsTupleScheme extends TupleScheme<activate_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, activate_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, activate_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
      }
    }

  }

  public static class activate_result implements org.apache.thrift.TBase<activate_result, activate_result._Fields>, java.io.Serializable, Cloneable, Comparable<activate_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("activate_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new activate_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new activate_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(activate_result.class, metaDataMap);
    }

    public activate_result() {
    }

    public activate_result(
      NotAliveException e)
    {
      this();
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public activate_result(activate_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public activate_result deepCopy() {
      return new activate_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof activate_result)
        return this.equals((activate_result)that);
      return false;
    }

    public boolean equals(activate_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(activate_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("activate_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class activate_resultStandardSchemeFactory implements SchemeFactory {
      public activate_resultStandardScheme getScheme() {
        return new activate_resultStandardScheme();
      }
    }

    private static class activate_resultStandardScheme extends StandardScheme<activate_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, activate_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, activate_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class activate_resultTupleSchemeFactory implements SchemeFactory {
      public activate_resultTupleScheme getScheme() {
        return new activate_resultTupleScheme();
      }
    }

    private static class activate_resultTupleScheme extends TupleScheme<activate_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, activate_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, activate_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class deactivate_args implements org.apache.thrift.TBase<deactivate_args, deactivate_args._Fields>, java.io.Serializable, Cloneable, Comparable<deactivate_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deactivate_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deactivate_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deactivate_argsTupleSchemeFactory());
    }

    private String name; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deactivate_args.class, metaDataMap);
    }

    public deactivate_args() {
    }

    public deactivate_args(
      String name)
    {
      this();
      this.name = name;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deactivate_args(deactivate_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
    }

    public deactivate_args deepCopy() {
      return new deactivate_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deactivate_args)
        return this.equals((deactivate_args)that);
      return false;
    }

    public boolean equals(deactivate_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      return list.hashCode();
    }

    @Override
    public int compareTo(deactivate_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deactivate_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deactivate_argsStandardSchemeFactory implements SchemeFactory {
      public deactivate_argsStandardScheme getScheme() {
        return new deactivate_argsStandardScheme();
      }
    }

    private static class deactivate_argsStandardScheme extends StandardScheme<deactivate_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deactivate_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deactivate_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deactivate_argsTupleSchemeFactory implements SchemeFactory {
      public deactivate_argsTupleScheme getScheme() {
        return new deactivate_argsTupleScheme();
      }
    }

    private static class deactivate_argsTupleScheme extends TupleScheme<deactivate_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deactivate_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deactivate_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
      }
    }

  }

  public static class deactivate_result implements org.apache.thrift.TBase<deactivate_result, deactivate_result._Fields>, java.io.Serializable, Cloneable, Comparable<deactivate_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deactivate_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deactivate_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deactivate_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deactivate_result.class, metaDataMap);
    }

    public deactivate_result() {
    }

    public deactivate_result(
      NotAliveException e)
    {
      this();
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deactivate_result(deactivate_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public deactivate_result deepCopy() {
      return new deactivate_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deactivate_result)
        return this.equals((deactivate_result)that);
      return false;
    }

    public boolean equals(deactivate_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(deactivate_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deactivate_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deactivate_resultStandardSchemeFactory implements SchemeFactory {
      public deactivate_resultStandardScheme getScheme() {
        return new deactivate_resultStandardScheme();
      }
    }

    private static class deactivate_resultStandardScheme extends StandardScheme<deactivate_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deactivate_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deactivate_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deactivate_resultTupleSchemeFactory implements SchemeFactory {
      public deactivate_resultTupleScheme getScheme() {
        return new deactivate_resultTupleScheme();
      }
    }

    private static class deactivate_resultTupleScheme extends TupleScheme<deactivate_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deactivate_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deactivate_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class rebalance_args implements org.apache.thrift.TBase<rebalance_args, rebalance_args._Fields>, java.io.Serializable, Cloneable, Comparable<rebalance_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("rebalance_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField OPTIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("options", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new rebalance_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new rebalance_argsTupleSchemeFactory());
    }

    private String name; // required
    private RebalanceOptions options; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name"),
      OPTIONS((short)2, "options");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          case 2: // OPTIONS
            return OPTIONS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("options", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, RebalanceOptions.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(rebalance_args.class, metaDataMap);
    }

    public rebalance_args() {
    }

    public rebalance_args(
      String name,
      RebalanceOptions options)
    {
      this();
      this.name = name;
      this.options = options;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public rebalance_args(rebalance_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
      if (other.is_set_options()) {
        this.options = new RebalanceOptions(other.options);
      }
    }

    public rebalance_args deepCopy() {
      return new rebalance_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
      this.options = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public RebalanceOptions get_options() {
      return this.options;
    }

    public void set_options(RebalanceOptions options) {
      this.options = options;
    }

    public void unset_options() {
      this.options = null;
    }

    /** Returns true if field options is set (has been assigned a value) and false otherwise */
    public boolean is_set_options() {
      return this.options != null;
    }

    public void set_options_isSet(boolean value) {
      if (!value) {
        this.options = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      case OPTIONS:
        if (value == null) {
          unset_options();
        } else {
          set_options((RebalanceOptions)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      case OPTIONS:
        return get_options();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      case OPTIONS:
        return is_set_options();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof rebalance_args)
        return this.equals((rebalance_args)that);
      return false;
    }

    public boolean equals(rebalance_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      boolean this_present_options = true && this.is_set_options();
      boolean that_present_options = true && that.is_set_options();
      if (this_present_options || that_present_options) {
        if (!(this_present_options && that_present_options))
          return false;
        if (!this.options.equals(that.options))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      boolean present_options = true && (is_set_options());
      list.add(present_options);
      if (present_options)
        list.add(options);

      return list.hashCode();
    }

    @Override
    public int compareTo(rebalance_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_options()).compareTo(other.is_set_options());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_options()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.options, other.options);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("rebalance_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("options:");
      if (this.options == null) {
        sb.append("null");
      } else {
        sb.append(this.options);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (options != null) {
        options.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class rebalance_argsStandardSchemeFactory implements SchemeFactory {
      public rebalance_argsStandardScheme getScheme() {
        return new rebalance_argsStandardScheme();
      }
    }

    private static class rebalance_argsStandardScheme extends StandardScheme<rebalance_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, rebalance_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // OPTIONS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.options = new RebalanceOptions();
                struct.options.read(iprot);
                struct.set_options_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, rebalance_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        if (struct.options != null) {
          oprot.writeFieldBegin(OPTIONS_FIELD_DESC);
          struct.options.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class rebalance_argsTupleSchemeFactory implements SchemeFactory {
      public rebalance_argsTupleScheme getScheme() {
        return new rebalance_argsTupleScheme();
      }
    }

    private static class rebalance_argsTupleScheme extends TupleScheme<rebalance_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, rebalance_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        if (struct.is_set_options()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
        if (struct.is_set_options()) {
          struct.options.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, rebalance_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
        if (incoming.get(1)) {
          struct.options = new RebalanceOptions();
          struct.options.read(iprot);
          struct.set_options_isSet(true);
        }
      }
    }

  }

  public static class rebalance_result implements org.apache.thrift.TBase<rebalance_result, rebalance_result._Fields>, java.io.Serializable, Cloneable, Comparable<rebalance_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("rebalance_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField ITE_FIELD_DESC = new org.apache.thrift.protocol.TField("ite", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new rebalance_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new rebalance_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required
    private InvalidTopologyException ite; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e"),
      ITE((short)2, "ite");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          case 2: // ITE
            return ITE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.ITE, new org.apache.thrift.meta_data.FieldMetaData("ite", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(rebalance_result.class, metaDataMap);
    }

    public rebalance_result() {
    }

    public rebalance_result(
      NotAliveException e,
      InvalidTopologyException ite)
    {
      this();
      this.e = e;
      this.ite = ite;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public rebalance_result(rebalance_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
      if (other.is_set_ite()) {
        this.ite = new InvalidTopologyException(other.ite);
      }
    }

    public rebalance_result deepCopy() {
      return new rebalance_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
      this.ite = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public InvalidTopologyException get_ite() {
      return this.ite;
    }

    public void set_ite(InvalidTopologyException ite) {
      this.ite = ite;
    }

    public void unset_ite() {
      this.ite = null;
    }

    /** Returns true if field ite is set (has been assigned a value) and false otherwise */
    public boolean is_set_ite() {
      return this.ite != null;
    }

    public void set_ite_isSet(boolean value) {
      if (!value) {
        this.ite = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      case ITE:
        if (value == null) {
          unset_ite();
        } else {
          set_ite((InvalidTopologyException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      case ITE:
        return get_ite();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      case ITE:
        return is_set_ite();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof rebalance_result)
        return this.equals((rebalance_result)that);
      return false;
    }

    public boolean equals(rebalance_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      boolean this_present_ite = true && this.is_set_ite();
      boolean that_present_ite = true && that.is_set_ite();
      if (this_present_ite || that_present_ite) {
        if (!(this_present_ite && that_present_ite))
          return false;
        if (!this.ite.equals(that.ite))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      boolean present_ite = true && (is_set_ite());
      list.add(present_ite);
      if (present_ite)
        list.add(ite);

      return list.hashCode();
    }

    @Override
    public int compareTo(rebalance_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_ite()).compareTo(other.is_set_ite());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_ite()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ite, other.ite);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("rebalance_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("ite:");
      if (this.ite == null) {
        sb.append("null");
      } else {
        sb.append(this.ite);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class rebalance_resultStandardSchemeFactory implements SchemeFactory {
      public rebalance_resultStandardScheme getScheme() {
        return new rebalance_resultStandardScheme();
      }
    }

    private static class rebalance_resultStandardScheme extends StandardScheme<rebalance_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, rebalance_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ITE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.ite = new InvalidTopologyException();
                struct.ite.read(iprot);
                struct.set_ite_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, rebalance_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.ite != null) {
          oprot.writeFieldBegin(ITE_FIELD_DESC);
          struct.ite.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class rebalance_resultTupleSchemeFactory implements SchemeFactory {
      public rebalance_resultTupleScheme getScheme() {
        return new rebalance_resultTupleScheme();
      }
    }

    private static class rebalance_resultTupleScheme extends TupleScheme<rebalance_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, rebalance_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        if (struct.is_set_ite()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
        if (struct.is_set_ite()) {
          struct.ite.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, rebalance_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
        if (incoming.get(1)) {
          struct.ite = new InvalidTopologyException();
          struct.ite.read(iprot);
          struct.set_ite_isSet(true);
        }
      }
    }

  }

  public static class metricMonitor_args implements org.apache.thrift.TBase<metricMonitor_args, metricMonitor_args._Fields>, java.io.Serializable, Cloneable, Comparable<metricMonitor_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("metricMonitor_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField OPTIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("options", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new metricMonitor_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new metricMonitor_argsTupleSchemeFactory());
    }

    private String name; // required
    private MonitorOptions options; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name"),
      OPTIONS((short)2, "options");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          case 2: // OPTIONS
            return OPTIONS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("options", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MonitorOptions.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(metricMonitor_args.class, metaDataMap);
    }

    public metricMonitor_args() {
    }

    public metricMonitor_args(
      String name,
      MonitorOptions options)
    {
      this();
      this.name = name;
      this.options = options;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public metricMonitor_args(metricMonitor_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
      if (other.is_set_options()) {
        this.options = new MonitorOptions(other.options);
      }
    }

    public metricMonitor_args deepCopy() {
      return new metricMonitor_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
      this.options = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public MonitorOptions get_options() {
      return this.options;
    }

    public void set_options(MonitorOptions options) {
      this.options = options;
    }

    public void unset_options() {
      this.options = null;
    }

    /** Returns true if field options is set (has been assigned a value) and false otherwise */
    public boolean is_set_options() {
      return this.options != null;
    }

    public void set_options_isSet(boolean value) {
      if (!value) {
        this.options = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      case OPTIONS:
        if (value == null) {
          unset_options();
        } else {
          set_options((MonitorOptions)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      case OPTIONS:
        return get_options();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      case OPTIONS:
        return is_set_options();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof metricMonitor_args)
        return this.equals((metricMonitor_args)that);
      return false;
    }

    public boolean equals(metricMonitor_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      boolean this_present_options = true && this.is_set_options();
      boolean that_present_options = true && that.is_set_options();
      if (this_present_options || that_present_options) {
        if (!(this_present_options && that_present_options))
          return false;
        if (!this.options.equals(that.options))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      boolean present_options = true && (is_set_options());
      list.add(present_options);
      if (present_options)
        list.add(options);

      return list.hashCode();
    }

    @Override
    public int compareTo(metricMonitor_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_options()).compareTo(other.is_set_options());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_options()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.options, other.options);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("metricMonitor_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("options:");
      if (this.options == null) {
        sb.append("null");
      } else {
        sb.append(this.options);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (options != null) {
        options.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class metricMonitor_argsStandardSchemeFactory implements SchemeFactory {
      public metricMonitor_argsStandardScheme getScheme() {
        return new metricMonitor_argsStandardScheme();
      }
    }

    private static class metricMonitor_argsStandardScheme extends StandardScheme<metricMonitor_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, metricMonitor_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // OPTIONS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.options = new MonitorOptions();
                struct.options.read(iprot);
                struct.set_options_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, metricMonitor_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        if (struct.options != null) {
          oprot.writeFieldBegin(OPTIONS_FIELD_DESC);
          struct.options.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class metricMonitor_argsTupleSchemeFactory implements SchemeFactory {
      public metricMonitor_argsTupleScheme getScheme() {
        return new metricMonitor_argsTupleScheme();
      }
    }

    private static class metricMonitor_argsTupleScheme extends TupleScheme<metricMonitor_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, metricMonitor_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        if (struct.is_set_options()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
        if (struct.is_set_options()) {
          struct.options.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, metricMonitor_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
        if (incoming.get(1)) {
          struct.options = new MonitorOptions();
          struct.options.read(iprot);
          struct.set_options_isSet(true);
        }
      }
    }

  }

  public static class metricMonitor_result implements org.apache.thrift.TBase<metricMonitor_result, metricMonitor_result._Fields>, java.io.Serializable, Cloneable, Comparable<metricMonitor_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("metricMonitor_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new metricMonitor_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new metricMonitor_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(metricMonitor_result.class, metaDataMap);
    }

    public metricMonitor_result() {
    }

    public metricMonitor_result(
      NotAliveException e)
    {
      this();
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public metricMonitor_result(metricMonitor_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public metricMonitor_result deepCopy() {
      return new metricMonitor_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof metricMonitor_result)
        return this.equals((metricMonitor_result)that);
      return false;
    }

    public boolean equals(metricMonitor_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(metricMonitor_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("metricMonitor_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class metricMonitor_resultStandardSchemeFactory implements SchemeFactory {
      public metricMonitor_resultStandardScheme getScheme() {
        return new metricMonitor_resultStandardScheme();
      }
    }

    private static class metricMonitor_resultStandardScheme extends StandardScheme<metricMonitor_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, metricMonitor_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, metricMonitor_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class metricMonitor_resultTupleSchemeFactory implements SchemeFactory {
      public metricMonitor_resultTupleScheme getScheme() {
        return new metricMonitor_resultTupleScheme();
      }
    }

    private static class metricMonitor_resultTupleScheme extends TupleScheme<metricMonitor_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, metricMonitor_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, metricMonitor_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class restart_args implements org.apache.thrift.TBase<restart_args, restart_args._Fields>, java.io.Serializable, Cloneable, Comparable<restart_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("restart_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField JSON_CONF_FIELD_DESC = new org.apache.thrift.protocol.TField("jsonConf", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new restart_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new restart_argsTupleSchemeFactory());
    }

    private String name; // required
    private String jsonConf; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name"),
      JSON_CONF((short)2, "jsonConf");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          case 2: // JSON_CONF
            return JSON_CONF;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.JSON_CONF, new org.apache.thrift.meta_data.FieldMetaData("jsonConf", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(restart_args.class, metaDataMap);
    }

    public restart_args() {
    }

    public restart_args(
      String name,
      String jsonConf)
    {
      this();
      this.name = name;
      this.jsonConf = jsonConf;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public restart_args(restart_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
      if (other.is_set_jsonConf()) {
        this.jsonConf = other.jsonConf;
      }
    }

    public restart_args deepCopy() {
      return new restart_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
      this.jsonConf = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public String get_jsonConf() {
      return this.jsonConf;
    }

    public void set_jsonConf(String jsonConf) {
      this.jsonConf = jsonConf;
    }

    public void unset_jsonConf() {
      this.jsonConf = null;
    }

    /** Returns true if field jsonConf is set (has been assigned a value) and false otherwise */
    public boolean is_set_jsonConf() {
      return this.jsonConf != null;
    }

    public void set_jsonConf_isSet(boolean value) {
      if (!value) {
        this.jsonConf = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      case JSON_CONF:
        if (value == null) {
          unset_jsonConf();
        } else {
          set_jsonConf((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      case JSON_CONF:
        return get_jsonConf();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      case JSON_CONF:
        return is_set_jsonConf();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof restart_args)
        return this.equals((restart_args)that);
      return false;
    }

    public boolean equals(restart_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      boolean this_present_jsonConf = true && this.is_set_jsonConf();
      boolean that_present_jsonConf = true && that.is_set_jsonConf();
      if (this_present_jsonConf || that_present_jsonConf) {
        if (!(this_present_jsonConf && that_present_jsonConf))
          return false;
        if (!this.jsonConf.equals(that.jsonConf))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      boolean present_jsonConf = true && (is_set_jsonConf());
      list.add(present_jsonConf);
      if (present_jsonConf)
        list.add(jsonConf);

      return list.hashCode();
    }

    @Override
    public int compareTo(restart_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_jsonConf()).compareTo(other.is_set_jsonConf());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_jsonConf()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.jsonConf, other.jsonConf);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("restart_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("jsonConf:");
      if (this.jsonConf == null) {
        sb.append("null");
      } else {
        sb.append(this.jsonConf);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class restart_argsStandardSchemeFactory implements SchemeFactory {
      public restart_argsStandardScheme getScheme() {
        return new restart_argsStandardScheme();
      }
    }

    private static class restart_argsStandardScheme extends StandardScheme<restart_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, restart_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // JSON_CONF
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.jsonConf = iprot.readString();
                struct.set_jsonConf_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, restart_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        if (struct.jsonConf != null) {
          oprot.writeFieldBegin(JSON_CONF_FIELD_DESC);
          oprot.writeString(struct.jsonConf);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class restart_argsTupleSchemeFactory implements SchemeFactory {
      public restart_argsTupleScheme getScheme() {
        return new restart_argsTupleScheme();
      }
    }

    private static class restart_argsTupleScheme extends TupleScheme<restart_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, restart_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        if (struct.is_set_jsonConf()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
        if (struct.is_set_jsonConf()) {
          oprot.writeString(struct.jsonConf);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, restart_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
        if (incoming.get(1)) {
          struct.jsonConf = iprot.readString();
          struct.set_jsonConf_isSet(true);
        }
      }
    }

  }

  public static class restart_result implements org.apache.thrift.TBase<restart_result, restart_result._Fields>, java.io.Serializable, Cloneable, Comparable<restart_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("restart_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField ITE_FIELD_DESC = new org.apache.thrift.protocol.TField("ite", org.apache.thrift.protocol.TType.STRUCT, (short)2);
    private static final org.apache.thrift.protocol.TField TAE_FIELD_DESC = new org.apache.thrift.protocol.TField("tae", org.apache.thrift.protocol.TType.STRUCT, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new restart_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new restart_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required
    private InvalidTopologyException ite; // required
    private TopologyAssignException tae; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e"),
      ITE((short)2, "ite"),
      TAE((short)3, "tae");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          case 2: // ITE
            return ITE;
          case 3: // TAE
            return TAE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.ITE, new org.apache.thrift.meta_data.FieldMetaData("ite", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.TAE, new org.apache.thrift.meta_data.FieldMetaData("tae", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(restart_result.class, metaDataMap);
    }

    public restart_result() {
    }

    public restart_result(
      NotAliveException e,
      InvalidTopologyException ite,
      TopologyAssignException tae)
    {
      this();
      this.e = e;
      this.ite = ite;
      this.tae = tae;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public restart_result(restart_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
      if (other.is_set_ite()) {
        this.ite = new InvalidTopologyException(other.ite);
      }
      if (other.is_set_tae()) {
        this.tae = new TopologyAssignException(other.tae);
      }
    }

    public restart_result deepCopy() {
      return new restart_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
      this.ite = null;
      this.tae = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public InvalidTopologyException get_ite() {
      return this.ite;
    }

    public void set_ite(InvalidTopologyException ite) {
      this.ite = ite;
    }

    public void unset_ite() {
      this.ite = null;
    }

    /** Returns true if field ite is set (has been assigned a value) and false otherwise */
    public boolean is_set_ite() {
      return this.ite != null;
    }

    public void set_ite_isSet(boolean value) {
      if (!value) {
        this.ite = null;
      }
    }

    public TopologyAssignException get_tae() {
      return this.tae;
    }

    public void set_tae(TopologyAssignException tae) {
      this.tae = tae;
    }

    public void unset_tae() {
      this.tae = null;
    }

    /** Returns true if field tae is set (has been assigned a value) and false otherwise */
    public boolean is_set_tae() {
      return this.tae != null;
    }

    public void set_tae_isSet(boolean value) {
      if (!value) {
        this.tae = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      case ITE:
        if (value == null) {
          unset_ite();
        } else {
          set_ite((InvalidTopologyException)value);
        }
        break;

      case TAE:
        if (value == null) {
          unset_tae();
        } else {
          set_tae((TopologyAssignException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      case ITE:
        return get_ite();

      case TAE:
        return get_tae();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      case ITE:
        return is_set_ite();
      case TAE:
        return is_set_tae();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof restart_result)
        return this.equals((restart_result)that);
      return false;
    }

    public boolean equals(restart_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      boolean this_present_ite = true && this.is_set_ite();
      boolean that_present_ite = true && that.is_set_ite();
      if (this_present_ite || that_present_ite) {
        if (!(this_present_ite && that_present_ite))
          return false;
        if (!this.ite.equals(that.ite))
          return false;
      }

      boolean this_present_tae = true && this.is_set_tae();
      boolean that_present_tae = true && that.is_set_tae();
      if (this_present_tae || that_present_tae) {
        if (!(this_present_tae && that_present_tae))
          return false;
        if (!this.tae.equals(that.tae))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      boolean present_ite = true && (is_set_ite());
      list.add(present_ite);
      if (present_ite)
        list.add(ite);

      boolean present_tae = true && (is_set_tae());
      list.add(present_tae);
      if (present_tae)
        list.add(tae);

      return list.hashCode();
    }

    @Override
    public int compareTo(restart_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_ite()).compareTo(other.is_set_ite());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_ite()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ite, other.ite);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_tae()).compareTo(other.is_set_tae());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_tae()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tae, other.tae);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("restart_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("ite:");
      if (this.ite == null) {
        sb.append("null");
      } else {
        sb.append(this.ite);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("tae:");
      if (this.tae == null) {
        sb.append("null");
      } else {
        sb.append(this.tae);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class restart_resultStandardSchemeFactory implements SchemeFactory {
      public restart_resultStandardScheme getScheme() {
        return new restart_resultStandardScheme();
      }
    }

    private static class restart_resultStandardScheme extends StandardScheme<restart_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, restart_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ITE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.ite = new InvalidTopologyException();
                struct.ite.read(iprot);
                struct.set_ite_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // TAE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.tae = new TopologyAssignException();
                struct.tae.read(iprot);
                struct.set_tae_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, restart_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.ite != null) {
          oprot.writeFieldBegin(ITE_FIELD_DESC);
          struct.ite.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.tae != null) {
          oprot.writeFieldBegin(TAE_FIELD_DESC);
          struct.tae.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class restart_resultTupleSchemeFactory implements SchemeFactory {
      public restart_resultTupleScheme getScheme() {
        return new restart_resultTupleScheme();
      }
    }

    private static class restart_resultTupleScheme extends TupleScheme<restart_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, restart_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        if (struct.is_set_ite()) {
          optionals.set(1);
        }
        if (struct.is_set_tae()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
        if (struct.is_set_ite()) {
          struct.ite.write(oprot);
        }
        if (struct.is_set_tae()) {
          struct.tae.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, restart_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
        if (incoming.get(1)) {
          struct.ite = new InvalidTopologyException();
          struct.ite.read(iprot);
          struct.set_ite_isSet(true);
        }
        if (incoming.get(2)) {
          struct.tae = new TopologyAssignException();
          struct.tae.read(iprot);
          struct.set_tae_isSet(true);
        }
      }
    }

  }

  public static class beginLibUpload_args implements org.apache.thrift.TBase<beginLibUpload_args, beginLibUpload_args._Fields>, java.io.Serializable, Cloneable, Comparable<beginLibUpload_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("beginLibUpload_args");

    private static final org.apache.thrift.protocol.TField LIB_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("libName", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new beginLibUpload_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new beginLibUpload_argsTupleSchemeFactory());
    }

    private String libName; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      LIB_NAME((short)1, "libName");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // LIB_NAME
            return LIB_NAME;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.LIB_NAME, new org.apache.thrift.meta_data.FieldMetaData("libName", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(beginLibUpload_args.class, metaDataMap);
    }

    public beginLibUpload_args() {
    }

    public beginLibUpload_args(
      String libName)
    {
      this();
      this.libName = libName;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public beginLibUpload_args(beginLibUpload_args other) {
      if (other.is_set_libName()) {
        this.libName = other.libName;
      }
    }

    public beginLibUpload_args deepCopy() {
      return new beginLibUpload_args(this);
    }

    @Override
    public void clear() {
      this.libName = null;
    }

    public String get_libName() {
      return this.libName;
    }

    public void set_libName(String libName) {
      this.libName = libName;
    }

    public void unset_libName() {
      this.libName = null;
    }

    /** Returns true if field libName is set (has been assigned a value) and false otherwise */
    public boolean is_set_libName() {
      return this.libName != null;
    }

    public void set_libName_isSet(boolean value) {
      if (!value) {
        this.libName = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case LIB_NAME:
        if (value == null) {
          unset_libName();
        } else {
          set_libName((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case LIB_NAME:
        return get_libName();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case LIB_NAME:
        return is_set_libName();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof beginLibUpload_args)
        return this.equals((beginLibUpload_args)that);
      return false;
    }

    public boolean equals(beginLibUpload_args that) {
      if (that == null)
        return false;

      boolean this_present_libName = true && this.is_set_libName();
      boolean that_present_libName = true && that.is_set_libName();
      if (this_present_libName || that_present_libName) {
        if (!(this_present_libName && that_present_libName))
          return false;
        if (!this.libName.equals(that.libName))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_libName = true && (is_set_libName());
      list.add(present_libName);
      if (present_libName)
        list.add(libName);

      return list.hashCode();
    }

    @Override
    public int compareTo(beginLibUpload_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_libName()).compareTo(other.is_set_libName());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_libName()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.libName, other.libName);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("beginLibUpload_args(");
      boolean first = true;

      sb.append("libName:");
      if (this.libName == null) {
        sb.append("null");
      } else {
        sb.append(this.libName);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class beginLibUpload_argsStandardSchemeFactory implements SchemeFactory {
      public beginLibUpload_argsStandardScheme getScheme() {
        return new beginLibUpload_argsStandardScheme();
      }
    }

    private static class beginLibUpload_argsStandardScheme extends StandardScheme<beginLibUpload_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, beginLibUpload_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // LIB_NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.libName = iprot.readString();
                struct.set_libName_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, beginLibUpload_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.libName != null) {
          oprot.writeFieldBegin(LIB_NAME_FIELD_DESC);
          oprot.writeString(struct.libName);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class beginLibUpload_argsTupleSchemeFactory implements SchemeFactory {
      public beginLibUpload_argsTupleScheme getScheme() {
        return new beginLibUpload_argsTupleScheme();
      }
    }

    private static class beginLibUpload_argsTupleScheme extends TupleScheme<beginLibUpload_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, beginLibUpload_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_libName()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_libName()) {
          oprot.writeString(struct.libName);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, beginLibUpload_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.libName = iprot.readString();
          struct.set_libName_isSet(true);
        }
      }
    }

  }

  public static class beginLibUpload_result implements org.apache.thrift.TBase<beginLibUpload_result, beginLibUpload_result._Fields>, java.io.Serializable, Cloneable, Comparable<beginLibUpload_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("beginLibUpload_result");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new beginLibUpload_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new beginLibUpload_resultTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(beginLibUpload_result.class, metaDataMap);
    }

    public beginLibUpload_result() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public beginLibUpload_result(beginLibUpload_result other) {
    }

    public beginLibUpload_result deepCopy() {
      return new beginLibUpload_result(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof beginLibUpload_result)
        return this.equals((beginLibUpload_result)that);
      return false;
    }

    public boolean equals(beginLibUpload_result that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(beginLibUpload_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("beginLibUpload_result(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class beginLibUpload_resultStandardSchemeFactory implements SchemeFactory {
      public beginLibUpload_resultStandardScheme getScheme() {
        return new beginLibUpload_resultStandardScheme();
      }
    }

    private static class beginLibUpload_resultStandardScheme extends StandardScheme<beginLibUpload_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, beginLibUpload_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, beginLibUpload_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class beginLibUpload_resultTupleSchemeFactory implements SchemeFactory {
      public beginLibUpload_resultTupleScheme getScheme() {
        return new beginLibUpload_resultTupleScheme();
      }
    }

    private static class beginLibUpload_resultTupleScheme extends TupleScheme<beginLibUpload_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, beginLibUpload_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, beginLibUpload_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class beginFileUpload_args implements org.apache.thrift.TBase<beginFileUpload_args, beginFileUpload_args._Fields>, java.io.Serializable, Cloneable, Comparable<beginFileUpload_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("beginFileUpload_args");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new beginFileUpload_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new beginFileUpload_argsTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(beginFileUpload_args.class, metaDataMap);
    }

    public beginFileUpload_args() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public beginFileUpload_args(beginFileUpload_args other) {
    }

    public beginFileUpload_args deepCopy() {
      return new beginFileUpload_args(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof beginFileUpload_args)
        return this.equals((beginFileUpload_args)that);
      return false;
    }

    public boolean equals(beginFileUpload_args that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(beginFileUpload_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("beginFileUpload_args(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class beginFileUpload_argsStandardSchemeFactory implements SchemeFactory {
      public beginFileUpload_argsStandardScheme getScheme() {
        return new beginFileUpload_argsStandardScheme();
      }
    }

    private static class beginFileUpload_argsStandardScheme extends StandardScheme<beginFileUpload_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, beginFileUpload_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, beginFileUpload_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class beginFileUpload_argsTupleSchemeFactory implements SchemeFactory {
      public beginFileUpload_argsTupleScheme getScheme() {
        return new beginFileUpload_argsTupleScheme();
      }
    }

    private static class beginFileUpload_argsTupleScheme extends TupleScheme<beginFileUpload_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, beginFileUpload_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, beginFileUpload_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class beginFileUpload_result implements org.apache.thrift.TBase<beginFileUpload_result, beginFileUpload_result._Fields>, java.io.Serializable, Cloneable, Comparable<beginFileUpload_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("beginFileUpload_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new beginFileUpload_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new beginFileUpload_resultTupleSchemeFactory());
    }

    private String success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(beginFileUpload_result.class, metaDataMap);
    }

    public beginFileUpload_result() {
    }

    public beginFileUpload_result(
      String success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public beginFileUpload_result(beginFileUpload_result other) {
      if (other.is_set_success()) {
        this.success = other.success;
      }
    }

    public beginFileUpload_result deepCopy() {
      return new beginFileUpload_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public String get_success() {
      return this.success;
    }

    public void set_success(String success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof beginFileUpload_result)
        return this.equals((beginFileUpload_result)that);
      return false;
    }

    public boolean equals(beginFileUpload_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(beginFileUpload_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("beginFileUpload_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class beginFileUpload_resultStandardSchemeFactory implements SchemeFactory {
      public beginFileUpload_resultStandardScheme getScheme() {
        return new beginFileUpload_resultStandardScheme();
      }
    }

    private static class beginFileUpload_resultStandardScheme extends StandardScheme<beginFileUpload_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, beginFileUpload_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, beginFileUpload_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class beginFileUpload_resultTupleSchemeFactory implements SchemeFactory {
      public beginFileUpload_resultTupleScheme getScheme() {
        return new beginFileUpload_resultTupleScheme();
      }
    }

    private static class beginFileUpload_resultTupleScheme extends TupleScheme<beginFileUpload_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, beginFileUpload_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          oprot.writeString(struct.success);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, beginFileUpload_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class uploadChunk_args implements org.apache.thrift.TBase<uploadChunk_args, uploadChunk_args._Fields>, java.io.Serializable, Cloneable, Comparable<uploadChunk_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("uploadChunk_args");

    private static final org.apache.thrift.protocol.TField LOCATION_FIELD_DESC = new org.apache.thrift.protocol.TField("location", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField CHUNK_FIELD_DESC = new org.apache.thrift.protocol.TField("chunk", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new uploadChunk_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new uploadChunk_argsTupleSchemeFactory());
    }

    private String location; // required
    private ByteBuffer chunk; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      LOCATION((short)1, "location"),
      CHUNK((short)2, "chunk");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // LOCATION
            return LOCATION;
          case 2: // CHUNK
            return CHUNK;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.LOCATION, new org.apache.thrift.meta_data.FieldMetaData("location", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.CHUNK, new org.apache.thrift.meta_data.FieldMetaData("chunk", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING          , true)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(uploadChunk_args.class, metaDataMap);
    }

    public uploadChunk_args() {
    }

    public uploadChunk_args(
      String location,
      ByteBuffer chunk)
    {
      this();
      this.location = location;
      this.chunk = org.apache.thrift.TBaseHelper.copyBinary(chunk);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public uploadChunk_args(uploadChunk_args other) {
      if (other.is_set_location()) {
        this.location = other.location;
      }
      if (other.is_set_chunk()) {
        this.chunk = org.apache.thrift.TBaseHelper.copyBinary(other.chunk);
      }
    }

    public uploadChunk_args deepCopy() {
      return new uploadChunk_args(this);
    }

    @Override
    public void clear() {
      this.location = null;
      this.chunk = null;
    }

    public String get_location() {
      return this.location;
    }

    public void set_location(String location) {
      this.location = location;
    }

    public void unset_location() {
      this.location = null;
    }

    /** Returns true if field location is set (has been assigned a value) and false otherwise */
    public boolean is_set_location() {
      return this.location != null;
    }

    public void set_location_isSet(boolean value) {
      if (!value) {
        this.location = null;
      }
    }

    public byte[] get_chunk() {
      set_chunk(org.apache.thrift.TBaseHelper.rightSize(chunk));
      return chunk == null ? null : chunk.array();
    }

    public ByteBuffer buffer_for_chunk() {
      return org.apache.thrift.TBaseHelper.copyBinary(chunk);
    }

    public void set_chunk(byte[] chunk) {
      this.chunk = chunk == null ? (ByteBuffer)null : ByteBuffer.wrap(Arrays.copyOf(chunk, chunk.length));
    }

    public void set_chunk(ByteBuffer chunk) {
      this.chunk = org.apache.thrift.TBaseHelper.copyBinary(chunk);
    }

    public void unset_chunk() {
      this.chunk = null;
    }

    /** Returns true if field chunk is set (has been assigned a value) and false otherwise */
    public boolean is_set_chunk() {
      return this.chunk != null;
    }

    public void set_chunk_isSet(boolean value) {
      if (!value) {
        this.chunk = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case LOCATION:
        if (value == null) {
          unset_location();
        } else {
          set_location((String)value);
        }
        break;

      case CHUNK:
        if (value == null) {
          unset_chunk();
        } else {
          set_chunk((ByteBuffer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case LOCATION:
        return get_location();

      case CHUNK:
        return get_chunk();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case LOCATION:
        return is_set_location();
      case CHUNK:
        return is_set_chunk();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof uploadChunk_args)
        return this.equals((uploadChunk_args)that);
      return false;
    }

    public boolean equals(uploadChunk_args that) {
      if (that == null)
        return false;

      boolean this_present_location = true && this.is_set_location();
      boolean that_present_location = true && that.is_set_location();
      if (this_present_location || that_present_location) {
        if (!(this_present_location && that_present_location))
          return false;
        if (!this.location.equals(that.location))
          return false;
      }

      boolean this_present_chunk = true && this.is_set_chunk();
      boolean that_present_chunk = true && that.is_set_chunk();
      if (this_present_chunk || that_present_chunk) {
        if (!(this_present_chunk && that_present_chunk))
          return false;
        if (!this.chunk.equals(that.chunk))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_location = true && (is_set_location());
      list.add(present_location);
      if (present_location)
        list.add(location);

      boolean present_chunk = true && (is_set_chunk());
      list.add(present_chunk);
      if (present_chunk)
        list.add(chunk);

      return list.hashCode();
    }

    @Override
    public int compareTo(uploadChunk_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_location()).compareTo(other.is_set_location());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_location()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.location, other.location);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_chunk()).compareTo(other.is_set_chunk());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_chunk()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.chunk, other.chunk);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("uploadChunk_args(");
      boolean first = true;

      sb.append("location:");
      if (this.location == null) {
        sb.append("null");
      } else {
        sb.append(this.location);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("chunk:");
      if (this.chunk == null) {
        sb.append("null");
      } else {
        org.apache.thrift.TBaseHelper.toString(this.chunk, sb);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class uploadChunk_argsStandardSchemeFactory implements SchemeFactory {
      public uploadChunk_argsStandardScheme getScheme() {
        return new uploadChunk_argsStandardScheme();
      }
    }

    private static class uploadChunk_argsStandardScheme extends StandardScheme<uploadChunk_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, uploadChunk_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // LOCATION
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.location = iprot.readString();
                struct.set_location_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // CHUNK
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.chunk = iprot.readBinary();
                struct.set_chunk_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, uploadChunk_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.location != null) {
          oprot.writeFieldBegin(LOCATION_FIELD_DESC);
          oprot.writeString(struct.location);
          oprot.writeFieldEnd();
        }
        if (struct.chunk != null) {
          oprot.writeFieldBegin(CHUNK_FIELD_DESC);
          oprot.writeBinary(struct.chunk);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class uploadChunk_argsTupleSchemeFactory implements SchemeFactory {
      public uploadChunk_argsTupleScheme getScheme() {
        return new uploadChunk_argsTupleScheme();
      }
    }

    private static class uploadChunk_argsTupleScheme extends TupleScheme<uploadChunk_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, uploadChunk_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_location()) {
          optionals.set(0);
        }
        if (struct.is_set_chunk()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_location()) {
          oprot.writeString(struct.location);
        }
        if (struct.is_set_chunk()) {
          oprot.writeBinary(struct.chunk);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, uploadChunk_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.location = iprot.readString();
          struct.set_location_isSet(true);
        }
        if (incoming.get(1)) {
          struct.chunk = iprot.readBinary();
          struct.set_chunk_isSet(true);
        }
      }
    }

  }

  public static class uploadChunk_result implements org.apache.thrift.TBase<uploadChunk_result, uploadChunk_result._Fields>, java.io.Serializable, Cloneable, Comparable<uploadChunk_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("uploadChunk_result");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new uploadChunk_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new uploadChunk_resultTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(uploadChunk_result.class, metaDataMap);
    }

    public uploadChunk_result() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public uploadChunk_result(uploadChunk_result other) {
    }

    public uploadChunk_result deepCopy() {
      return new uploadChunk_result(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof uploadChunk_result)
        return this.equals((uploadChunk_result)that);
      return false;
    }

    public boolean equals(uploadChunk_result that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(uploadChunk_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("uploadChunk_result(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class uploadChunk_resultStandardSchemeFactory implements SchemeFactory {
      public uploadChunk_resultStandardScheme getScheme() {
        return new uploadChunk_resultStandardScheme();
      }
    }

    private static class uploadChunk_resultStandardScheme extends StandardScheme<uploadChunk_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, uploadChunk_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, uploadChunk_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class uploadChunk_resultTupleSchemeFactory implements SchemeFactory {
      public uploadChunk_resultTupleScheme getScheme() {
        return new uploadChunk_resultTupleScheme();
      }
    }

    private static class uploadChunk_resultTupleScheme extends TupleScheme<uploadChunk_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, uploadChunk_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, uploadChunk_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class finishFileUpload_args implements org.apache.thrift.TBase<finishFileUpload_args, finishFileUpload_args._Fields>, java.io.Serializable, Cloneable, Comparable<finishFileUpload_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("finishFileUpload_args");

    private static final org.apache.thrift.protocol.TField LOCATION_FIELD_DESC = new org.apache.thrift.protocol.TField("location", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new finishFileUpload_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new finishFileUpload_argsTupleSchemeFactory());
    }

    private String location; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      LOCATION((short)1, "location");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // LOCATION
            return LOCATION;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.LOCATION, new org.apache.thrift.meta_data.FieldMetaData("location", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(finishFileUpload_args.class, metaDataMap);
    }

    public finishFileUpload_args() {
    }

    public finishFileUpload_args(
      String location)
    {
      this();
      this.location = location;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public finishFileUpload_args(finishFileUpload_args other) {
      if (other.is_set_location()) {
        this.location = other.location;
      }
    }

    public finishFileUpload_args deepCopy() {
      return new finishFileUpload_args(this);
    }

    @Override
    public void clear() {
      this.location = null;
    }

    public String get_location() {
      return this.location;
    }

    public void set_location(String location) {
      this.location = location;
    }

    public void unset_location() {
      this.location = null;
    }

    /** Returns true if field location is set (has been assigned a value) and false otherwise */
    public boolean is_set_location() {
      return this.location != null;
    }

    public void set_location_isSet(boolean value) {
      if (!value) {
        this.location = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case LOCATION:
        if (value == null) {
          unset_location();
        } else {
          set_location((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case LOCATION:
        return get_location();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case LOCATION:
        return is_set_location();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof finishFileUpload_args)
        return this.equals((finishFileUpload_args)that);
      return false;
    }

    public boolean equals(finishFileUpload_args that) {
      if (that == null)
        return false;

      boolean this_present_location = true && this.is_set_location();
      boolean that_present_location = true && that.is_set_location();
      if (this_present_location || that_present_location) {
        if (!(this_present_location && that_present_location))
          return false;
        if (!this.location.equals(that.location))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_location = true && (is_set_location());
      list.add(present_location);
      if (present_location)
        list.add(location);

      return list.hashCode();
    }

    @Override
    public int compareTo(finishFileUpload_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_location()).compareTo(other.is_set_location());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_location()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.location, other.location);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("finishFileUpload_args(");
      boolean first = true;

      sb.append("location:");
      if (this.location == null) {
        sb.append("null");
      } else {
        sb.append(this.location);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class finishFileUpload_argsStandardSchemeFactory implements SchemeFactory {
      public finishFileUpload_argsStandardScheme getScheme() {
        return new finishFileUpload_argsStandardScheme();
      }
    }

    private static class finishFileUpload_argsStandardScheme extends StandardScheme<finishFileUpload_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, finishFileUpload_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // LOCATION
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.location = iprot.readString();
                struct.set_location_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, finishFileUpload_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.location != null) {
          oprot.writeFieldBegin(LOCATION_FIELD_DESC);
          oprot.writeString(struct.location);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class finishFileUpload_argsTupleSchemeFactory implements SchemeFactory {
      public finishFileUpload_argsTupleScheme getScheme() {
        return new finishFileUpload_argsTupleScheme();
      }
    }

    private static class finishFileUpload_argsTupleScheme extends TupleScheme<finishFileUpload_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, finishFileUpload_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_location()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_location()) {
          oprot.writeString(struct.location);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, finishFileUpload_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.location = iprot.readString();
          struct.set_location_isSet(true);
        }
      }
    }

  }

  public static class finishFileUpload_result implements org.apache.thrift.TBase<finishFileUpload_result, finishFileUpload_result._Fields>, java.io.Serializable, Cloneable, Comparable<finishFileUpload_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("finishFileUpload_result");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new finishFileUpload_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new finishFileUpload_resultTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(finishFileUpload_result.class, metaDataMap);
    }

    public finishFileUpload_result() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public finishFileUpload_result(finishFileUpload_result other) {
    }

    public finishFileUpload_result deepCopy() {
      return new finishFileUpload_result(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof finishFileUpload_result)
        return this.equals((finishFileUpload_result)that);
      return false;
    }

    public boolean equals(finishFileUpload_result that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(finishFileUpload_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("finishFileUpload_result(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class finishFileUpload_resultStandardSchemeFactory implements SchemeFactory {
      public finishFileUpload_resultStandardScheme getScheme() {
        return new finishFileUpload_resultStandardScheme();
      }
    }

    private static class finishFileUpload_resultStandardScheme extends StandardScheme<finishFileUpload_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, finishFileUpload_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, finishFileUpload_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class finishFileUpload_resultTupleSchemeFactory implements SchemeFactory {
      public finishFileUpload_resultTupleScheme getScheme() {
        return new finishFileUpload_resultTupleScheme();
      }
    }

    private static class finishFileUpload_resultTupleScheme extends TupleScheme<finishFileUpload_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, finishFileUpload_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, finishFileUpload_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class beginFileDownload_args implements org.apache.thrift.TBase<beginFileDownload_args, beginFileDownload_args._Fields>, java.io.Serializable, Cloneable, Comparable<beginFileDownload_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("beginFileDownload_args");

    private static final org.apache.thrift.protocol.TField FILE_FIELD_DESC = new org.apache.thrift.protocol.TField("file", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new beginFileDownload_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new beginFileDownload_argsTupleSchemeFactory());
    }

    private String file; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      FILE((short)1, "file");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // FILE
            return FILE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.FILE, new org.apache.thrift.meta_data.FieldMetaData("file", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(beginFileDownload_args.class, metaDataMap);
    }

    public beginFileDownload_args() {
    }

    public beginFileDownload_args(
      String file)
    {
      this();
      this.file = file;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public beginFileDownload_args(beginFileDownload_args other) {
      if (other.is_set_file()) {
        this.file = other.file;
      }
    }

    public beginFileDownload_args deepCopy() {
      return new beginFileDownload_args(this);
    }

    @Override
    public void clear() {
      this.file = null;
    }

    public String get_file() {
      return this.file;
    }

    public void set_file(String file) {
      this.file = file;
    }

    public void unset_file() {
      this.file = null;
    }

    /** Returns true if field file is set (has been assigned a value) and false otherwise */
    public boolean is_set_file() {
      return this.file != null;
    }

    public void set_file_isSet(boolean value) {
      if (!value) {
        this.file = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case FILE:
        if (value == null) {
          unset_file();
        } else {
          set_file((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case FILE:
        return get_file();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case FILE:
        return is_set_file();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof beginFileDownload_args)
        return this.equals((beginFileDownload_args)that);
      return false;
    }

    public boolean equals(beginFileDownload_args that) {
      if (that == null)
        return false;

      boolean this_present_file = true && this.is_set_file();
      boolean that_present_file = true && that.is_set_file();
      if (this_present_file || that_present_file) {
        if (!(this_present_file && that_present_file))
          return false;
        if (!this.file.equals(that.file))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_file = true && (is_set_file());
      list.add(present_file);
      if (present_file)
        list.add(file);

      return list.hashCode();
    }

    @Override
    public int compareTo(beginFileDownload_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_file()).compareTo(other.is_set_file());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_file()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.file, other.file);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("beginFileDownload_args(");
      boolean first = true;

      sb.append("file:");
      if (this.file == null) {
        sb.append("null");
      } else {
        sb.append(this.file);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class beginFileDownload_argsStandardSchemeFactory implements SchemeFactory {
      public beginFileDownload_argsStandardScheme getScheme() {
        return new beginFileDownload_argsStandardScheme();
      }
    }

    private static class beginFileDownload_argsStandardScheme extends StandardScheme<beginFileDownload_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, beginFileDownload_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // FILE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.file = iprot.readString();
                struct.set_file_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, beginFileDownload_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.file != null) {
          oprot.writeFieldBegin(FILE_FIELD_DESC);
          oprot.writeString(struct.file);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class beginFileDownload_argsTupleSchemeFactory implements SchemeFactory {
      public beginFileDownload_argsTupleScheme getScheme() {
        return new beginFileDownload_argsTupleScheme();
      }
    }

    private static class beginFileDownload_argsTupleScheme extends TupleScheme<beginFileDownload_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, beginFileDownload_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_file()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_file()) {
          oprot.writeString(struct.file);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, beginFileDownload_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.file = iprot.readString();
          struct.set_file_isSet(true);
        }
      }
    }

  }

  public static class beginFileDownload_result implements org.apache.thrift.TBase<beginFileDownload_result, beginFileDownload_result._Fields>, java.io.Serializable, Cloneable, Comparable<beginFileDownload_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("beginFileDownload_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new beginFileDownload_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new beginFileDownload_resultTupleSchemeFactory());
    }

    private String success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(beginFileDownload_result.class, metaDataMap);
    }

    public beginFileDownload_result() {
    }

    public beginFileDownload_result(
      String success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public beginFileDownload_result(beginFileDownload_result other) {
      if (other.is_set_success()) {
        this.success = other.success;
      }
    }

    public beginFileDownload_result deepCopy() {
      return new beginFileDownload_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public String get_success() {
      return this.success;
    }

    public void set_success(String success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof beginFileDownload_result)
        return this.equals((beginFileDownload_result)that);
      return false;
    }

    public boolean equals(beginFileDownload_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(beginFileDownload_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("beginFileDownload_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class beginFileDownload_resultStandardSchemeFactory implements SchemeFactory {
      public beginFileDownload_resultStandardScheme getScheme() {
        return new beginFileDownload_resultStandardScheme();
      }
    }

    private static class beginFileDownload_resultStandardScheme extends StandardScheme<beginFileDownload_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, beginFileDownload_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, beginFileDownload_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class beginFileDownload_resultTupleSchemeFactory implements SchemeFactory {
      public beginFileDownload_resultTupleScheme getScheme() {
        return new beginFileDownload_resultTupleScheme();
      }
    }

    private static class beginFileDownload_resultTupleScheme extends TupleScheme<beginFileDownload_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, beginFileDownload_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          oprot.writeString(struct.success);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, beginFileDownload_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class downloadChunk_args implements org.apache.thrift.TBase<downloadChunk_args, downloadChunk_args._Fields>, java.io.Serializable, Cloneable, Comparable<downloadChunk_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("downloadChunk_args");

    private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new downloadChunk_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new downloadChunk_argsTupleSchemeFactory());
    }

    private String id; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ID((short)1, "id");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ID
            return ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ID, new org.apache.thrift.meta_data.FieldMetaData("id", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(downloadChunk_args.class, metaDataMap);
    }

    public downloadChunk_args() {
    }

    public downloadChunk_args(
      String id)
    {
      this();
      this.id = id;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public downloadChunk_args(downloadChunk_args other) {
      if (other.is_set_id()) {
        this.id = other.id;
      }
    }

    public downloadChunk_args deepCopy() {
      return new downloadChunk_args(this);
    }

    @Override
    public void clear() {
      this.id = null;
    }

    public String get_id() {
      return this.id;
    }

    public void set_id(String id) {
      this.id = id;
    }

    public void unset_id() {
      this.id = null;
    }

    /** Returns true if field id is set (has been assigned a value) and false otherwise */
    public boolean is_set_id() {
      return this.id != null;
    }

    public void set_id_isSet(boolean value) {
      if (!value) {
        this.id = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ID:
        if (value == null) {
          unset_id();
        } else {
          set_id((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ID:
        return get_id();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ID:
        return is_set_id();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof downloadChunk_args)
        return this.equals((downloadChunk_args)that);
      return false;
    }

    public boolean equals(downloadChunk_args that) {
      if (that == null)
        return false;

      boolean this_present_id = true && this.is_set_id();
      boolean that_present_id = true && that.is_set_id();
      if (this_present_id || that_present_id) {
        if (!(this_present_id && that_present_id))
          return false;
        if (!this.id.equals(that.id))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_id = true && (is_set_id());
      list.add(present_id);
      if (present_id)
        list.add(id);

      return list.hashCode();
    }

    @Override
    public int compareTo(downloadChunk_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_id()).compareTo(other.is_set_id());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_id()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.id, other.id);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("downloadChunk_args(");
      boolean first = true;

      sb.append("id:");
      if (this.id == null) {
        sb.append("null");
      } else {
        sb.append(this.id);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class downloadChunk_argsStandardSchemeFactory implements SchemeFactory {
      public downloadChunk_argsStandardScheme getScheme() {
        return new downloadChunk_argsStandardScheme();
      }
    }

    private static class downloadChunk_argsStandardScheme extends StandardScheme<downloadChunk_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, downloadChunk_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.id = iprot.readString();
                struct.set_id_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, downloadChunk_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.id != null) {
          oprot.writeFieldBegin(ID_FIELD_DESC);
          oprot.writeString(struct.id);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class downloadChunk_argsTupleSchemeFactory implements SchemeFactory {
      public downloadChunk_argsTupleScheme getScheme() {
        return new downloadChunk_argsTupleScheme();
      }
    }

    private static class downloadChunk_argsTupleScheme extends TupleScheme<downloadChunk_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, downloadChunk_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_id()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_id()) {
          oprot.writeString(struct.id);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, downloadChunk_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.id = iprot.readString();
          struct.set_id_isSet(true);
        }
      }
    }

  }

  public static class downloadChunk_result implements org.apache.thrift.TBase<downloadChunk_result, downloadChunk_result._Fields>, java.io.Serializable, Cloneable, Comparable<downloadChunk_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("downloadChunk_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new downloadChunk_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new downloadChunk_resultTupleSchemeFactory());
    }

    private ByteBuffer success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING          , true)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(downloadChunk_result.class, metaDataMap);
    }

    public downloadChunk_result() {
    }

    public downloadChunk_result(
      ByteBuffer success)
    {
      this();
      this.success = org.apache.thrift.TBaseHelper.copyBinary(success);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public downloadChunk_result(downloadChunk_result other) {
      if (other.is_set_success()) {
        this.success = org.apache.thrift.TBaseHelper.copyBinary(other.success);
      }
    }

    public downloadChunk_result deepCopy() {
      return new downloadChunk_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public byte[] get_success() {
      set_success(org.apache.thrift.TBaseHelper.rightSize(success));
      return success == null ? null : success.array();
    }

    public ByteBuffer buffer_for_success() {
      return org.apache.thrift.TBaseHelper.copyBinary(success);
    }

    public void set_success(byte[] success) {
      this.success = success == null ? (ByteBuffer)null : ByteBuffer.wrap(Arrays.copyOf(success, success.length));
    }

    public void set_success(ByteBuffer success) {
      this.success = org.apache.thrift.TBaseHelper.copyBinary(success);
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((ByteBuffer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof downloadChunk_result)
        return this.equals((downloadChunk_result)that);
      return false;
    }

    public boolean equals(downloadChunk_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(downloadChunk_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("downloadChunk_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        org.apache.thrift.TBaseHelper.toString(this.success, sb);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class downloadChunk_resultStandardSchemeFactory implements SchemeFactory {
      public downloadChunk_resultStandardScheme getScheme() {
        return new downloadChunk_resultStandardScheme();
      }
    }

    private static class downloadChunk_resultStandardScheme extends StandardScheme<downloadChunk_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, downloadChunk_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readBinary();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, downloadChunk_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBinary(struct.success);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class downloadChunk_resultTupleSchemeFactory implements SchemeFactory {
      public downloadChunk_resultTupleScheme getScheme() {
        return new downloadChunk_resultTupleScheme();
      }
    }

    private static class downloadChunk_resultTupleScheme extends TupleScheme<downloadChunk_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, downloadChunk_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          oprot.writeBinary(struct.success);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, downloadChunk_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = iprot.readBinary();
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class finishFileDownload_args implements org.apache.thrift.TBase<finishFileDownload_args, finishFileDownload_args._Fields>, java.io.Serializable, Cloneable, Comparable<finishFileDownload_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("finishFileDownload_args");

    private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new finishFileDownload_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new finishFileDownload_argsTupleSchemeFactory());
    }

    private String id; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ID((short)1, "id");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ID
            return ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ID, new org.apache.thrift.meta_data.FieldMetaData("id", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(finishFileDownload_args.class, metaDataMap);
    }

    public finishFileDownload_args() {
    }

    public finishFileDownload_args(
      String id)
    {
      this();
      this.id = id;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public finishFileDownload_args(finishFileDownload_args other) {
      if (other.is_set_id()) {
        this.id = other.id;
      }
    }

    public finishFileDownload_args deepCopy() {
      return new finishFileDownload_args(this);
    }

    @Override
    public void clear() {
      this.id = null;
    }

    public String get_id() {
      return this.id;
    }

    public void set_id(String id) {
      this.id = id;
    }

    public void unset_id() {
      this.id = null;
    }

    /** Returns true if field id is set (has been assigned a value) and false otherwise */
    public boolean is_set_id() {
      return this.id != null;
    }

    public void set_id_isSet(boolean value) {
      if (!value) {
        this.id = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ID:
        if (value == null) {
          unset_id();
        } else {
          set_id((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ID:
        return get_id();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ID:
        return is_set_id();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof finishFileDownload_args)
        return this.equals((finishFileDownload_args)that);
      return false;
    }

    public boolean equals(finishFileDownload_args that) {
      if (that == null)
        return false;

      boolean this_present_id = true && this.is_set_id();
      boolean that_present_id = true && that.is_set_id();
      if (this_present_id || that_present_id) {
        if (!(this_present_id && that_present_id))
          return false;
        if (!this.id.equals(that.id))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_id = true && (is_set_id());
      list.add(present_id);
      if (present_id)
        list.add(id);

      return list.hashCode();
    }

    @Override
    public int compareTo(finishFileDownload_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_id()).compareTo(other.is_set_id());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_id()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.id, other.id);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("finishFileDownload_args(");
      boolean first = true;

      sb.append("id:");
      if (this.id == null) {
        sb.append("null");
      } else {
        sb.append(this.id);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class finishFileDownload_argsStandardSchemeFactory implements SchemeFactory {
      public finishFileDownload_argsStandardScheme getScheme() {
        return new finishFileDownload_argsStandardScheme();
      }
    }

    private static class finishFileDownload_argsStandardScheme extends StandardScheme<finishFileDownload_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, finishFileDownload_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.id = iprot.readString();
                struct.set_id_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, finishFileDownload_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.id != null) {
          oprot.writeFieldBegin(ID_FIELD_DESC);
          oprot.writeString(struct.id);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class finishFileDownload_argsTupleSchemeFactory implements SchemeFactory {
      public finishFileDownload_argsTupleScheme getScheme() {
        return new finishFileDownload_argsTupleScheme();
      }
    }

    private static class finishFileDownload_argsTupleScheme extends TupleScheme<finishFileDownload_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, finishFileDownload_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_id()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_id()) {
          oprot.writeString(struct.id);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, finishFileDownload_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.id = iprot.readString();
          struct.set_id_isSet(true);
        }
      }
    }

  }

  public static class finishFileDownload_result implements org.apache.thrift.TBase<finishFileDownload_result, finishFileDownload_result._Fields>, java.io.Serializable, Cloneable, Comparable<finishFileDownload_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("finishFileDownload_result");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new finishFileDownload_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new finishFileDownload_resultTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(finishFileDownload_result.class, metaDataMap);
    }

    public finishFileDownload_result() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public finishFileDownload_result(finishFileDownload_result other) {
    }

    public finishFileDownload_result deepCopy() {
      return new finishFileDownload_result(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof finishFileDownload_result)
        return this.equals((finishFileDownload_result)that);
      return false;
    }

    public boolean equals(finishFileDownload_result that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(finishFileDownload_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("finishFileDownload_result(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class finishFileDownload_resultStandardSchemeFactory implements SchemeFactory {
      public finishFileDownload_resultStandardScheme getScheme() {
        return new finishFileDownload_resultStandardScheme();
      }
    }

    private static class finishFileDownload_resultStandardScheme extends StandardScheme<finishFileDownload_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, finishFileDownload_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, finishFileDownload_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class finishFileDownload_resultTupleSchemeFactory implements SchemeFactory {
      public finishFileDownload_resultTupleScheme getScheme() {
        return new finishFileDownload_resultTupleScheme();
      }
    }

    private static class finishFileDownload_resultTupleScheme extends TupleScheme<finishFileDownload_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, finishFileDownload_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, finishFileDownload_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class getNimbusConf_args implements org.apache.thrift.TBase<getNimbusConf_args, getNimbusConf_args._Fields>, java.io.Serializable, Cloneable, Comparable<getNimbusConf_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNimbusConf_args");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNimbusConf_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNimbusConf_argsTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNimbusConf_args.class, metaDataMap);
    }

    public getNimbusConf_args() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNimbusConf_args(getNimbusConf_args other) {
    }

    public getNimbusConf_args deepCopy() {
      return new getNimbusConf_args(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNimbusConf_args)
        return this.equals((getNimbusConf_args)that);
      return false;
    }

    public boolean equals(getNimbusConf_args that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(getNimbusConf_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNimbusConf_args(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNimbusConf_argsStandardSchemeFactory implements SchemeFactory {
      public getNimbusConf_argsStandardScheme getScheme() {
        return new getNimbusConf_argsStandardScheme();
      }
    }

    private static class getNimbusConf_argsStandardScheme extends StandardScheme<getNimbusConf_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNimbusConf_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNimbusConf_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNimbusConf_argsTupleSchemeFactory implements SchemeFactory {
      public getNimbusConf_argsTupleScheme getScheme() {
        return new getNimbusConf_argsTupleScheme();
      }
    }

    private static class getNimbusConf_argsTupleScheme extends TupleScheme<getNimbusConf_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNimbusConf_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNimbusConf_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class getNimbusConf_result implements org.apache.thrift.TBase<getNimbusConf_result, getNimbusConf_result._Fields>, java.io.Serializable, Cloneable, Comparable<getNimbusConf_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNimbusConf_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNimbusConf_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNimbusConf_resultTupleSchemeFactory());
    }

    private String success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNimbusConf_result.class, metaDataMap);
    }

    public getNimbusConf_result() {
    }

    public getNimbusConf_result(
      String success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNimbusConf_result(getNimbusConf_result other) {
      if (other.is_set_success()) {
        this.success = other.success;
      }
    }

    public getNimbusConf_result deepCopy() {
      return new getNimbusConf_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public String get_success() {
      return this.success;
    }

    public void set_success(String success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNimbusConf_result)
        return this.equals((getNimbusConf_result)that);
      return false;
    }

    public boolean equals(getNimbusConf_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getNimbusConf_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNimbusConf_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNimbusConf_resultStandardSchemeFactory implements SchemeFactory {
      public getNimbusConf_resultStandardScheme getScheme() {
        return new getNimbusConf_resultStandardScheme();
      }
    }

    private static class getNimbusConf_resultStandardScheme extends StandardScheme<getNimbusConf_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNimbusConf_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNimbusConf_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNimbusConf_resultTupleSchemeFactory implements SchemeFactory {
      public getNimbusConf_resultTupleScheme getScheme() {
        return new getNimbusConf_resultTupleScheme();
      }
    }

    private static class getNimbusConf_resultTupleScheme extends TupleScheme<getNimbusConf_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNimbusConf_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          oprot.writeString(struct.success);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNimbusConf_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getTopologyConf_args implements org.apache.thrift.TBase<getTopologyConf_args, getTopologyConf_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyConf_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyConf_args");

    private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyConf_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyConf_argsTupleSchemeFactory());
    }

    private String id; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ID((short)1, "id");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ID
            return ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ID, new org.apache.thrift.meta_data.FieldMetaData("id", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyConf_args.class, metaDataMap);
    }

    public getTopologyConf_args() {
    }

    public getTopologyConf_args(
      String id)
    {
      this();
      this.id = id;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyConf_args(getTopologyConf_args other) {
      if (other.is_set_id()) {
        this.id = other.id;
      }
    }

    public getTopologyConf_args deepCopy() {
      return new getTopologyConf_args(this);
    }

    @Override
    public void clear() {
      this.id = null;
    }

    public String get_id() {
      return this.id;
    }

    public void set_id(String id) {
      this.id = id;
    }

    public void unset_id() {
      this.id = null;
    }

    /** Returns true if field id is set (has been assigned a value) and false otherwise */
    public boolean is_set_id() {
      return this.id != null;
    }

    public void set_id_isSet(boolean value) {
      if (!value) {
        this.id = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ID:
        if (value == null) {
          unset_id();
        } else {
          set_id((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ID:
        return get_id();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ID:
        return is_set_id();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyConf_args)
        return this.equals((getTopologyConf_args)that);
      return false;
    }

    public boolean equals(getTopologyConf_args that) {
      if (that == null)
        return false;

      boolean this_present_id = true && this.is_set_id();
      boolean that_present_id = true && that.is_set_id();
      if (this_present_id || that_present_id) {
        if (!(this_present_id && that_present_id))
          return false;
        if (!this.id.equals(that.id))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_id = true && (is_set_id());
      list.add(present_id);
      if (present_id)
        list.add(id);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyConf_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_id()).compareTo(other.is_set_id());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_id()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.id, other.id);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyConf_args(");
      boolean first = true;

      sb.append("id:");
      if (this.id == null) {
        sb.append("null");
      } else {
        sb.append(this.id);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyConf_argsStandardSchemeFactory implements SchemeFactory {
      public getTopologyConf_argsStandardScheme getScheme() {
        return new getTopologyConf_argsStandardScheme();
      }
    }

    private static class getTopologyConf_argsStandardScheme extends StandardScheme<getTopologyConf_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyConf_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.id = iprot.readString();
                struct.set_id_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyConf_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.id != null) {
          oprot.writeFieldBegin(ID_FIELD_DESC);
          oprot.writeString(struct.id);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyConf_argsTupleSchemeFactory implements SchemeFactory {
      public getTopologyConf_argsTupleScheme getScheme() {
        return new getTopologyConf_argsTupleScheme();
      }
    }

    private static class getTopologyConf_argsTupleScheme extends TupleScheme<getTopologyConf_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyConf_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_id()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_id()) {
          oprot.writeString(struct.id);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyConf_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.id = iprot.readString();
          struct.set_id_isSet(true);
        }
      }
    }

  }

  public static class getTopologyConf_result implements org.apache.thrift.TBase<getTopologyConf_result, getTopologyConf_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyConf_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyConf_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyConf_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyConf_resultTupleSchemeFactory());
    }

    private String success; // required
    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyConf_result.class, metaDataMap);
    }

    public getTopologyConf_result() {
    }

    public getTopologyConf_result(
      String success,
      NotAliveException e)
    {
      this();
      this.success = success;
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyConf_result(getTopologyConf_result other) {
      if (other.is_set_success()) {
        this.success = other.success;
      }
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public getTopologyConf_result deepCopy() {
      return new getTopologyConf_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.e = null;
    }

    public String get_success() {
      return this.success;
    }

    public void set_success(String success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((String)value);
        }
        break;

      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyConf_result)
        return this.equals((getTopologyConf_result)that);
      return false;
    }

    public boolean equals(getTopologyConf_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyConf_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyConf_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyConf_resultStandardSchemeFactory implements SchemeFactory {
      public getTopologyConf_resultStandardScheme getScheme() {
        return new getTopologyConf_resultStandardScheme();
      }
    }

    private static class getTopologyConf_resultStandardScheme extends StandardScheme<getTopologyConf_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyConf_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyConf_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyConf_resultTupleSchemeFactory implements SchemeFactory {
      public getTopologyConf_resultTupleScheme getScheme() {
        return new getTopologyConf_resultTupleScheme();
      }
    }

    private static class getTopologyConf_resultTupleScheme extends TupleScheme<getTopologyConf_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyConf_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        if (struct.is_set_e()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_success()) {
          oprot.writeString(struct.success);
        }
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyConf_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.set_success_isSet(true);
        }
        if (incoming.get(1)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class getTopologyId_args implements org.apache.thrift.TBase<getTopologyId_args, getTopologyId_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyId_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyId_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyName", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyId_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyId_argsTupleSchemeFactory());
    }

    private String topologyName; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_NAME((short)1, "topologyName");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_NAME
            return TOPOLOGY_NAME;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_NAME, new org.apache.thrift.meta_data.FieldMetaData("topologyName", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyId_args.class, metaDataMap);
    }

    public getTopologyId_args() {
    }

    public getTopologyId_args(
      String topologyName)
    {
      this();
      this.topologyName = topologyName;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyId_args(getTopologyId_args other) {
      if (other.is_set_topologyName()) {
        this.topologyName = other.topologyName;
      }
    }

    public getTopologyId_args deepCopy() {
      return new getTopologyId_args(this);
    }

    @Override
    public void clear() {
      this.topologyName = null;
    }

    public String get_topologyName() {
      return this.topologyName;
    }

    public void set_topologyName(String topologyName) {
      this.topologyName = topologyName;
    }

    public void unset_topologyName() {
      this.topologyName = null;
    }

    /** Returns true if field topologyName is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyName() {
      return this.topologyName != null;
    }

    public void set_topologyName_isSet(boolean value) {
      if (!value) {
        this.topologyName = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_NAME:
        if (value == null) {
          unset_topologyName();
        } else {
          set_topologyName((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_NAME:
        return get_topologyName();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_NAME:
        return is_set_topologyName();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyId_args)
        return this.equals((getTopologyId_args)that);
      return false;
    }

    public boolean equals(getTopologyId_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyName = true && this.is_set_topologyName();
      boolean that_present_topologyName = true && that.is_set_topologyName();
      if (this_present_topologyName || that_present_topologyName) {
        if (!(this_present_topologyName && that_present_topologyName))
          return false;
        if (!this.topologyName.equals(that.topologyName))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyName = true && (is_set_topologyName());
      list.add(present_topologyName);
      if (present_topologyName)
        list.add(topologyName);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyId_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyName()).compareTo(other.is_set_topologyName());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyName()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyName, other.topologyName);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyId_args(");
      boolean first = true;

      sb.append("topologyName:");
      if (this.topologyName == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyName);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyId_argsStandardSchemeFactory implements SchemeFactory {
      public getTopologyId_argsStandardScheme getScheme() {
        return new getTopologyId_argsStandardScheme();
      }
    }

    private static class getTopologyId_argsStandardScheme extends StandardScheme<getTopologyId_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyId_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyName = iprot.readString();
                struct.set_topologyName_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyId_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyName != null) {
          oprot.writeFieldBegin(TOPOLOGY_NAME_FIELD_DESC);
          oprot.writeString(struct.topologyName);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyId_argsTupleSchemeFactory implements SchemeFactory {
      public getTopologyId_argsTupleScheme getScheme() {
        return new getTopologyId_argsTupleScheme();
      }
    }

    private static class getTopologyId_argsTupleScheme extends TupleScheme<getTopologyId_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyId_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyName()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_topologyName()) {
          oprot.writeString(struct.topologyName);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyId_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.topologyName = iprot.readString();
          struct.set_topologyName_isSet(true);
        }
      }
    }

  }

  public static class getTopologyId_result implements org.apache.thrift.TBase<getTopologyId_result, getTopologyId_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyId_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyId_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyId_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyId_resultTupleSchemeFactory());
    }

    private String success; // required
    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyId_result.class, metaDataMap);
    }

    public getTopologyId_result() {
    }

    public getTopologyId_result(
      String success,
      NotAliveException e)
    {
      this();
      this.success = success;
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyId_result(getTopologyId_result other) {
      if (other.is_set_success()) {
        this.success = other.success;
      }
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public getTopologyId_result deepCopy() {
      return new getTopologyId_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.e = null;
    }

    public String get_success() {
      return this.success;
    }

    public void set_success(String success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((String)value);
        }
        break;

      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyId_result)
        return this.equals((getTopologyId_result)that);
      return false;
    }

    public boolean equals(getTopologyId_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyId_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyId_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyId_resultStandardSchemeFactory implements SchemeFactory {
      public getTopologyId_resultStandardScheme getScheme() {
        return new getTopologyId_resultStandardScheme();
      }
    }

    private static class getTopologyId_resultStandardScheme extends StandardScheme<getTopologyId_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyId_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyId_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyId_resultTupleSchemeFactory implements SchemeFactory {
      public getTopologyId_resultTupleScheme getScheme() {
        return new getTopologyId_resultTupleScheme();
      }
    }

    private static class getTopologyId_resultTupleScheme extends TupleScheme<getTopologyId_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyId_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        if (struct.is_set_e()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_success()) {
          oprot.writeString(struct.success);
        }
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyId_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.set_success_isSet(true);
        }
        if (incoming.get(1)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class getClusterInfo_args implements org.apache.thrift.TBase<getClusterInfo_args, getClusterInfo_args._Fields>, java.io.Serializable, Cloneable, Comparable<getClusterInfo_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getClusterInfo_args");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getClusterInfo_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getClusterInfo_argsTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getClusterInfo_args.class, metaDataMap);
    }

    public getClusterInfo_args() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getClusterInfo_args(getClusterInfo_args other) {
    }

    public getClusterInfo_args deepCopy() {
      return new getClusterInfo_args(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getClusterInfo_args)
        return this.equals((getClusterInfo_args)that);
      return false;
    }

    public boolean equals(getClusterInfo_args that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(getClusterInfo_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getClusterInfo_args(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getClusterInfo_argsStandardSchemeFactory implements SchemeFactory {
      public getClusterInfo_argsStandardScheme getScheme() {
        return new getClusterInfo_argsStandardScheme();
      }
    }

    private static class getClusterInfo_argsStandardScheme extends StandardScheme<getClusterInfo_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getClusterInfo_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getClusterInfo_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getClusterInfo_argsTupleSchemeFactory implements SchemeFactory {
      public getClusterInfo_argsTupleScheme getScheme() {
        return new getClusterInfo_argsTupleScheme();
      }
    }

    private static class getClusterInfo_argsTupleScheme extends TupleScheme<getClusterInfo_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getClusterInfo_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getClusterInfo_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class getClusterInfo_result implements org.apache.thrift.TBase<getClusterInfo_result, getClusterInfo_result._Fields>, java.io.Serializable, Cloneable, Comparable<getClusterInfo_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getClusterInfo_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getClusterInfo_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getClusterInfo_resultTupleSchemeFactory());
    }

    private ClusterSummary success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, ClusterSummary.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getClusterInfo_result.class, metaDataMap);
    }

    public getClusterInfo_result() {
    }

    public getClusterInfo_result(
      ClusterSummary success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getClusterInfo_result(getClusterInfo_result other) {
      if (other.is_set_success()) {
        this.success = new ClusterSummary(other.success);
      }
    }

    public getClusterInfo_result deepCopy() {
      return new getClusterInfo_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public ClusterSummary get_success() {
      return this.success;
    }

    public void set_success(ClusterSummary success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((ClusterSummary)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getClusterInfo_result)
        return this.equals((getClusterInfo_result)that);
      return false;
    }

    public boolean equals(getClusterInfo_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getClusterInfo_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getClusterInfo_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getClusterInfo_resultStandardSchemeFactory implements SchemeFactory {
      public getClusterInfo_resultStandardScheme getScheme() {
        return new getClusterInfo_resultStandardScheme();
      }
    }

    private static class getClusterInfo_resultStandardScheme extends StandardScheme<getClusterInfo_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getClusterInfo_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new ClusterSummary();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getClusterInfo_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getClusterInfo_resultTupleSchemeFactory implements SchemeFactory {
      public getClusterInfo_resultTupleScheme getScheme() {
        return new getClusterInfo_resultTupleScheme();
      }
    }

    private static class getClusterInfo_resultTupleScheme extends TupleScheme<getClusterInfo_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getClusterInfo_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getClusterInfo_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = new ClusterSummary();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getSupervisorWorkers_args implements org.apache.thrift.TBase<getSupervisorWorkers_args, getSupervisorWorkers_args._Fields>, java.io.Serializable, Cloneable, Comparable<getSupervisorWorkers_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getSupervisorWorkers_args");

    private static final org.apache.thrift.protocol.TField HOST_FIELD_DESC = new org.apache.thrift.protocol.TField("host", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getSupervisorWorkers_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getSupervisorWorkers_argsTupleSchemeFactory());
    }

    private String host; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      HOST((short)1, "host");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // HOST
            return HOST;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.HOST, new org.apache.thrift.meta_data.FieldMetaData("host", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getSupervisorWorkers_args.class, metaDataMap);
    }

    public getSupervisorWorkers_args() {
    }

    public getSupervisorWorkers_args(
      String host)
    {
      this();
      this.host = host;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getSupervisorWorkers_args(getSupervisorWorkers_args other) {
      if (other.is_set_host()) {
        this.host = other.host;
      }
    }

    public getSupervisorWorkers_args deepCopy() {
      return new getSupervisorWorkers_args(this);
    }

    @Override
    public void clear() {
      this.host = null;
    }

    public String get_host() {
      return this.host;
    }

    public void set_host(String host) {
      this.host = host;
    }

    public void unset_host() {
      this.host = null;
    }

    /** Returns true if field host is set (has been assigned a value) and false otherwise */
    public boolean is_set_host() {
      return this.host != null;
    }

    public void set_host_isSet(boolean value) {
      if (!value) {
        this.host = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case HOST:
        if (value == null) {
          unset_host();
        } else {
          set_host((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case HOST:
        return get_host();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case HOST:
        return is_set_host();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getSupervisorWorkers_args)
        return this.equals((getSupervisorWorkers_args)that);
      return false;
    }

    public boolean equals(getSupervisorWorkers_args that) {
      if (that == null)
        return false;

      boolean this_present_host = true && this.is_set_host();
      boolean that_present_host = true && that.is_set_host();
      if (this_present_host || that_present_host) {
        if (!(this_present_host && that_present_host))
          return false;
        if (!this.host.equals(that.host))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_host = true && (is_set_host());
      list.add(present_host);
      if (present_host)
        list.add(host);

      return list.hashCode();
    }

    @Override
    public int compareTo(getSupervisorWorkers_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_host()).compareTo(other.is_set_host());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_host()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.host, other.host);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getSupervisorWorkers_args(");
      boolean first = true;

      sb.append("host:");
      if (this.host == null) {
        sb.append("null");
      } else {
        sb.append(this.host);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getSupervisorWorkers_argsStandardSchemeFactory implements SchemeFactory {
      public getSupervisorWorkers_argsStandardScheme getScheme() {
        return new getSupervisorWorkers_argsStandardScheme();
      }
    }

    private static class getSupervisorWorkers_argsStandardScheme extends StandardScheme<getSupervisorWorkers_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getSupervisorWorkers_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // HOST
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.host = iprot.readString();
                struct.set_host_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getSupervisorWorkers_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.host != null) {
          oprot.writeFieldBegin(HOST_FIELD_DESC);
          oprot.writeString(struct.host);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getSupervisorWorkers_argsTupleSchemeFactory implements SchemeFactory {
      public getSupervisorWorkers_argsTupleScheme getScheme() {
        return new getSupervisorWorkers_argsTupleScheme();
      }
    }

    private static class getSupervisorWorkers_argsTupleScheme extends TupleScheme<getSupervisorWorkers_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getSupervisorWorkers_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_host()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_host()) {
          oprot.writeString(struct.host);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getSupervisorWorkers_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.host = iprot.readString();
          struct.set_host_isSet(true);
        }
      }
    }

  }

  public static class getSupervisorWorkers_result implements org.apache.thrift.TBase<getSupervisorWorkers_result, getSupervisorWorkers_result._Fields>, java.io.Serializable, Cloneable, Comparable<getSupervisorWorkers_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getSupervisorWorkers_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getSupervisorWorkers_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getSupervisorWorkers_resultTupleSchemeFactory());
    }

    private SupervisorWorkers success; // required
    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, SupervisorWorkers.class)));
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getSupervisorWorkers_result.class, metaDataMap);
    }

    public getSupervisorWorkers_result() {
    }

    public getSupervisorWorkers_result(
      SupervisorWorkers success,
      NotAliveException e)
    {
      this();
      this.success = success;
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getSupervisorWorkers_result(getSupervisorWorkers_result other) {
      if (other.is_set_success()) {
        this.success = new SupervisorWorkers(other.success);
      }
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public getSupervisorWorkers_result deepCopy() {
      return new getSupervisorWorkers_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.e = null;
    }

    public SupervisorWorkers get_success() {
      return this.success;
    }

    public void set_success(SupervisorWorkers success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((SupervisorWorkers)value);
        }
        break;

      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getSupervisorWorkers_result)
        return this.equals((getSupervisorWorkers_result)that);
      return false;
    }

    public boolean equals(getSupervisorWorkers_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(getSupervisorWorkers_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getSupervisorWorkers_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getSupervisorWorkers_resultStandardSchemeFactory implements SchemeFactory {
      public getSupervisorWorkers_resultStandardScheme getScheme() {
        return new getSupervisorWorkers_resultStandardScheme();
      }
    }

    private static class getSupervisorWorkers_resultStandardScheme extends StandardScheme<getSupervisorWorkers_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getSupervisorWorkers_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new SupervisorWorkers();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getSupervisorWorkers_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getSupervisorWorkers_resultTupleSchemeFactory implements SchemeFactory {
      public getSupervisorWorkers_resultTupleScheme getScheme() {
        return new getSupervisorWorkers_resultTupleScheme();
      }
    }

    private static class getSupervisorWorkers_resultTupleScheme extends TupleScheme<getSupervisorWorkers_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getSupervisorWorkers_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        if (struct.is_set_e()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getSupervisorWorkers_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new SupervisorWorkers();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
        if (incoming.get(1)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class getTopologyInfo_args implements org.apache.thrift.TBase<getTopologyInfo_args, getTopologyInfo_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyInfo_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyInfo_args");

    private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyInfo_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyInfo_argsTupleSchemeFactory());
    }

    private String id; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ID((short)1, "id");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ID
            return ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ID, new org.apache.thrift.meta_data.FieldMetaData("id", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyInfo_args.class, metaDataMap);
    }

    public getTopologyInfo_args() {
    }

    public getTopologyInfo_args(
      String id)
    {
      this();
      this.id = id;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyInfo_args(getTopologyInfo_args other) {
      if (other.is_set_id()) {
        this.id = other.id;
      }
    }

    public getTopologyInfo_args deepCopy() {
      return new getTopologyInfo_args(this);
    }

    @Override
    public void clear() {
      this.id = null;
    }

    public String get_id() {
      return this.id;
    }

    public void set_id(String id) {
      this.id = id;
    }

    public void unset_id() {
      this.id = null;
    }

    /** Returns true if field id is set (has been assigned a value) and false otherwise */
    public boolean is_set_id() {
      return this.id != null;
    }

    public void set_id_isSet(boolean value) {
      if (!value) {
        this.id = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ID:
        if (value == null) {
          unset_id();
        } else {
          set_id((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ID:
        return get_id();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ID:
        return is_set_id();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyInfo_args)
        return this.equals((getTopologyInfo_args)that);
      return false;
    }

    public boolean equals(getTopologyInfo_args that) {
      if (that == null)
        return false;

      boolean this_present_id = true && this.is_set_id();
      boolean that_present_id = true && that.is_set_id();
      if (this_present_id || that_present_id) {
        if (!(this_present_id && that_present_id))
          return false;
        if (!this.id.equals(that.id))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_id = true && (is_set_id());
      list.add(present_id);
      if (present_id)
        list.add(id);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyInfo_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_id()).compareTo(other.is_set_id());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_id()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.id, other.id);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyInfo_args(");
      boolean first = true;

      sb.append("id:");
      if (this.id == null) {
        sb.append("null");
      } else {
        sb.append(this.id);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyInfo_argsStandardSchemeFactory implements SchemeFactory {
      public getTopologyInfo_argsStandardScheme getScheme() {
        return new getTopologyInfo_argsStandardScheme();
      }
    }

    private static class getTopologyInfo_argsStandardScheme extends StandardScheme<getTopologyInfo_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyInfo_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.id = iprot.readString();
                struct.set_id_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyInfo_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.id != null) {
          oprot.writeFieldBegin(ID_FIELD_DESC);
          oprot.writeString(struct.id);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyInfo_argsTupleSchemeFactory implements SchemeFactory {
      public getTopologyInfo_argsTupleScheme getScheme() {
        return new getTopologyInfo_argsTupleScheme();
      }
    }

    private static class getTopologyInfo_argsTupleScheme extends TupleScheme<getTopologyInfo_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyInfo_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_id()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_id()) {
          oprot.writeString(struct.id);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyInfo_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.id = iprot.readString();
          struct.set_id_isSet(true);
        }
      }
    }

  }

  public static class getTopologyInfo_result implements org.apache.thrift.TBase<getTopologyInfo_result, getTopologyInfo_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyInfo_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyInfo_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyInfo_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyInfo_resultTupleSchemeFactory());
    }

    private TopologyInfo success; // required
    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TopologyInfo.class)));
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyInfo_result.class, metaDataMap);
    }

    public getTopologyInfo_result() {
    }

    public getTopologyInfo_result(
      TopologyInfo success,
      NotAliveException e)
    {
      this();
      this.success = success;
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyInfo_result(getTopologyInfo_result other) {
      if (other.is_set_success()) {
        this.success = new TopologyInfo(other.success);
      }
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public getTopologyInfo_result deepCopy() {
      return new getTopologyInfo_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.e = null;
    }

    public TopologyInfo get_success() {
      return this.success;
    }

    public void set_success(TopologyInfo success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((TopologyInfo)value);
        }
        break;

      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyInfo_result)
        return this.equals((getTopologyInfo_result)that);
      return false;
    }

    public boolean equals(getTopologyInfo_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyInfo_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyInfo_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyInfo_resultStandardSchemeFactory implements SchemeFactory {
      public getTopologyInfo_resultStandardScheme getScheme() {
        return new getTopologyInfo_resultStandardScheme();
      }
    }

    private static class getTopologyInfo_resultStandardScheme extends StandardScheme<getTopologyInfo_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyInfo_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new TopologyInfo();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyInfo_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyInfo_resultTupleSchemeFactory implements SchemeFactory {
      public getTopologyInfo_resultTupleScheme getScheme() {
        return new getTopologyInfo_resultTupleScheme();
      }
    }

    private static class getTopologyInfo_resultTupleScheme extends TupleScheme<getTopologyInfo_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyInfo_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        if (struct.is_set_e()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyInfo_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new TopologyInfo();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
        if (incoming.get(1)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class getTopologyInfoByName_args implements org.apache.thrift.TBase<getTopologyInfoByName_args, getTopologyInfoByName_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyInfoByName_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyInfoByName_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyName", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyInfoByName_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyInfoByName_argsTupleSchemeFactory());
    }

    private String topologyName; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_NAME((short)1, "topologyName");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_NAME
            return TOPOLOGY_NAME;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_NAME, new org.apache.thrift.meta_data.FieldMetaData("topologyName", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyInfoByName_args.class, metaDataMap);
    }

    public getTopologyInfoByName_args() {
    }

    public getTopologyInfoByName_args(
      String topologyName)
    {
      this();
      this.topologyName = topologyName;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyInfoByName_args(getTopologyInfoByName_args other) {
      if (other.is_set_topologyName()) {
        this.topologyName = other.topologyName;
      }
    }

    public getTopologyInfoByName_args deepCopy() {
      return new getTopologyInfoByName_args(this);
    }

    @Override
    public void clear() {
      this.topologyName = null;
    }

    public String get_topologyName() {
      return this.topologyName;
    }

    public void set_topologyName(String topologyName) {
      this.topologyName = topologyName;
    }

    public void unset_topologyName() {
      this.topologyName = null;
    }

    /** Returns true if field topologyName is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyName() {
      return this.topologyName != null;
    }

    public void set_topologyName_isSet(boolean value) {
      if (!value) {
        this.topologyName = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_NAME:
        if (value == null) {
          unset_topologyName();
        } else {
          set_topologyName((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_NAME:
        return get_topologyName();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_NAME:
        return is_set_topologyName();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyInfoByName_args)
        return this.equals((getTopologyInfoByName_args)that);
      return false;
    }

    public boolean equals(getTopologyInfoByName_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyName = true && this.is_set_topologyName();
      boolean that_present_topologyName = true && that.is_set_topologyName();
      if (this_present_topologyName || that_present_topologyName) {
        if (!(this_present_topologyName && that_present_topologyName))
          return false;
        if (!this.topologyName.equals(that.topologyName))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyName = true && (is_set_topologyName());
      list.add(present_topologyName);
      if (present_topologyName)
        list.add(topologyName);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyInfoByName_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyName()).compareTo(other.is_set_topologyName());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyName()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyName, other.topologyName);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyInfoByName_args(");
      boolean first = true;

      sb.append("topologyName:");
      if (this.topologyName == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyName);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyInfoByName_argsStandardSchemeFactory implements SchemeFactory {
      public getTopologyInfoByName_argsStandardScheme getScheme() {
        return new getTopologyInfoByName_argsStandardScheme();
      }
    }

    private static class getTopologyInfoByName_argsStandardScheme extends StandardScheme<getTopologyInfoByName_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyInfoByName_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyName = iprot.readString();
                struct.set_topologyName_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyInfoByName_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyName != null) {
          oprot.writeFieldBegin(TOPOLOGY_NAME_FIELD_DESC);
          oprot.writeString(struct.topologyName);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyInfoByName_argsTupleSchemeFactory implements SchemeFactory {
      public getTopologyInfoByName_argsTupleScheme getScheme() {
        return new getTopologyInfoByName_argsTupleScheme();
      }
    }

    private static class getTopologyInfoByName_argsTupleScheme extends TupleScheme<getTopologyInfoByName_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyInfoByName_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyName()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_topologyName()) {
          oprot.writeString(struct.topologyName);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyInfoByName_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.topologyName = iprot.readString();
          struct.set_topologyName_isSet(true);
        }
      }
    }

  }

  public static class getTopologyInfoByName_result implements org.apache.thrift.TBase<getTopologyInfoByName_result, getTopologyInfoByName_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyInfoByName_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyInfoByName_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyInfoByName_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyInfoByName_resultTupleSchemeFactory());
    }

    private TopologyInfo success; // required
    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TopologyInfo.class)));
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyInfoByName_result.class, metaDataMap);
    }

    public getTopologyInfoByName_result() {
    }

    public getTopologyInfoByName_result(
      TopologyInfo success,
      NotAliveException e)
    {
      this();
      this.success = success;
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyInfoByName_result(getTopologyInfoByName_result other) {
      if (other.is_set_success()) {
        this.success = new TopologyInfo(other.success);
      }
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public getTopologyInfoByName_result deepCopy() {
      return new getTopologyInfoByName_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.e = null;
    }

    public TopologyInfo get_success() {
      return this.success;
    }

    public void set_success(TopologyInfo success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((TopologyInfo)value);
        }
        break;

      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyInfoByName_result)
        return this.equals((getTopologyInfoByName_result)that);
      return false;
    }

    public boolean equals(getTopologyInfoByName_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyInfoByName_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyInfoByName_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyInfoByName_resultStandardSchemeFactory implements SchemeFactory {
      public getTopologyInfoByName_resultStandardScheme getScheme() {
        return new getTopologyInfoByName_resultStandardScheme();
      }
    }

    private static class getTopologyInfoByName_resultStandardScheme extends StandardScheme<getTopologyInfoByName_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyInfoByName_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new TopologyInfo();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyInfoByName_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyInfoByName_resultTupleSchemeFactory implements SchemeFactory {
      public getTopologyInfoByName_resultTupleScheme getScheme() {
        return new getTopologyInfoByName_resultTupleScheme();
      }
    }

    private static class getTopologyInfoByName_resultTupleScheme extends TupleScheme<getTopologyInfoByName_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyInfoByName_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        if (struct.is_set_e()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyInfoByName_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new TopologyInfo();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
        if (incoming.get(1)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class getTopology_args implements org.apache.thrift.TBase<getTopology_args, getTopology_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTopology_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopology_args");

    private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopology_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopology_argsTupleSchemeFactory());
    }

    private String id; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ID((short)1, "id");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ID
            return ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ID, new org.apache.thrift.meta_data.FieldMetaData("id", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopology_args.class, metaDataMap);
    }

    public getTopology_args() {
    }

    public getTopology_args(
      String id)
    {
      this();
      this.id = id;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopology_args(getTopology_args other) {
      if (other.is_set_id()) {
        this.id = other.id;
      }
    }

    public getTopology_args deepCopy() {
      return new getTopology_args(this);
    }

    @Override
    public void clear() {
      this.id = null;
    }

    public String get_id() {
      return this.id;
    }

    public void set_id(String id) {
      this.id = id;
    }

    public void unset_id() {
      this.id = null;
    }

    /** Returns true if field id is set (has been assigned a value) and false otherwise */
    public boolean is_set_id() {
      return this.id != null;
    }

    public void set_id_isSet(boolean value) {
      if (!value) {
        this.id = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ID:
        if (value == null) {
          unset_id();
        } else {
          set_id((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ID:
        return get_id();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ID:
        return is_set_id();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopology_args)
        return this.equals((getTopology_args)that);
      return false;
    }

    public boolean equals(getTopology_args that) {
      if (that == null)
        return false;

      boolean this_present_id = true && this.is_set_id();
      boolean that_present_id = true && that.is_set_id();
      if (this_present_id || that_present_id) {
        if (!(this_present_id && that_present_id))
          return false;
        if (!this.id.equals(that.id))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_id = true && (is_set_id());
      list.add(present_id);
      if (present_id)
        list.add(id);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopology_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_id()).compareTo(other.is_set_id());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_id()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.id, other.id);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopology_args(");
      boolean first = true;

      sb.append("id:");
      if (this.id == null) {
        sb.append("null");
      } else {
        sb.append(this.id);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopology_argsStandardSchemeFactory implements SchemeFactory {
      public getTopology_argsStandardScheme getScheme() {
        return new getTopology_argsStandardScheme();
      }
    }

    private static class getTopology_argsStandardScheme extends StandardScheme<getTopology_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopology_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.id = iprot.readString();
                struct.set_id_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopology_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.id != null) {
          oprot.writeFieldBegin(ID_FIELD_DESC);
          oprot.writeString(struct.id);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopology_argsTupleSchemeFactory implements SchemeFactory {
      public getTopology_argsTupleScheme getScheme() {
        return new getTopology_argsTupleScheme();
      }
    }

    private static class getTopology_argsTupleScheme extends TupleScheme<getTopology_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopology_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_id()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_id()) {
          oprot.writeString(struct.id);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopology_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.id = iprot.readString();
          struct.set_id_isSet(true);
        }
      }
    }

  }

  public static class getTopology_result implements org.apache.thrift.TBase<getTopology_result, getTopology_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTopology_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopology_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopology_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopology_resultTupleSchemeFactory());
    }

    private StormTopology success; // required
    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, StormTopology.class)));
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopology_result.class, metaDataMap);
    }

    public getTopology_result() {
    }

    public getTopology_result(
      StormTopology success,
      NotAliveException e)
    {
      this();
      this.success = success;
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopology_result(getTopology_result other) {
      if (other.is_set_success()) {
        this.success = new StormTopology(other.success);
      }
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public getTopology_result deepCopy() {
      return new getTopology_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.e = null;
    }

    public StormTopology get_success() {
      return this.success;
    }

    public void set_success(StormTopology success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((StormTopology)value);
        }
        break;

      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopology_result)
        return this.equals((getTopology_result)that);
      return false;
    }

    public boolean equals(getTopology_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopology_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopology_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopology_resultStandardSchemeFactory implements SchemeFactory {
      public getTopology_resultStandardScheme getScheme() {
        return new getTopology_resultStandardScheme();
      }
    }

    private static class getTopology_resultStandardScheme extends StandardScheme<getTopology_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopology_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new StormTopology();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopology_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopology_resultTupleSchemeFactory implements SchemeFactory {
      public getTopology_resultTupleScheme getScheme() {
        return new getTopology_resultTupleScheme();
      }
    }

    private static class getTopology_resultTupleScheme extends TupleScheme<getTopology_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopology_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        if (struct.is_set_e()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopology_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new StormTopology();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
        if (incoming.get(1)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class getUserTopology_args implements org.apache.thrift.TBase<getUserTopology_args, getUserTopology_args._Fields>, java.io.Serializable, Cloneable, Comparable<getUserTopology_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getUserTopology_args");

    private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getUserTopology_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getUserTopology_argsTupleSchemeFactory());
    }

    private String id; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ID((short)1, "id");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ID
            return ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ID, new org.apache.thrift.meta_data.FieldMetaData("id", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getUserTopology_args.class, metaDataMap);
    }

    public getUserTopology_args() {
    }

    public getUserTopology_args(
      String id)
    {
      this();
      this.id = id;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getUserTopology_args(getUserTopology_args other) {
      if (other.is_set_id()) {
        this.id = other.id;
      }
    }

    public getUserTopology_args deepCopy() {
      return new getUserTopology_args(this);
    }

    @Override
    public void clear() {
      this.id = null;
    }

    public String get_id() {
      return this.id;
    }

    public void set_id(String id) {
      this.id = id;
    }

    public void unset_id() {
      this.id = null;
    }

    /** Returns true if field id is set (has been assigned a value) and false otherwise */
    public boolean is_set_id() {
      return this.id != null;
    }

    public void set_id_isSet(boolean value) {
      if (!value) {
        this.id = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ID:
        if (value == null) {
          unset_id();
        } else {
          set_id((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ID:
        return get_id();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ID:
        return is_set_id();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getUserTopology_args)
        return this.equals((getUserTopology_args)that);
      return false;
    }

    public boolean equals(getUserTopology_args that) {
      if (that == null)
        return false;

      boolean this_present_id = true && this.is_set_id();
      boolean that_present_id = true && that.is_set_id();
      if (this_present_id || that_present_id) {
        if (!(this_present_id && that_present_id))
          return false;
        if (!this.id.equals(that.id))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_id = true && (is_set_id());
      list.add(present_id);
      if (present_id)
        list.add(id);

      return list.hashCode();
    }

    @Override
    public int compareTo(getUserTopology_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_id()).compareTo(other.is_set_id());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_id()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.id, other.id);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getUserTopology_args(");
      boolean first = true;

      sb.append("id:");
      if (this.id == null) {
        sb.append("null");
      } else {
        sb.append(this.id);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getUserTopology_argsStandardSchemeFactory implements SchemeFactory {
      public getUserTopology_argsStandardScheme getScheme() {
        return new getUserTopology_argsStandardScheme();
      }
    }

    private static class getUserTopology_argsStandardScheme extends StandardScheme<getUserTopology_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getUserTopology_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.id = iprot.readString();
                struct.set_id_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getUserTopology_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.id != null) {
          oprot.writeFieldBegin(ID_FIELD_DESC);
          oprot.writeString(struct.id);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getUserTopology_argsTupleSchemeFactory implements SchemeFactory {
      public getUserTopology_argsTupleScheme getScheme() {
        return new getUserTopology_argsTupleScheme();
      }
    }

    private static class getUserTopology_argsTupleScheme extends TupleScheme<getUserTopology_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getUserTopology_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_id()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_id()) {
          oprot.writeString(struct.id);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getUserTopology_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.id = iprot.readString();
          struct.set_id_isSet(true);
        }
      }
    }

  }

  public static class getUserTopology_result implements org.apache.thrift.TBase<getUserTopology_result, getUserTopology_result._Fields>, java.io.Serializable, Cloneable, Comparable<getUserTopology_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getUserTopology_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getUserTopology_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getUserTopology_resultTupleSchemeFactory());
    }

    private StormTopology success; // required
    private NotAliveException e; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      E((short)1, "e");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // E
            return E;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, StormTopology.class)));
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getUserTopology_result.class, metaDataMap);
    }

    public getUserTopology_result() {
    }

    public getUserTopology_result(
      StormTopology success,
      NotAliveException e)
    {
      this();
      this.success = success;
      this.e = e;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getUserTopology_result(getUserTopology_result other) {
      if (other.is_set_success()) {
        this.success = new StormTopology(other.success);
      }
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
    }

    public getUserTopology_result deepCopy() {
      return new getUserTopology_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.e = null;
    }

    public StormTopology get_success() {
      return this.success;
    }

    public void set_success(StormTopology success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((StormTopology)value);
        }
        break;

      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      case E:
        return get_e();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      case E:
        return is_set_e();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getUserTopology_result)
        return this.equals((getUserTopology_result)that);
      return false;
    }

    public boolean equals(getUserTopology_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      return list.hashCode();
    }

    @Override
    public int compareTo(getUserTopology_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getUserTopology_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getUserTopology_resultStandardSchemeFactory implements SchemeFactory {
      public getUserTopology_resultStandardScheme getScheme() {
        return new getUserTopology_resultStandardScheme();
      }
    }

    private static class getUserTopology_resultStandardScheme extends StandardScheme<getUserTopology_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getUserTopology_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new StormTopology();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getUserTopology_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getUserTopology_resultTupleSchemeFactory implements SchemeFactory {
      public getUserTopology_resultTupleScheme getScheme() {
        return new getUserTopology_resultTupleScheme();
      }
    }

    private static class getUserTopology_resultTupleScheme extends TupleScheme<getUserTopology_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getUserTopology_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        if (struct.is_set_e()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getUserTopology_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new StormTopology();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
        if (incoming.get(1)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
      }
    }

  }

  public static class uploadTopologyMetrics_args implements org.apache.thrift.TBase<uploadTopologyMetrics_args, uploadTopologyMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<uploadTopologyMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("uploadTopologyMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField TOPOLOGY_METRICS_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyMetrics", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new uploadTopologyMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new uploadTopologyMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private TopologyMetric topologyMetrics; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      TOPOLOGY_METRICS((short)2, "topologyMetrics");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // TOPOLOGY_METRICS
            return TOPOLOGY_METRICS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.TOPOLOGY_METRICS, new org.apache.thrift.meta_data.FieldMetaData("topologyMetrics", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TopologyMetric.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(uploadTopologyMetrics_args.class, metaDataMap);
    }

    public uploadTopologyMetrics_args() {
    }

    public uploadTopologyMetrics_args(
      String topologyId,
      TopologyMetric topologyMetrics)
    {
      this();
      this.topologyId = topologyId;
      this.topologyMetrics = topologyMetrics;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public uploadTopologyMetrics_args(uploadTopologyMetrics_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      if (other.is_set_topologyMetrics()) {
        this.topologyMetrics = new TopologyMetric(other.topologyMetrics);
      }
    }

    public uploadTopologyMetrics_args deepCopy() {
      return new uploadTopologyMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      this.topologyMetrics = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public TopologyMetric get_topologyMetrics() {
      return this.topologyMetrics;
    }

    public void set_topologyMetrics(TopologyMetric topologyMetrics) {
      this.topologyMetrics = topologyMetrics;
    }

    public void unset_topologyMetrics() {
      this.topologyMetrics = null;
    }

    /** Returns true if field topologyMetrics is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyMetrics() {
      return this.topologyMetrics != null;
    }

    public void set_topologyMetrics_isSet(boolean value) {
      if (!value) {
        this.topologyMetrics = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case TOPOLOGY_METRICS:
        if (value == null) {
          unset_topologyMetrics();
        } else {
          set_topologyMetrics((TopologyMetric)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case TOPOLOGY_METRICS:
        return get_topologyMetrics();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case TOPOLOGY_METRICS:
        return is_set_topologyMetrics();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof uploadTopologyMetrics_args)
        return this.equals((uploadTopologyMetrics_args)that);
      return false;
    }

    public boolean equals(uploadTopologyMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_topologyMetrics = true && this.is_set_topologyMetrics();
      boolean that_present_topologyMetrics = true && that.is_set_topologyMetrics();
      if (this_present_topologyMetrics || that_present_topologyMetrics) {
        if (!(this_present_topologyMetrics && that_present_topologyMetrics))
          return false;
        if (!this.topologyMetrics.equals(that.topologyMetrics))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_topologyMetrics = true && (is_set_topologyMetrics());
      list.add(present_topologyMetrics);
      if (present_topologyMetrics)
        list.add(topologyMetrics);

      return list.hashCode();
    }

    @Override
    public int compareTo(uploadTopologyMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_topologyMetrics()).compareTo(other.is_set_topologyMetrics());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyMetrics()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyMetrics, other.topologyMetrics);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("uploadTopologyMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("topologyMetrics:");
      if (this.topologyMetrics == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyMetrics);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (topologyMetrics != null) {
        topologyMetrics.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class uploadTopologyMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public uploadTopologyMetrics_argsStandardScheme getScheme() {
        return new uploadTopologyMetrics_argsStandardScheme();
      }
    }

    private static class uploadTopologyMetrics_argsStandardScheme extends StandardScheme<uploadTopologyMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, uploadTopologyMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // TOPOLOGY_METRICS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.topologyMetrics = new TopologyMetric();
                struct.topologyMetrics.read(iprot);
                struct.set_topologyMetrics_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, uploadTopologyMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        if (struct.topologyMetrics != null) {
          oprot.writeFieldBegin(TOPOLOGY_METRICS_FIELD_DESC);
          struct.topologyMetrics.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class uploadTopologyMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public uploadTopologyMetrics_argsTupleScheme getScheme() {
        return new uploadTopologyMetrics_argsTupleScheme();
      }
    }

    private static class uploadTopologyMetrics_argsTupleScheme extends TupleScheme<uploadTopologyMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, uploadTopologyMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_topologyMetrics()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_topologyMetrics()) {
          struct.topologyMetrics.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, uploadTopologyMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          struct.topologyMetrics = new TopologyMetric();
          struct.topologyMetrics.read(iprot);
          struct.set_topologyMetrics_isSet(true);
        }
      }
    }

  }

  public static class uploadTopologyMetrics_result implements org.apache.thrift.TBase<uploadTopologyMetrics_result, uploadTopologyMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<uploadTopologyMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("uploadTopologyMetrics_result");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new uploadTopologyMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new uploadTopologyMetrics_resultTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(uploadTopologyMetrics_result.class, metaDataMap);
    }

    public uploadTopologyMetrics_result() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public uploadTopologyMetrics_result(uploadTopologyMetrics_result other) {
    }

    public uploadTopologyMetrics_result deepCopy() {
      return new uploadTopologyMetrics_result(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof uploadTopologyMetrics_result)
        return this.equals((uploadTopologyMetrics_result)that);
      return false;
    }

    public boolean equals(uploadTopologyMetrics_result that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(uploadTopologyMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("uploadTopologyMetrics_result(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class uploadTopologyMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public uploadTopologyMetrics_resultStandardScheme getScheme() {
        return new uploadTopologyMetrics_resultStandardScheme();
      }
    }

    private static class uploadTopologyMetrics_resultStandardScheme extends StandardScheme<uploadTopologyMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, uploadTopologyMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, uploadTopologyMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class uploadTopologyMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public uploadTopologyMetrics_resultTupleScheme getScheme() {
        return new uploadTopologyMetrics_resultTupleScheme();
      }
    }

    private static class uploadTopologyMetrics_resultTupleScheme extends TupleScheme<uploadTopologyMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, uploadTopologyMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, uploadTopologyMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class registerMetrics_args implements org.apache.thrift.TBase<registerMetrics_args, registerMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<registerMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("registerMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField METRICS_FIELD_DESC = new org.apache.thrift.protocol.TField("metrics", org.apache.thrift.protocol.TType.SET, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new registerMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new registerMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private Set<String> metrics; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      METRICS((short)2, "metrics");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // METRICS
            return METRICS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.METRICS, new org.apache.thrift.meta_data.FieldMetaData("metrics", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.SetMetaData(org.apache.thrift.protocol.TType.SET, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(registerMetrics_args.class, metaDataMap);
    }

    public registerMetrics_args() {
    }

    public registerMetrics_args(
      String topologyId,
      Set<String> metrics)
    {
      this();
      this.topologyId = topologyId;
      this.metrics = metrics;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public registerMetrics_args(registerMetrics_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      if (other.is_set_metrics()) {
        Set<String> __this__metrics = new HashSet<String>(other.metrics);
        this.metrics = __this__metrics;
      }
    }

    public registerMetrics_args deepCopy() {
      return new registerMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      this.metrics = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public int get_metrics_size() {
      return (this.metrics == null) ? 0 : this.metrics.size();
    }

    public java.util.Iterator<String> get_metrics_iterator() {
      return (this.metrics == null) ? null : this.metrics.iterator();
    }

    public void add_to_metrics(String elem) {
      if (this.metrics == null) {
        this.metrics = new HashSet<String>();
      }
      this.metrics.add(elem);
    }

    public Set<String> get_metrics() {
      return this.metrics;
    }

    public void set_metrics(Set<String> metrics) {
      this.metrics = metrics;
    }

    public void unset_metrics() {
      this.metrics = null;
    }

    /** Returns true if field metrics is set (has been assigned a value) and false otherwise */
    public boolean is_set_metrics() {
      return this.metrics != null;
    }

    public void set_metrics_isSet(boolean value) {
      if (!value) {
        this.metrics = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case METRICS:
        if (value == null) {
          unset_metrics();
        } else {
          set_metrics((Set<String>)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case METRICS:
        return get_metrics();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case METRICS:
        return is_set_metrics();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof registerMetrics_args)
        return this.equals((registerMetrics_args)that);
      return false;
    }

    public boolean equals(registerMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_metrics = true && this.is_set_metrics();
      boolean that_present_metrics = true && that.is_set_metrics();
      if (this_present_metrics || that_present_metrics) {
        if (!(this_present_metrics && that_present_metrics))
          return false;
        if (!this.metrics.equals(that.metrics))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_metrics = true && (is_set_metrics());
      list.add(present_metrics);
      if (present_metrics)
        list.add(metrics);

      return list.hashCode();
    }

    @Override
    public int compareTo(registerMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_metrics()).compareTo(other.is_set_metrics());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_metrics()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.metrics, other.metrics);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("registerMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("metrics:");
      if (this.metrics == null) {
        sb.append("null");
      } else {
        sb.append(this.metrics);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class registerMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public registerMetrics_argsStandardScheme getScheme() {
        return new registerMetrics_argsStandardScheme();
      }
    }

    private static class registerMetrics_argsStandardScheme extends StandardScheme<registerMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, registerMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // METRICS
              if (schemeField.type == org.apache.thrift.protocol.TType.SET) {
                {
                  org.apache.thrift.protocol.TSet _set232 = iprot.readSetBegin();
                  struct.metrics = new HashSet<String>(2*_set232.size);
                  String _elem233;
                  for (int _i234 = 0; _i234 < _set232.size; ++_i234)
                  {
                    _elem233 = iprot.readString();
                    struct.metrics.add(_elem233);
                  }
                  iprot.readSetEnd();
                }
                struct.set_metrics_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, registerMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        if (struct.metrics != null) {
          oprot.writeFieldBegin(METRICS_FIELD_DESC);
          {
            oprot.writeSetBegin(new org.apache.thrift.protocol.TSet(org.apache.thrift.protocol.TType.STRING, struct.metrics.size()));
            for (String _iter235 : struct.metrics)
            {
              oprot.writeString(_iter235);
            }
            oprot.writeSetEnd();
          }
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class registerMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public registerMetrics_argsTupleScheme getScheme() {
        return new registerMetrics_argsTupleScheme();
      }
    }

    private static class registerMetrics_argsTupleScheme extends TupleScheme<registerMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, registerMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_metrics()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_metrics()) {
          {
            oprot.writeI32(struct.metrics.size());
            for (String _iter236 : struct.metrics)
            {
              oprot.writeString(_iter236);
            }
          }
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, registerMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          {
            org.apache.thrift.protocol.TSet _set237 = new org.apache.thrift.protocol.TSet(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
            struct.metrics = new HashSet<String>(2*_set237.size);
            String _elem238;
            for (int _i239 = 0; _i239 < _set237.size; ++_i239)
            {
              _elem238 = iprot.readString();
              struct.metrics.add(_elem238);
            }
          }
          struct.set_metrics_isSet(true);
        }
      }
    }

  }

  public static class registerMetrics_result implements org.apache.thrift.TBase<registerMetrics_result, registerMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<registerMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("registerMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.MAP, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new registerMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new registerMetrics_resultTupleSchemeFactory());
    }

    private Map<String,Long> success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING), 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64))));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(registerMetrics_result.class, metaDataMap);
    }

    public registerMetrics_result() {
    }

    public registerMetrics_result(
      Map<String,Long> success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public registerMetrics_result(registerMetrics_result other) {
      if (other.is_set_success()) {
        Map<String,Long> __this__success = new HashMap<String,Long>(other.success);
        this.success = __this__success;
      }
    }

    public registerMetrics_result deepCopy() {
      return new registerMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public int get_success_size() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public void put_to_success(String key, long val) {
      if (this.success == null) {
        this.success = new HashMap<String,Long>();
      }
      this.success.put(key, val);
    }

    public Map<String,Long> get_success() {
      return this.success;
    }

    public void set_success(Map<String,Long> success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((Map<String,Long>)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof registerMetrics_result)
        return this.equals((registerMetrics_result)that);
      return false;
    }

    public boolean equals(registerMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(registerMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("registerMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class registerMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public registerMetrics_resultStandardScheme getScheme() {
        return new registerMetrics_resultStandardScheme();
      }
    }

    private static class registerMetrics_resultStandardScheme extends StandardScheme<registerMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, registerMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.MAP) {
                {
                  org.apache.thrift.protocol.TMap _map240 = iprot.readMapBegin();
                  struct.success = new HashMap<String,Long>(2*_map240.size);
                  String _key241;
                  long _val242;
                  for (int _i243 = 0; _i243 < _map240.size; ++_i243)
                  {
                    _key241 = iprot.readString();
                    _val242 = iprot.readI64();
                    struct.success.put(_key241, _val242);
                  }
                  iprot.readMapEnd();
                }
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, registerMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.I64, struct.success.size()));
            for (Map.Entry<String, Long> _iter244 : struct.success.entrySet())
            {
              oprot.writeString(_iter244.getKey());
              oprot.writeI64(_iter244.getValue());
            }
            oprot.writeMapEnd();
          }
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class registerMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public registerMetrics_resultTupleScheme getScheme() {
        return new registerMetrics_resultTupleScheme();
      }
    }

    private static class registerMetrics_resultTupleScheme extends TupleScheme<registerMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, registerMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          {
            oprot.writeI32(struct.success.size());
            for (Map.Entry<String, Long> _iter245 : struct.success.entrySet())
            {
              oprot.writeString(_iter245.getKey());
              oprot.writeI64(_iter245.getValue());
            }
          }
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, registerMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TMap _map246 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.I64, iprot.readI32());
            struct.success = new HashMap<String,Long>(2*_map246.size);
            String _key247;
            long _val248;
            for (int _i249 = 0; _i249 < _map246.size; ++_i249)
            {
              _key247 = iprot.readString();
              _val248 = iprot.readI64();
              struct.success.put(_key247, _val248);
            }
          }
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getTopologyMetrics_args implements org.apache.thrift.TBase<getTopologyMetrics_args, getTopologyMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyMetrics_args.class, metaDataMap);
    }

    public getTopologyMetrics_args() {
    }

    public getTopologyMetrics_args(
      String topologyId)
    {
      this();
      this.topologyId = topologyId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyMetrics_args(getTopologyMetrics_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
    }

    public getTopologyMetrics_args deepCopy() {
      return new getTopologyMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyMetrics_args)
        return this.equals((getTopologyMetrics_args)that);
      return false;
    }

    public boolean equals(getTopologyMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public getTopologyMetrics_argsStandardScheme getScheme() {
        return new getTopologyMetrics_argsStandardScheme();
      }
    }

    private static class getTopologyMetrics_argsStandardScheme extends StandardScheme<getTopologyMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public getTopologyMetrics_argsTupleScheme getScheme() {
        return new getTopologyMetrics_argsTupleScheme();
      }
    }

    private static class getTopologyMetrics_argsTupleScheme extends TupleScheme<getTopologyMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
      }
    }

  }

  public static class getTopologyMetrics_result implements org.apache.thrift.TBase<getTopologyMetrics_result, getTopologyMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTopologyMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTopologyMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTopologyMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTopologyMetrics_resultTupleSchemeFactory());
    }

    private TopologyMetric success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TopologyMetric.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTopologyMetrics_result.class, metaDataMap);
    }

    public getTopologyMetrics_result() {
    }

    public getTopologyMetrics_result(
      TopologyMetric success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTopologyMetrics_result(getTopologyMetrics_result other) {
      if (other.is_set_success()) {
        this.success = new TopologyMetric(other.success);
      }
    }

    public getTopologyMetrics_result deepCopy() {
      return new getTopologyMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public TopologyMetric get_success() {
      return this.success;
    }

    public void set_success(TopologyMetric success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((TopologyMetric)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTopologyMetrics_result)
        return this.equals((getTopologyMetrics_result)that);
      return false;
    }

    public boolean equals(getTopologyMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTopologyMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTopologyMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTopologyMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public getTopologyMetrics_resultStandardScheme getScheme() {
        return new getTopologyMetrics_resultStandardScheme();
      }
    }

    private static class getTopologyMetrics_resultStandardScheme extends StandardScheme<getTopologyMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTopologyMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new TopologyMetric();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTopologyMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTopologyMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public getTopologyMetrics_resultTupleScheme getScheme() {
        return new getTopologyMetrics_resultTupleScheme();
      }
    }

    private static class getTopologyMetrics_resultTupleScheme extends TupleScheme<getTopologyMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTopologyMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTopologyMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = new TopologyMetric();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getMetrics_args implements org.apache.thrift.TBase<getMetrics_args, getMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<getMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("type", org.apache.thrift.protocol.TType.I32, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private int type; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      TYPE((short)2, "type");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // TYPE
            return TYPE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __TYPE_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.TYPE, new org.apache.thrift.meta_data.FieldMetaData("type", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getMetrics_args.class, metaDataMap);
    }

    public getMetrics_args() {
    }

    public getMetrics_args(
      String topologyId,
      int type)
    {
      this();
      this.topologyId = topologyId;
      this.type = type;
      set_type_isSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getMetrics_args(getMetrics_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      this.type = other.type;
    }

    public getMetrics_args deepCopy() {
      return new getMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      set_type_isSet(false);
      this.type = 0;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public int get_type() {
      return this.type;
    }

    public void set_type(int type) {
      this.type = type;
      set_type_isSet(true);
    }

    public void unset_type() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __TYPE_ISSET_ID);
    }

    /** Returns true if field type is set (has been assigned a value) and false otherwise */
    public boolean is_set_type() {
      return EncodingUtils.testBit(__isset_bitfield, __TYPE_ISSET_ID);
    }

    public void set_type_isSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __TYPE_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case TYPE:
        if (value == null) {
          unset_type();
        } else {
          set_type((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case TYPE:
        return Integer.valueOf(get_type());

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case TYPE:
        return is_set_type();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getMetrics_args)
        return this.equals((getMetrics_args)that);
      return false;
    }

    public boolean equals(getMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_type = true;
      boolean that_present_type = true;
      if (this_present_type || that_present_type) {
        if (!(this_present_type && that_present_type))
          return false;
        if (this.type != that.type)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_type = true;
      list.add(present_type);
      if (present_type)
        list.add(type);

      return list.hashCode();
    }

    @Override
    public int compareTo(getMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_type()).compareTo(other.is_set_type());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_type()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.type, other.type);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("type:");
      sb.append(this.type);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public getMetrics_argsStandardScheme getScheme() {
        return new getMetrics_argsStandardScheme();
      }
    }

    private static class getMetrics_argsStandardScheme extends StandardScheme<getMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // TYPE
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.type = iprot.readI32();
                struct.set_type_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(TYPE_FIELD_DESC);
        oprot.writeI32(struct.type);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public getMetrics_argsTupleScheme getScheme() {
        return new getMetrics_argsTupleScheme();
      }
    }

    private static class getMetrics_argsTupleScheme extends TupleScheme<getMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_type()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_type()) {
          oprot.writeI32(struct.type);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          struct.type = iprot.readI32();
          struct.set_type_isSet(true);
        }
      }
    }

  }

  public static class getMetrics_result implements org.apache.thrift.TBase<getMetrics_result, getMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<getMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getMetrics_resultTupleSchemeFactory());
    }

    private List<MetricInfo> success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class))));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getMetrics_result.class, metaDataMap);
    }

    public getMetrics_result() {
    }

    public getMetrics_result(
      List<MetricInfo> success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getMetrics_result(getMetrics_result other) {
      if (other.is_set_success()) {
        List<MetricInfo> __this__success = new ArrayList<MetricInfo>(other.success.size());
        for (MetricInfo other_element : other.success) {
          __this__success.add(new MetricInfo(other_element));
        }
        this.success = __this__success;
      }
    }

    public getMetrics_result deepCopy() {
      return new getMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public int get_success_size() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<MetricInfo> get_success_iterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void add_to_success(MetricInfo elem) {
      if (this.success == null) {
        this.success = new ArrayList<MetricInfo>();
      }
      this.success.add(elem);
    }

    public List<MetricInfo> get_success() {
      return this.success;
    }

    public void set_success(List<MetricInfo> success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((List<MetricInfo>)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getMetrics_result)
        return this.equals((getMetrics_result)that);
      return false;
    }

    public boolean equals(getMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public getMetrics_resultStandardScheme getScheme() {
        return new getMetrics_resultStandardScheme();
      }
    }

    private static class getMetrics_resultStandardScheme extends StandardScheme<getMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list250 = iprot.readListBegin();
                  struct.success = new ArrayList<MetricInfo>(_list250.size);
                  MetricInfo _elem251;
                  for (int _i252 = 0; _i252 < _list250.size; ++_i252)
                  {
                    _elem251 = new MetricInfo();
                    _elem251.read(iprot);
                    struct.success.add(_elem251);
                  }
                  iprot.readListEnd();
                }
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (MetricInfo _iter253 : struct.success)
            {
              _iter253.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public getMetrics_resultTupleScheme getScheme() {
        return new getMetrics_resultTupleScheme();
      }
    }

    private static class getMetrics_resultTupleScheme extends TupleScheme<getMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          {
            oprot.writeI32(struct.success.size());
            for (MetricInfo _iter254 : struct.success)
            {
              _iter254.write(oprot);
            }
          }
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list255 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<MetricInfo>(_list255.size);
            MetricInfo _elem256;
            for (int _i257 = 0; _i257 < _list255.size; ++_i257)
            {
              _elem256 = new MetricInfo();
              _elem256.read(iprot);
              struct.success.add(_elem256);
            }
          }
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getNettyMetrics_args implements org.apache.thrift.TBase<getNettyMetrics_args, getNettyMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<getNettyMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNettyMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNettyMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNettyMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNettyMetrics_args.class, metaDataMap);
    }

    public getNettyMetrics_args() {
    }

    public getNettyMetrics_args(
      String topologyId)
    {
      this();
      this.topologyId = topologyId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNettyMetrics_args(getNettyMetrics_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
    }

    public getNettyMetrics_args deepCopy() {
      return new getNettyMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNettyMetrics_args)
        return this.equals((getNettyMetrics_args)that);
      return false;
    }

    public boolean equals(getNettyMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getNettyMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNettyMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNettyMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public getNettyMetrics_argsStandardScheme getScheme() {
        return new getNettyMetrics_argsStandardScheme();
      }
    }

    private static class getNettyMetrics_argsStandardScheme extends StandardScheme<getNettyMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNettyMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNettyMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNettyMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public getNettyMetrics_argsTupleScheme getScheme() {
        return new getNettyMetrics_argsTupleScheme();
      }
    }

    private static class getNettyMetrics_argsTupleScheme extends TupleScheme<getNettyMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNettyMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNettyMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
      }
    }

  }

  public static class getNettyMetrics_result implements org.apache.thrift.TBase<getNettyMetrics_result, getNettyMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<getNettyMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNettyMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNettyMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNettyMetrics_resultTupleSchemeFactory());
    }

    private MetricInfo success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNettyMetrics_result.class, metaDataMap);
    }

    public getNettyMetrics_result() {
    }

    public getNettyMetrics_result(
      MetricInfo success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNettyMetrics_result(getNettyMetrics_result other) {
      if (other.is_set_success()) {
        this.success = new MetricInfo(other.success);
      }
    }

    public getNettyMetrics_result deepCopy() {
      return new getNettyMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public MetricInfo get_success() {
      return this.success;
    }

    public void set_success(MetricInfo success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((MetricInfo)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNettyMetrics_result)
        return this.equals((getNettyMetrics_result)that);
      return false;
    }

    public boolean equals(getNettyMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getNettyMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNettyMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNettyMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public getNettyMetrics_resultStandardScheme getScheme() {
        return new getNettyMetrics_resultStandardScheme();
      }
    }

    private static class getNettyMetrics_resultStandardScheme extends StandardScheme<getNettyMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNettyMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new MetricInfo();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNettyMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNettyMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public getNettyMetrics_resultTupleScheme getScheme() {
        return new getNettyMetrics_resultTupleScheme();
      }
    }

    private static class getNettyMetrics_resultTupleScheme extends TupleScheme<getNettyMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNettyMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNettyMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = new MetricInfo();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getNettyMetricsByHost_args implements org.apache.thrift.TBase<getNettyMetricsByHost_args, getNettyMetricsByHost_args._Fields>, java.io.Serializable, Cloneable, Comparable<getNettyMetricsByHost_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNettyMetricsByHost_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField HOST_FIELD_DESC = new org.apache.thrift.protocol.TField("host", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNettyMetricsByHost_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNettyMetricsByHost_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private String host; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      HOST((short)2, "host");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // HOST
            return HOST;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.HOST, new org.apache.thrift.meta_data.FieldMetaData("host", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNettyMetricsByHost_args.class, metaDataMap);
    }

    public getNettyMetricsByHost_args() {
    }

    public getNettyMetricsByHost_args(
      String topologyId,
      String host)
    {
      this();
      this.topologyId = topologyId;
      this.host = host;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNettyMetricsByHost_args(getNettyMetricsByHost_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      if (other.is_set_host()) {
        this.host = other.host;
      }
    }

    public getNettyMetricsByHost_args deepCopy() {
      return new getNettyMetricsByHost_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      this.host = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public String get_host() {
      return this.host;
    }

    public void set_host(String host) {
      this.host = host;
    }

    public void unset_host() {
      this.host = null;
    }

    /** Returns true if field host is set (has been assigned a value) and false otherwise */
    public boolean is_set_host() {
      return this.host != null;
    }

    public void set_host_isSet(boolean value) {
      if (!value) {
        this.host = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case HOST:
        if (value == null) {
          unset_host();
        } else {
          set_host((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case HOST:
        return get_host();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case HOST:
        return is_set_host();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNettyMetricsByHost_args)
        return this.equals((getNettyMetricsByHost_args)that);
      return false;
    }

    public boolean equals(getNettyMetricsByHost_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_host = true && this.is_set_host();
      boolean that_present_host = true && that.is_set_host();
      if (this_present_host || that_present_host) {
        if (!(this_present_host && that_present_host))
          return false;
        if (!this.host.equals(that.host))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_host = true && (is_set_host());
      list.add(present_host);
      if (present_host)
        list.add(host);

      return list.hashCode();
    }

    @Override
    public int compareTo(getNettyMetricsByHost_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_host()).compareTo(other.is_set_host());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_host()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.host, other.host);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNettyMetricsByHost_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("host:");
      if (this.host == null) {
        sb.append("null");
      } else {
        sb.append(this.host);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNettyMetricsByHost_argsStandardSchemeFactory implements SchemeFactory {
      public getNettyMetricsByHost_argsStandardScheme getScheme() {
        return new getNettyMetricsByHost_argsStandardScheme();
      }
    }

    private static class getNettyMetricsByHost_argsStandardScheme extends StandardScheme<getNettyMetricsByHost_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNettyMetricsByHost_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // HOST
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.host = iprot.readString();
                struct.set_host_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNettyMetricsByHost_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        if (struct.host != null) {
          oprot.writeFieldBegin(HOST_FIELD_DESC);
          oprot.writeString(struct.host);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNettyMetricsByHost_argsTupleSchemeFactory implements SchemeFactory {
      public getNettyMetricsByHost_argsTupleScheme getScheme() {
        return new getNettyMetricsByHost_argsTupleScheme();
      }
    }

    private static class getNettyMetricsByHost_argsTupleScheme extends TupleScheme<getNettyMetricsByHost_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNettyMetricsByHost_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_host()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_host()) {
          oprot.writeString(struct.host);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNettyMetricsByHost_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          struct.host = iprot.readString();
          struct.set_host_isSet(true);
        }
      }
    }

  }

  public static class getNettyMetricsByHost_result implements org.apache.thrift.TBase<getNettyMetricsByHost_result, getNettyMetricsByHost_result._Fields>, java.io.Serializable, Cloneable, Comparable<getNettyMetricsByHost_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNettyMetricsByHost_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNettyMetricsByHost_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNettyMetricsByHost_resultTupleSchemeFactory());
    }

    private MetricInfo success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNettyMetricsByHost_result.class, metaDataMap);
    }

    public getNettyMetricsByHost_result() {
    }

    public getNettyMetricsByHost_result(
      MetricInfo success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNettyMetricsByHost_result(getNettyMetricsByHost_result other) {
      if (other.is_set_success()) {
        this.success = new MetricInfo(other.success);
      }
    }

    public getNettyMetricsByHost_result deepCopy() {
      return new getNettyMetricsByHost_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public MetricInfo get_success() {
      return this.success;
    }

    public void set_success(MetricInfo success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((MetricInfo)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNettyMetricsByHost_result)
        return this.equals((getNettyMetricsByHost_result)that);
      return false;
    }

    public boolean equals(getNettyMetricsByHost_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getNettyMetricsByHost_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNettyMetricsByHost_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNettyMetricsByHost_resultStandardSchemeFactory implements SchemeFactory {
      public getNettyMetricsByHost_resultStandardScheme getScheme() {
        return new getNettyMetricsByHost_resultStandardScheme();
      }
    }

    private static class getNettyMetricsByHost_resultStandardScheme extends StandardScheme<getNettyMetricsByHost_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNettyMetricsByHost_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new MetricInfo();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNettyMetricsByHost_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNettyMetricsByHost_resultTupleSchemeFactory implements SchemeFactory {
      public getNettyMetricsByHost_resultTupleScheme getScheme() {
        return new getNettyMetricsByHost_resultTupleScheme();
      }
    }

    private static class getNettyMetricsByHost_resultTupleScheme extends TupleScheme<getNettyMetricsByHost_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNettyMetricsByHost_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNettyMetricsByHost_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = new MetricInfo();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getPagingNettyMetrics_args implements org.apache.thrift.TBase<getPagingNettyMetrics_args, getPagingNettyMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<getPagingNettyMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPagingNettyMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField HOST_FIELD_DESC = new org.apache.thrift.protocol.TField("host", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField PAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("page", org.apache.thrift.protocol.TType.I32, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getPagingNettyMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getPagingNettyMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private String host; // required
    private int page; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      HOST((short)2, "host"),
      PAGE((short)3, "page");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // HOST
            return HOST;
          case 3: // PAGE
            return PAGE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __PAGE_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.HOST, new org.apache.thrift.meta_data.FieldMetaData("host", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.PAGE, new org.apache.thrift.meta_data.FieldMetaData("page", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPagingNettyMetrics_args.class, metaDataMap);
    }

    public getPagingNettyMetrics_args() {
    }

    public getPagingNettyMetrics_args(
      String topologyId,
      String host,
      int page)
    {
      this();
      this.topologyId = topologyId;
      this.host = host;
      this.page = page;
      set_page_isSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getPagingNettyMetrics_args(getPagingNettyMetrics_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      if (other.is_set_host()) {
        this.host = other.host;
      }
      this.page = other.page;
    }

    public getPagingNettyMetrics_args deepCopy() {
      return new getPagingNettyMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      this.host = null;
      set_page_isSet(false);
      this.page = 0;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public String get_host() {
      return this.host;
    }

    public void set_host(String host) {
      this.host = host;
    }

    public void unset_host() {
      this.host = null;
    }

    /** Returns true if field host is set (has been assigned a value) and false otherwise */
    public boolean is_set_host() {
      return this.host != null;
    }

    public void set_host_isSet(boolean value) {
      if (!value) {
        this.host = null;
      }
    }

    public int get_page() {
      return this.page;
    }

    public void set_page(int page) {
      this.page = page;
      set_page_isSet(true);
    }

    public void unset_page() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __PAGE_ISSET_ID);
    }

    /** Returns true if field page is set (has been assigned a value) and false otherwise */
    public boolean is_set_page() {
      return EncodingUtils.testBit(__isset_bitfield, __PAGE_ISSET_ID);
    }

    public void set_page_isSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __PAGE_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case HOST:
        if (value == null) {
          unset_host();
        } else {
          set_host((String)value);
        }
        break;

      case PAGE:
        if (value == null) {
          unset_page();
        } else {
          set_page((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case HOST:
        return get_host();

      case PAGE:
        return Integer.valueOf(get_page());

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case HOST:
        return is_set_host();
      case PAGE:
        return is_set_page();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getPagingNettyMetrics_args)
        return this.equals((getPagingNettyMetrics_args)that);
      return false;
    }

    public boolean equals(getPagingNettyMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_host = true && this.is_set_host();
      boolean that_present_host = true && that.is_set_host();
      if (this_present_host || that_present_host) {
        if (!(this_present_host && that_present_host))
          return false;
        if (!this.host.equals(that.host))
          return false;
      }

      boolean this_present_page = true;
      boolean that_present_page = true;
      if (this_present_page || that_present_page) {
        if (!(this_present_page && that_present_page))
          return false;
        if (this.page != that.page)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_host = true && (is_set_host());
      list.add(present_host);
      if (present_host)
        list.add(host);

      boolean present_page = true;
      list.add(present_page);
      if (present_page)
        list.add(page);

      return list.hashCode();
    }

    @Override
    public int compareTo(getPagingNettyMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_host()).compareTo(other.is_set_host());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_host()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.host, other.host);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_page()).compareTo(other.is_set_page());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_page()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.page, other.page);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getPagingNettyMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("host:");
      if (this.host == null) {
        sb.append("null");
      } else {
        sb.append(this.host);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("page:");
      sb.append(this.page);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getPagingNettyMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public getPagingNettyMetrics_argsStandardScheme getScheme() {
        return new getPagingNettyMetrics_argsStandardScheme();
      }
    }

    private static class getPagingNettyMetrics_argsStandardScheme extends StandardScheme<getPagingNettyMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getPagingNettyMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // HOST
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.host = iprot.readString();
                struct.set_host_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // PAGE
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.page = iprot.readI32();
                struct.set_page_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getPagingNettyMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        if (struct.host != null) {
          oprot.writeFieldBegin(HOST_FIELD_DESC);
          oprot.writeString(struct.host);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(PAGE_FIELD_DESC);
        oprot.writeI32(struct.page);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getPagingNettyMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public getPagingNettyMetrics_argsTupleScheme getScheme() {
        return new getPagingNettyMetrics_argsTupleScheme();
      }
    }

    private static class getPagingNettyMetrics_argsTupleScheme extends TupleScheme<getPagingNettyMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getPagingNettyMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_host()) {
          optionals.set(1);
        }
        if (struct.is_set_page()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_host()) {
          oprot.writeString(struct.host);
        }
        if (struct.is_set_page()) {
          oprot.writeI32(struct.page);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getPagingNettyMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          struct.host = iprot.readString();
          struct.set_host_isSet(true);
        }
        if (incoming.get(2)) {
          struct.page = iprot.readI32();
          struct.set_page_isSet(true);
        }
      }
    }

  }

  public static class getPagingNettyMetrics_result implements org.apache.thrift.TBase<getPagingNettyMetrics_result, getPagingNettyMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<getPagingNettyMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPagingNettyMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getPagingNettyMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getPagingNettyMetrics_resultTupleSchemeFactory());
    }

    private MetricInfo success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPagingNettyMetrics_result.class, metaDataMap);
    }

    public getPagingNettyMetrics_result() {
    }

    public getPagingNettyMetrics_result(
      MetricInfo success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getPagingNettyMetrics_result(getPagingNettyMetrics_result other) {
      if (other.is_set_success()) {
        this.success = new MetricInfo(other.success);
      }
    }

    public getPagingNettyMetrics_result deepCopy() {
      return new getPagingNettyMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public MetricInfo get_success() {
      return this.success;
    }

    public void set_success(MetricInfo success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((MetricInfo)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getPagingNettyMetrics_result)
        return this.equals((getPagingNettyMetrics_result)that);
      return false;
    }

    public boolean equals(getPagingNettyMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getPagingNettyMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getPagingNettyMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getPagingNettyMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public getPagingNettyMetrics_resultStandardScheme getScheme() {
        return new getPagingNettyMetrics_resultStandardScheme();
      }
    }

    private static class getPagingNettyMetrics_resultStandardScheme extends StandardScheme<getPagingNettyMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getPagingNettyMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new MetricInfo();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getPagingNettyMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getPagingNettyMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public getPagingNettyMetrics_resultTupleScheme getScheme() {
        return new getPagingNettyMetrics_resultTupleScheme();
      }
    }

    private static class getPagingNettyMetrics_resultTupleScheme extends TupleScheme<getPagingNettyMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getPagingNettyMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getPagingNettyMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = new MetricInfo();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getNettyMetricSizeByHost_args implements org.apache.thrift.TBase<getNettyMetricSizeByHost_args, getNettyMetricSizeByHost_args._Fields>, java.io.Serializable, Cloneable, Comparable<getNettyMetricSizeByHost_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNettyMetricSizeByHost_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField HOST_FIELD_DESC = new org.apache.thrift.protocol.TField("host", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNettyMetricSizeByHost_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNettyMetricSizeByHost_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private String host; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      HOST((short)2, "host");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // HOST
            return HOST;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.HOST, new org.apache.thrift.meta_data.FieldMetaData("host", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNettyMetricSizeByHost_args.class, metaDataMap);
    }

    public getNettyMetricSizeByHost_args() {
    }

    public getNettyMetricSizeByHost_args(
      String topologyId,
      String host)
    {
      this();
      this.topologyId = topologyId;
      this.host = host;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNettyMetricSizeByHost_args(getNettyMetricSizeByHost_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      if (other.is_set_host()) {
        this.host = other.host;
      }
    }

    public getNettyMetricSizeByHost_args deepCopy() {
      return new getNettyMetricSizeByHost_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      this.host = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public String get_host() {
      return this.host;
    }

    public void set_host(String host) {
      this.host = host;
    }

    public void unset_host() {
      this.host = null;
    }

    /** Returns true if field host is set (has been assigned a value) and false otherwise */
    public boolean is_set_host() {
      return this.host != null;
    }

    public void set_host_isSet(boolean value) {
      if (!value) {
        this.host = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case HOST:
        if (value == null) {
          unset_host();
        } else {
          set_host((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case HOST:
        return get_host();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case HOST:
        return is_set_host();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNettyMetricSizeByHost_args)
        return this.equals((getNettyMetricSizeByHost_args)that);
      return false;
    }

    public boolean equals(getNettyMetricSizeByHost_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_host = true && this.is_set_host();
      boolean that_present_host = true && that.is_set_host();
      if (this_present_host || that_present_host) {
        if (!(this_present_host && that_present_host))
          return false;
        if (!this.host.equals(that.host))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_host = true && (is_set_host());
      list.add(present_host);
      if (present_host)
        list.add(host);

      return list.hashCode();
    }

    @Override
    public int compareTo(getNettyMetricSizeByHost_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_host()).compareTo(other.is_set_host());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_host()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.host, other.host);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNettyMetricSizeByHost_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("host:");
      if (this.host == null) {
        sb.append("null");
      } else {
        sb.append(this.host);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNettyMetricSizeByHost_argsStandardSchemeFactory implements SchemeFactory {
      public getNettyMetricSizeByHost_argsStandardScheme getScheme() {
        return new getNettyMetricSizeByHost_argsStandardScheme();
      }
    }

    private static class getNettyMetricSizeByHost_argsStandardScheme extends StandardScheme<getNettyMetricSizeByHost_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNettyMetricSizeByHost_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // HOST
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.host = iprot.readString();
                struct.set_host_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNettyMetricSizeByHost_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        if (struct.host != null) {
          oprot.writeFieldBegin(HOST_FIELD_DESC);
          oprot.writeString(struct.host);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNettyMetricSizeByHost_argsTupleSchemeFactory implements SchemeFactory {
      public getNettyMetricSizeByHost_argsTupleScheme getScheme() {
        return new getNettyMetricSizeByHost_argsTupleScheme();
      }
    }

    private static class getNettyMetricSizeByHost_argsTupleScheme extends TupleScheme<getNettyMetricSizeByHost_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNettyMetricSizeByHost_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_host()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_host()) {
          oprot.writeString(struct.host);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNettyMetricSizeByHost_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          struct.host = iprot.readString();
          struct.set_host_isSet(true);
        }
      }
    }

  }

  public static class getNettyMetricSizeByHost_result implements org.apache.thrift.TBase<getNettyMetricSizeByHost_result, getNettyMetricSizeByHost_result._Fields>, java.io.Serializable, Cloneable, Comparable<getNettyMetricSizeByHost_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getNettyMetricSizeByHost_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getNettyMetricSizeByHost_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getNettyMetricSizeByHost_resultTupleSchemeFactory());
    }

    private int success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getNettyMetricSizeByHost_result.class, metaDataMap);
    }

    public getNettyMetricSizeByHost_result() {
    }

    public getNettyMetricSizeByHost_result(
      int success)
    {
      this();
      this.success = success;
      set_success_isSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getNettyMetricSizeByHost_result(getNettyMetricSizeByHost_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
    }

    public getNettyMetricSizeByHost_result deepCopy() {
      return new getNettyMetricSizeByHost_result(this);
    }

    @Override
    public void clear() {
      set_success_isSet(false);
      this.success = 0;
    }

    public int get_success() {
      return this.success;
    }

    public void set_success(int success) {
      this.success = success;
      set_success_isSet(true);
    }

    public void unset_success() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void set_success_isSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return Integer.valueOf(get_success());

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getNettyMetricSizeByHost_result)
        return this.equals((getNettyMetricSizeByHost_result)that);
      return false;
    }

    public boolean equals(getNettyMetricSizeByHost_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getNettyMetricSizeByHost_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getNettyMetricSizeByHost_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getNettyMetricSizeByHost_resultStandardSchemeFactory implements SchemeFactory {
      public getNettyMetricSizeByHost_resultStandardScheme getScheme() {
        return new getNettyMetricSizeByHost_resultStandardScheme();
      }
    }

    private static class getNettyMetricSizeByHost_resultStandardScheme extends StandardScheme<getNettyMetricSizeByHost_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getNettyMetricSizeByHost_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.success = iprot.readI32();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getNettyMetricSizeByHost_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.is_set_success()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeI32(struct.success);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getNettyMetricSizeByHost_resultTupleSchemeFactory implements SchemeFactory {
      public getNettyMetricSizeByHost_resultTupleScheme getScheme() {
        return new getNettyMetricSizeByHost_resultTupleScheme();
      }
    }

    private static class getNettyMetricSizeByHost_resultTupleScheme extends TupleScheme<getNettyMetricSizeByHost_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getNettyMetricSizeByHost_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          oprot.writeI32(struct.success);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getNettyMetricSizeByHost_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = iprot.readI32();
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getTaskMetrics_args implements org.apache.thrift.TBase<getTaskMetrics_args, getTaskMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTaskMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTaskMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField COMPONENT_FIELD_DESC = new org.apache.thrift.protocol.TField("component", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTaskMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTaskMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private String component; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      COMPONENT((short)2, "component");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // COMPONENT
            return COMPONENT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.COMPONENT, new org.apache.thrift.meta_data.FieldMetaData("component", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTaskMetrics_args.class, metaDataMap);
    }

    public getTaskMetrics_args() {
    }

    public getTaskMetrics_args(
      String topologyId,
      String component)
    {
      this();
      this.topologyId = topologyId;
      this.component = component;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTaskMetrics_args(getTaskMetrics_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      if (other.is_set_component()) {
        this.component = other.component;
      }
    }

    public getTaskMetrics_args deepCopy() {
      return new getTaskMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      this.component = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public String get_component() {
      return this.component;
    }

    public void set_component(String component) {
      this.component = component;
    }

    public void unset_component() {
      this.component = null;
    }

    /** Returns true if field component is set (has been assigned a value) and false otherwise */
    public boolean is_set_component() {
      return this.component != null;
    }

    public void set_component_isSet(boolean value) {
      if (!value) {
        this.component = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case COMPONENT:
        if (value == null) {
          unset_component();
        } else {
          set_component((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case COMPONENT:
        return get_component();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case COMPONENT:
        return is_set_component();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTaskMetrics_args)
        return this.equals((getTaskMetrics_args)that);
      return false;
    }

    public boolean equals(getTaskMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_component = true && this.is_set_component();
      boolean that_present_component = true && that.is_set_component();
      if (this_present_component || that_present_component) {
        if (!(this_present_component && that_present_component))
          return false;
        if (!this.component.equals(that.component))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_component = true && (is_set_component());
      list.add(present_component);
      if (present_component)
        list.add(component);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTaskMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_component()).compareTo(other.is_set_component());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_component()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.component, other.component);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTaskMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("component:");
      if (this.component == null) {
        sb.append("null");
      } else {
        sb.append(this.component);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTaskMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public getTaskMetrics_argsStandardScheme getScheme() {
        return new getTaskMetrics_argsStandardScheme();
      }
    }

    private static class getTaskMetrics_argsStandardScheme extends StandardScheme<getTaskMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTaskMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // COMPONENT
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.component = iprot.readString();
                struct.set_component_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTaskMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        if (struct.component != null) {
          oprot.writeFieldBegin(COMPONENT_FIELD_DESC);
          oprot.writeString(struct.component);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTaskMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public getTaskMetrics_argsTupleScheme getScheme() {
        return new getTaskMetrics_argsTupleScheme();
      }
    }

    private static class getTaskMetrics_argsTupleScheme extends TupleScheme<getTaskMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTaskMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_component()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_component()) {
          oprot.writeString(struct.component);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTaskMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          struct.component = iprot.readString();
          struct.set_component_isSet(true);
        }
      }
    }

  }

  public static class getTaskMetrics_result implements org.apache.thrift.TBase<getTaskMetrics_result, getTaskMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTaskMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTaskMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTaskMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTaskMetrics_resultTupleSchemeFactory());
    }

    private MetricInfo success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTaskMetrics_result.class, metaDataMap);
    }

    public getTaskMetrics_result() {
    }

    public getTaskMetrics_result(
      MetricInfo success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTaskMetrics_result(getTaskMetrics_result other) {
      if (other.is_set_success()) {
        this.success = new MetricInfo(other.success);
      }
    }

    public getTaskMetrics_result deepCopy() {
      return new getTaskMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public MetricInfo get_success() {
      return this.success;
    }

    public void set_success(MetricInfo success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((MetricInfo)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTaskMetrics_result)
        return this.equals((getTaskMetrics_result)that);
      return false;
    }

    public boolean equals(getTaskMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTaskMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTaskMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTaskMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public getTaskMetrics_resultStandardScheme getScheme() {
        return new getTaskMetrics_resultStandardScheme();
      }
    }

    private static class getTaskMetrics_resultStandardScheme extends StandardScheme<getTaskMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTaskMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new MetricInfo();
                struct.success.read(iprot);
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTaskMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTaskMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public getTaskMetrics_resultTupleScheme getScheme() {
        return new getTaskMetrics_resultTupleScheme();
      }
    }

    private static class getTaskMetrics_resultTupleScheme extends TupleScheme<getTaskMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTaskMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          struct.success.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTaskMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = new MetricInfo();
          struct.success.read(iprot);
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getTaskAndStreamMetrics_args implements org.apache.thrift.TBase<getTaskAndStreamMetrics_args, getTaskAndStreamMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<getTaskAndStreamMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTaskAndStreamMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField TASK_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("taskId", org.apache.thrift.protocol.TType.I32, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTaskAndStreamMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTaskAndStreamMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required
    private int taskId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId"),
      TASK_ID((short)2, "taskId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          case 2: // TASK_ID
            return TASK_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __TASKID_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.TASK_ID, new org.apache.thrift.meta_data.FieldMetaData("taskId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTaskAndStreamMetrics_args.class, metaDataMap);
    }

    public getTaskAndStreamMetrics_args() {
    }

    public getTaskAndStreamMetrics_args(
      String topologyId,
      int taskId)
    {
      this();
      this.topologyId = topologyId;
      this.taskId = taskId;
      set_taskId_isSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTaskAndStreamMetrics_args(getTaskAndStreamMetrics_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
      this.taskId = other.taskId;
    }

    public getTaskAndStreamMetrics_args deepCopy() {
      return new getTaskAndStreamMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
      set_taskId_isSet(false);
      this.taskId = 0;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public int get_taskId() {
      return this.taskId;
    }

    public void set_taskId(int taskId) {
      this.taskId = taskId;
      set_taskId_isSet(true);
    }

    public void unset_taskId() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __TASKID_ISSET_ID);
    }

    /** Returns true if field taskId is set (has been assigned a value) and false otherwise */
    public boolean is_set_taskId() {
      return EncodingUtils.testBit(__isset_bitfield, __TASKID_ISSET_ID);
    }

    public void set_taskId_isSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __TASKID_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      case TASK_ID:
        if (value == null) {
          unset_taskId();
        } else {
          set_taskId((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      case TASK_ID:
        return Integer.valueOf(get_taskId());

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      case TASK_ID:
        return is_set_taskId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTaskAndStreamMetrics_args)
        return this.equals((getTaskAndStreamMetrics_args)that);
      return false;
    }

    public boolean equals(getTaskAndStreamMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      boolean this_present_taskId = true;
      boolean that_present_taskId = true;
      if (this_present_taskId || that_present_taskId) {
        if (!(this_present_taskId && that_present_taskId))
          return false;
        if (this.taskId != that.taskId)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      boolean present_taskId = true;
      list.add(present_taskId);
      if (present_taskId)
        list.add(taskId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTaskAndStreamMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_taskId()).compareTo(other.is_set_taskId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_taskId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.taskId, other.taskId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTaskAndStreamMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("taskId:");
      sb.append(this.taskId);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTaskAndStreamMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public getTaskAndStreamMetrics_argsStandardScheme getScheme() {
        return new getTaskAndStreamMetrics_argsStandardScheme();
      }
    }

    private static class getTaskAndStreamMetrics_argsStandardScheme extends StandardScheme<getTaskAndStreamMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTaskAndStreamMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // TASK_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.taskId = iprot.readI32();
                struct.set_taskId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTaskAndStreamMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(TASK_ID_FIELD_DESC);
        oprot.writeI32(struct.taskId);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTaskAndStreamMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public getTaskAndStreamMetrics_argsTupleScheme getScheme() {
        return new getTaskAndStreamMetrics_argsTupleScheme();
      }
    }

    private static class getTaskAndStreamMetrics_argsTupleScheme extends TupleScheme<getTaskAndStreamMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTaskAndStreamMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        if (struct.is_set_taskId()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
        if (struct.is_set_taskId()) {
          oprot.writeI32(struct.taskId);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTaskAndStreamMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
        if (incoming.get(1)) {
          struct.taskId = iprot.readI32();
          struct.set_taskId_isSet(true);
        }
      }
    }

  }

  public static class getTaskAndStreamMetrics_result implements org.apache.thrift.TBase<getTaskAndStreamMetrics_result, getTaskAndStreamMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<getTaskAndStreamMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getTaskAndStreamMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getTaskAndStreamMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getTaskAndStreamMetrics_resultTupleSchemeFactory());
    }

    private List<MetricInfo> success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class))));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getTaskAndStreamMetrics_result.class, metaDataMap);
    }

    public getTaskAndStreamMetrics_result() {
    }

    public getTaskAndStreamMetrics_result(
      List<MetricInfo> success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getTaskAndStreamMetrics_result(getTaskAndStreamMetrics_result other) {
      if (other.is_set_success()) {
        List<MetricInfo> __this__success = new ArrayList<MetricInfo>(other.success.size());
        for (MetricInfo other_element : other.success) {
          __this__success.add(new MetricInfo(other_element));
        }
        this.success = __this__success;
      }
    }

    public getTaskAndStreamMetrics_result deepCopy() {
      return new getTaskAndStreamMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public int get_success_size() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<MetricInfo> get_success_iterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void add_to_success(MetricInfo elem) {
      if (this.success == null) {
        this.success = new ArrayList<MetricInfo>();
      }
      this.success.add(elem);
    }

    public List<MetricInfo> get_success() {
      return this.success;
    }

    public void set_success(List<MetricInfo> success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((List<MetricInfo>)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getTaskAndStreamMetrics_result)
        return this.equals((getTaskAndStreamMetrics_result)that);
      return false;
    }

    public boolean equals(getTaskAndStreamMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getTaskAndStreamMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getTaskAndStreamMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getTaskAndStreamMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public getTaskAndStreamMetrics_resultStandardScheme getScheme() {
        return new getTaskAndStreamMetrics_resultStandardScheme();
      }
    }

    private static class getTaskAndStreamMetrics_resultStandardScheme extends StandardScheme<getTaskAndStreamMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getTaskAndStreamMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list258 = iprot.readListBegin();
                  struct.success = new ArrayList<MetricInfo>(_list258.size);
                  MetricInfo _elem259;
                  for (int _i260 = 0; _i260 < _list258.size; ++_i260)
                  {
                    _elem259 = new MetricInfo();
                    _elem259.read(iprot);
                    struct.success.add(_elem259);
                  }
                  iprot.readListEnd();
                }
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getTaskAndStreamMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (MetricInfo _iter261 : struct.success)
            {
              _iter261.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getTaskAndStreamMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public getTaskAndStreamMetrics_resultTupleScheme getScheme() {
        return new getTaskAndStreamMetrics_resultTupleScheme();
      }
    }

    private static class getTaskAndStreamMetrics_resultTupleScheme extends TupleScheme<getTaskAndStreamMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getTaskAndStreamMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          {
            oprot.writeI32(struct.success.size());
            for (MetricInfo _iter262 : struct.success)
            {
              _iter262.write(oprot);
            }
          }
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getTaskAndStreamMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list263 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<MetricInfo>(_list263.size);
            MetricInfo _elem264;
            for (int _i265 = 0; _i265 < _list263.size; ++_i265)
            {
              _elem264 = new MetricInfo();
              _elem264.read(iprot);
              struct.success.add(_elem264);
            }
          }
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getSummarizedTopologyMetrics_args implements org.apache.thrift.TBase<getSummarizedTopologyMetrics_args, getSummarizedTopologyMetrics_args._Fields>, java.io.Serializable, Cloneable, Comparable<getSummarizedTopologyMetrics_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getSummarizedTopologyMetrics_args");

    private static final org.apache.thrift.protocol.TField TOPOLOGY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("topologyId", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getSummarizedTopologyMetrics_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getSummarizedTopologyMetrics_argsTupleSchemeFactory());
    }

    private String topologyId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TOPOLOGY_ID((short)1, "topologyId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TOPOLOGY_ID
            return TOPOLOGY_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TOPOLOGY_ID, new org.apache.thrift.meta_data.FieldMetaData("topologyId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getSummarizedTopologyMetrics_args.class, metaDataMap);
    }

    public getSummarizedTopologyMetrics_args() {
    }

    public getSummarizedTopologyMetrics_args(
      String topologyId)
    {
      this();
      this.topologyId = topologyId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getSummarizedTopologyMetrics_args(getSummarizedTopologyMetrics_args other) {
      if (other.is_set_topologyId()) {
        this.topologyId = other.topologyId;
      }
    }

    public getSummarizedTopologyMetrics_args deepCopy() {
      return new getSummarizedTopologyMetrics_args(this);
    }

    @Override
    public void clear() {
      this.topologyId = null;
    }

    public String get_topologyId() {
      return this.topologyId;
    }

    public void set_topologyId(String topologyId) {
      this.topologyId = topologyId;
    }

    public void unset_topologyId() {
      this.topologyId = null;
    }

    /** Returns true if field topologyId is set (has been assigned a value) and false otherwise */
    public boolean is_set_topologyId() {
      return this.topologyId != null;
    }

    public void set_topologyId_isSet(boolean value) {
      if (!value) {
        this.topologyId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TOPOLOGY_ID:
        if (value == null) {
          unset_topologyId();
        } else {
          set_topologyId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TOPOLOGY_ID:
        return get_topologyId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TOPOLOGY_ID:
        return is_set_topologyId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getSummarizedTopologyMetrics_args)
        return this.equals((getSummarizedTopologyMetrics_args)that);
      return false;
    }

    public boolean equals(getSummarizedTopologyMetrics_args that) {
      if (that == null)
        return false;

      boolean this_present_topologyId = true && this.is_set_topologyId();
      boolean that_present_topologyId = true && that.is_set_topologyId();
      if (this_present_topologyId || that_present_topologyId) {
        if (!(this_present_topologyId && that_present_topologyId))
          return false;
        if (!this.topologyId.equals(that.topologyId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_topologyId = true && (is_set_topologyId());
      list.add(present_topologyId);
      if (present_topologyId)
        list.add(topologyId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getSummarizedTopologyMetrics_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_topologyId()).compareTo(other.is_set_topologyId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_topologyId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topologyId, other.topologyId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getSummarizedTopologyMetrics_args(");
      boolean first = true;

      sb.append("topologyId:");
      if (this.topologyId == null) {
        sb.append("null");
      } else {
        sb.append(this.topologyId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getSummarizedTopologyMetrics_argsStandardSchemeFactory implements SchemeFactory {
      public getSummarizedTopologyMetrics_argsStandardScheme getScheme() {
        return new getSummarizedTopologyMetrics_argsStandardScheme();
      }
    }

    private static class getSummarizedTopologyMetrics_argsStandardScheme extends StandardScheme<getSummarizedTopologyMetrics_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getSummarizedTopologyMetrics_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TOPOLOGY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.topologyId = iprot.readString();
                struct.set_topologyId_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getSummarizedTopologyMetrics_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.topologyId != null) {
          oprot.writeFieldBegin(TOPOLOGY_ID_FIELD_DESC);
          oprot.writeString(struct.topologyId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getSummarizedTopologyMetrics_argsTupleSchemeFactory implements SchemeFactory {
      public getSummarizedTopologyMetrics_argsTupleScheme getScheme() {
        return new getSummarizedTopologyMetrics_argsTupleScheme();
      }
    }

    private static class getSummarizedTopologyMetrics_argsTupleScheme extends TupleScheme<getSummarizedTopologyMetrics_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getSummarizedTopologyMetrics_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_topologyId()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_topologyId()) {
          oprot.writeString(struct.topologyId);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getSummarizedTopologyMetrics_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.topologyId = iprot.readString();
          struct.set_topologyId_isSet(true);
        }
      }
    }

  }

  public static class getSummarizedTopologyMetrics_result implements org.apache.thrift.TBase<getSummarizedTopologyMetrics_result, getSummarizedTopologyMetrics_result._Fields>, java.io.Serializable, Cloneable, Comparable<getSummarizedTopologyMetrics_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getSummarizedTopologyMetrics_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getSummarizedTopologyMetrics_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getSummarizedTopologyMetrics_resultTupleSchemeFactory());
    }

    private List<MetricInfo> success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class))));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getSummarizedTopologyMetrics_result.class, metaDataMap);
    }

    public getSummarizedTopologyMetrics_result() {
    }

    public getSummarizedTopologyMetrics_result(
      List<MetricInfo> success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getSummarizedTopologyMetrics_result(getSummarizedTopologyMetrics_result other) {
      if (other.is_set_success()) {
        List<MetricInfo> __this__success = new ArrayList<MetricInfo>(other.success.size());
        for (MetricInfo other_element : other.success) {
          __this__success.add(new MetricInfo(other_element));
        }
        this.success = __this__success;
      }
    }

    public getSummarizedTopologyMetrics_result deepCopy() {
      return new getSummarizedTopologyMetrics_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public int get_success_size() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<MetricInfo> get_success_iterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void add_to_success(MetricInfo elem) {
      if (this.success == null) {
        this.success = new ArrayList<MetricInfo>();
      }
      this.success.add(elem);
    }

    public List<MetricInfo> get_success() {
      return this.success;
    }

    public void set_success(List<MetricInfo> success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((List<MetricInfo>)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getSummarizedTopologyMetrics_result)
        return this.equals((getSummarizedTopologyMetrics_result)that);
      return false;
    }

    public boolean equals(getSummarizedTopologyMetrics_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getSummarizedTopologyMetrics_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getSummarizedTopologyMetrics_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getSummarizedTopologyMetrics_resultStandardSchemeFactory implements SchemeFactory {
      public getSummarizedTopologyMetrics_resultStandardScheme getScheme() {
        return new getSummarizedTopologyMetrics_resultStandardScheme();
      }
    }

    private static class getSummarizedTopologyMetrics_resultStandardScheme extends StandardScheme<getSummarizedTopologyMetrics_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getSummarizedTopologyMetrics_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list266 = iprot.readListBegin();
                  struct.success = new ArrayList<MetricInfo>(_list266.size);
                  MetricInfo _elem267;
                  for (int _i268 = 0; _i268 < _list266.size; ++_i268)
                  {
                    _elem267 = new MetricInfo();
                    _elem267.read(iprot);
                    struct.success.add(_elem267);
                  }
                  iprot.readListEnd();
                }
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getSummarizedTopologyMetrics_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (MetricInfo _iter269 : struct.success)
            {
              _iter269.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getSummarizedTopologyMetrics_resultTupleSchemeFactory implements SchemeFactory {
      public getSummarizedTopologyMetrics_resultTupleScheme getScheme() {
        return new getSummarizedTopologyMetrics_resultTupleScheme();
      }
    }

    private static class getSummarizedTopologyMetrics_resultTupleScheme extends TupleScheme<getSummarizedTopologyMetrics_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getSummarizedTopologyMetrics_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          {
            oprot.writeI32(struct.success.size());
            for (MetricInfo _iter270 : struct.success)
            {
              _iter270.write(oprot);
            }
          }
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getSummarizedTopologyMetrics_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list271 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<MetricInfo>(_list271.size);
            MetricInfo _elem272;
            for (int _i273 = 0; _i273 < _list271.size; ++_i273)
            {
              _elem272 = new MetricInfo();
              _elem272.read(iprot);
              struct.success.add(_elem272);
            }
          }
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class getVersion_args implements org.apache.thrift.TBase<getVersion_args, getVersion_args._Fields>, java.io.Serializable, Cloneable, Comparable<getVersion_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getVersion_args");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getVersion_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getVersion_argsTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getVersion_args.class, metaDataMap);
    }

    public getVersion_args() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getVersion_args(getVersion_args other) {
    }

    public getVersion_args deepCopy() {
      return new getVersion_args(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getVersion_args)
        return this.equals((getVersion_args)that);
      return false;
    }

    public boolean equals(getVersion_args that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(getVersion_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getVersion_args(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getVersion_argsStandardSchemeFactory implements SchemeFactory {
      public getVersion_argsStandardScheme getScheme() {
        return new getVersion_argsStandardScheme();
      }
    }

    private static class getVersion_argsStandardScheme extends StandardScheme<getVersion_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getVersion_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getVersion_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getVersion_argsTupleSchemeFactory implements SchemeFactory {
      public getVersion_argsTupleScheme getScheme() {
        return new getVersion_argsTupleScheme();
      }
    }

    private static class getVersion_argsTupleScheme extends TupleScheme<getVersion_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getVersion_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getVersion_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

  public static class getVersion_result implements org.apache.thrift.TBase<getVersion_result, getVersion_result._Fields>, java.io.Serializable, Cloneable, Comparable<getVersion_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getVersion_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getVersion_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getVersion_resultTupleSchemeFactory());
    }

    private String success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getVersion_result.class, metaDataMap);
    }

    public getVersion_result() {
    }

    public getVersion_result(
      String success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getVersion_result(getVersion_result other) {
      if (other.is_set_success()) {
        this.success = other.success;
      }
    }

    public getVersion_result deepCopy() {
      return new getVersion_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public String get_success() {
      return this.success;
    }

    public void set_success(String success) {
      this.success = success;
    }

    public void unset_success() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean is_set_success() {
      return this.success != null;
    }

    public void set_success_isSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unset_success();
        } else {
          set_success((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return get_success();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return is_set_success();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getVersion_result)
        return this.equals((getVersion_result)that);
      return false;
    }

    public boolean equals(getVersion_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.is_set_success();
      boolean that_present_success = true && that.is_set_success();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (is_set_success());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getVersion_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_success()).compareTo(other.is_set_success());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_success()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getVersion_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getVersion_resultStandardSchemeFactory implements SchemeFactory {
      public getVersion_resultStandardScheme getScheme() {
        return new getVersion_resultStandardScheme();
      }
    }

    private static class getVersion_resultStandardScheme extends StandardScheme<getVersion_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getVersion_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.set_success_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getVersion_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getVersion_resultTupleSchemeFactory implements SchemeFactory {
      public getVersion_resultTupleScheme getScheme() {
        return new getVersion_resultTupleScheme();
      }
    }

    private static class getVersion_resultTupleScheme extends TupleScheme<getVersion_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getVersion_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_success()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_success()) {
          oprot.writeString(struct.success);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getVersion_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.set_success_isSet(true);
        }
      }
    }

  }

  public static class updateTopology_args implements org.apache.thrift.TBase<updateTopology_args, updateTopology_args._Fields>, java.io.Serializable, Cloneable, Comparable<updateTopology_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateTopology_args");

    private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField UPLOADED_LOCATION_FIELD_DESC = new org.apache.thrift.protocol.TField("uploadedLocation", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField UPDATE_CONF_FIELD_DESC = new org.apache.thrift.protocol.TField("updateConf", org.apache.thrift.protocol.TType.STRING, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateTopology_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateTopology_argsTupleSchemeFactory());
    }

    private String name; // required
    private String uploadedLocation; // required
    private String updateConf; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      NAME((short)1, "name"),
      UPLOADED_LOCATION((short)2, "uploadedLocation"),
      UPDATE_CONF((short)3, "updateConf");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // NAME
            return NAME;
          case 2: // UPLOADED_LOCATION
            return UPLOADED_LOCATION;
          case 3: // UPDATE_CONF
            return UPDATE_CONF;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.UPLOADED_LOCATION, new org.apache.thrift.meta_data.FieldMetaData("uploadedLocation", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.UPDATE_CONF, new org.apache.thrift.meta_data.FieldMetaData("updateConf", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateTopology_args.class, metaDataMap);
    }

    public updateTopology_args() {
    }

    public updateTopology_args(
      String name,
      String uploadedLocation,
      String updateConf)
    {
      this();
      this.name = name;
      this.uploadedLocation = uploadedLocation;
      this.updateConf = updateConf;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateTopology_args(updateTopology_args other) {
      if (other.is_set_name()) {
        this.name = other.name;
      }
      if (other.is_set_uploadedLocation()) {
        this.uploadedLocation = other.uploadedLocation;
      }
      if (other.is_set_updateConf()) {
        this.updateConf = other.updateConf;
      }
    }

    public updateTopology_args deepCopy() {
      return new updateTopology_args(this);
    }

    @Override
    public void clear() {
      this.name = null;
      this.uploadedLocation = null;
      this.updateConf = null;
    }

    public String get_name() {
      return this.name;
    }

    public void set_name(String name) {
      this.name = name;
    }

    public void unset_name() {
      this.name = null;
    }

    /** Returns true if field name is set (has been assigned a value) and false otherwise */
    public boolean is_set_name() {
      return this.name != null;
    }

    public void set_name_isSet(boolean value) {
      if (!value) {
        this.name = null;
      }
    }

    public String get_uploadedLocation() {
      return this.uploadedLocation;
    }

    public void set_uploadedLocation(String uploadedLocation) {
      this.uploadedLocation = uploadedLocation;
    }

    public void unset_uploadedLocation() {
      this.uploadedLocation = null;
    }

    /** Returns true if field uploadedLocation is set (has been assigned a value) and false otherwise */
    public boolean is_set_uploadedLocation() {
      return this.uploadedLocation != null;
    }

    public void set_uploadedLocation_isSet(boolean value) {
      if (!value) {
        this.uploadedLocation = null;
      }
    }

    public String get_updateConf() {
      return this.updateConf;
    }

    public void set_updateConf(String updateConf) {
      this.updateConf = updateConf;
    }

    public void unset_updateConf() {
      this.updateConf = null;
    }

    /** Returns true if field updateConf is set (has been assigned a value) and false otherwise */
    public boolean is_set_updateConf() {
      return this.updateConf != null;
    }

    public void set_updateConf_isSet(boolean value) {
      if (!value) {
        this.updateConf = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case NAME:
        if (value == null) {
          unset_name();
        } else {
          set_name((String)value);
        }
        break;

      case UPLOADED_LOCATION:
        if (value == null) {
          unset_uploadedLocation();
        } else {
          set_uploadedLocation((String)value);
        }
        break;

      case UPDATE_CONF:
        if (value == null) {
          unset_updateConf();
        } else {
          set_updateConf((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case NAME:
        return get_name();

      case UPLOADED_LOCATION:
        return get_uploadedLocation();

      case UPDATE_CONF:
        return get_updateConf();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case NAME:
        return is_set_name();
      case UPLOADED_LOCATION:
        return is_set_uploadedLocation();
      case UPDATE_CONF:
        return is_set_updateConf();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateTopology_args)
        return this.equals((updateTopology_args)that);
      return false;
    }

    public boolean equals(updateTopology_args that) {
      if (that == null)
        return false;

      boolean this_present_name = true && this.is_set_name();
      boolean that_present_name = true && that.is_set_name();
      if (this_present_name || that_present_name) {
        if (!(this_present_name && that_present_name))
          return false;
        if (!this.name.equals(that.name))
          return false;
      }

      boolean this_present_uploadedLocation = true && this.is_set_uploadedLocation();
      boolean that_present_uploadedLocation = true && that.is_set_uploadedLocation();
      if (this_present_uploadedLocation || that_present_uploadedLocation) {
        if (!(this_present_uploadedLocation && that_present_uploadedLocation))
          return false;
        if (!this.uploadedLocation.equals(that.uploadedLocation))
          return false;
      }

      boolean this_present_updateConf = true && this.is_set_updateConf();
      boolean that_present_updateConf = true && that.is_set_updateConf();
      if (this_present_updateConf || that_present_updateConf) {
        if (!(this_present_updateConf && that_present_updateConf))
          return false;
        if (!this.updateConf.equals(that.updateConf))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_name = true && (is_set_name());
      list.add(present_name);
      if (present_name)
        list.add(name);

      boolean present_uploadedLocation = true && (is_set_uploadedLocation());
      list.add(present_uploadedLocation);
      if (present_uploadedLocation)
        list.add(uploadedLocation);

      boolean present_updateConf = true && (is_set_updateConf());
      list.add(present_updateConf);
      if (present_updateConf)
        list.add(updateConf);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateTopology_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_name()).compareTo(other.is_set_name());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_name()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_uploadedLocation()).compareTo(other.is_set_uploadedLocation());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_uploadedLocation()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.uploadedLocation, other.uploadedLocation);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_updateConf()).compareTo(other.is_set_updateConf());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_updateConf()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.updateConf, other.updateConf);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateTopology_args(");
      boolean first = true;

      sb.append("name:");
      if (this.name == null) {
        sb.append("null");
      } else {
        sb.append(this.name);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("uploadedLocation:");
      if (this.uploadedLocation == null) {
        sb.append("null");
      } else {
        sb.append(this.uploadedLocation);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("updateConf:");
      if (this.updateConf == null) {
        sb.append("null");
      } else {
        sb.append(this.updateConf);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateTopology_argsStandardSchemeFactory implements SchemeFactory {
      public updateTopology_argsStandardScheme getScheme() {
        return new updateTopology_argsStandardScheme();
      }
    }

    private static class updateTopology_argsStandardScheme extends StandardScheme<updateTopology_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateTopology_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // NAME
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.name = iprot.readString();
                struct.set_name_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // UPLOADED_LOCATION
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.uploadedLocation = iprot.readString();
                struct.set_uploadedLocation_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // UPDATE_CONF
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.updateConf = iprot.readString();
                struct.set_updateConf_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateTopology_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.name != null) {
          oprot.writeFieldBegin(NAME_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
        if (struct.uploadedLocation != null) {
          oprot.writeFieldBegin(UPLOADED_LOCATION_FIELD_DESC);
          oprot.writeString(struct.uploadedLocation);
          oprot.writeFieldEnd();
        }
        if (struct.updateConf != null) {
          oprot.writeFieldBegin(UPDATE_CONF_FIELD_DESC);
          oprot.writeString(struct.updateConf);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateTopology_argsTupleSchemeFactory implements SchemeFactory {
      public updateTopology_argsTupleScheme getScheme() {
        return new updateTopology_argsTupleScheme();
      }
    }

    private static class updateTopology_argsTupleScheme extends TupleScheme<updateTopology_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateTopology_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_name()) {
          optionals.set(0);
        }
        if (struct.is_set_uploadedLocation()) {
          optionals.set(1);
        }
        if (struct.is_set_updateConf()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.is_set_name()) {
          oprot.writeString(struct.name);
        }
        if (struct.is_set_uploadedLocation()) {
          oprot.writeString(struct.uploadedLocation);
        }
        if (struct.is_set_updateConf()) {
          oprot.writeString(struct.updateConf);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateTopology_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.name = iprot.readString();
          struct.set_name_isSet(true);
        }
        if (incoming.get(1)) {
          struct.uploadedLocation = iprot.readString();
          struct.set_uploadedLocation_isSet(true);
        }
        if (incoming.get(2)) {
          struct.updateConf = iprot.readString();
          struct.set_updateConf_isSet(true);
        }
      }
    }

  }

  public static class updateTopology_result implements org.apache.thrift.TBase<updateTopology_result, updateTopology_result._Fields>, java.io.Serializable, Cloneable, Comparable<updateTopology_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateTopology_result");

    private static final org.apache.thrift.protocol.TField E_FIELD_DESC = new org.apache.thrift.protocol.TField("e", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField ITE_FIELD_DESC = new org.apache.thrift.protocol.TField("ite", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateTopology_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateTopology_resultTupleSchemeFactory());
    }

    private NotAliveException e; // required
    private InvalidTopologyException ite; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      E((short)1, "e"),
      ITE((short)2, "ite");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // E
            return E;
          case 2: // ITE
            return ITE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.E, new org.apache.thrift.meta_data.FieldMetaData("e", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.ITE, new org.apache.thrift.meta_data.FieldMetaData("ite", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateTopology_result.class, metaDataMap);
    }

    public updateTopology_result() {
    }

    public updateTopology_result(
      NotAliveException e,
      InvalidTopologyException ite)
    {
      this();
      this.e = e;
      this.ite = ite;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateTopology_result(updateTopology_result other) {
      if (other.is_set_e()) {
        this.e = new NotAliveException(other.e);
      }
      if (other.is_set_ite()) {
        this.ite = new InvalidTopologyException(other.ite);
      }
    }

    public updateTopology_result deepCopy() {
      return new updateTopology_result(this);
    }

    @Override
    public void clear() {
      this.e = null;
      this.ite = null;
    }

    public NotAliveException get_e() {
      return this.e;
    }

    public void set_e(NotAliveException e) {
      this.e = e;
    }

    public void unset_e() {
      this.e = null;
    }

    /** Returns true if field e is set (has been assigned a value) and false otherwise */
    public boolean is_set_e() {
      return this.e != null;
    }

    public void set_e_isSet(boolean value) {
      if (!value) {
        this.e = null;
      }
    }

    public InvalidTopologyException get_ite() {
      return this.ite;
    }

    public void set_ite(InvalidTopologyException ite) {
      this.ite = ite;
    }

    public void unset_ite() {
      this.ite = null;
    }

    /** Returns true if field ite is set (has been assigned a value) and false otherwise */
    public boolean is_set_ite() {
      return this.ite != null;
    }

    public void set_ite_isSet(boolean value) {
      if (!value) {
        this.ite = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case E:
        if (value == null) {
          unset_e();
        } else {
          set_e((NotAliveException)value);
        }
        break;

      case ITE:
        if (value == null) {
          unset_ite();
        } else {
          set_ite((InvalidTopologyException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case E:
        return get_e();

      case ITE:
        return get_ite();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case E:
        return is_set_e();
      case ITE:
        return is_set_ite();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateTopology_result)
        return this.equals((updateTopology_result)that);
      return false;
    }

    public boolean equals(updateTopology_result that) {
      if (that == null)
        return false;

      boolean this_present_e = true && this.is_set_e();
      boolean that_present_e = true && that.is_set_e();
      if (this_present_e || that_present_e) {
        if (!(this_present_e && that_present_e))
          return false;
        if (!this.e.equals(that.e))
          return false;
      }

      boolean this_present_ite = true && this.is_set_ite();
      boolean that_present_ite = true && that.is_set_ite();
      if (this_present_ite || that_present_ite) {
        if (!(this_present_ite && that_present_ite))
          return false;
        if (!this.ite.equals(that.ite))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_e = true && (is_set_e());
      list.add(present_e);
      if (present_e)
        list.add(e);

      boolean present_ite = true && (is_set_ite());
      list.add(present_ite);
      if (present_ite)
        list.add(ite);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateTopology_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_e()).compareTo(other.is_set_e());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_e()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.e, other.e);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(is_set_ite()).compareTo(other.is_set_ite());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_ite()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ite, other.ite);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateTopology_result(");
      boolean first = true;

      sb.append("e:");
      if (this.e == null) {
        sb.append("null");
      } else {
        sb.append(this.e);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("ite:");
      if (this.ite == null) {
        sb.append("null");
      } else {
        sb.append(this.ite);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateTopology_resultStandardSchemeFactory implements SchemeFactory {
      public updateTopology_resultStandardScheme getScheme() {
        return new updateTopology_resultStandardScheme();
      }
    }

    private static class updateTopology_resultStandardScheme extends StandardScheme<updateTopology_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateTopology_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // E
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.e = new NotAliveException();
                struct.e.read(iprot);
                struct.set_e_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ITE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.ite = new InvalidTopologyException();
                struct.ite.read(iprot);
                struct.set_ite_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateTopology_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.e != null) {
          oprot.writeFieldBegin(E_FIELD_DESC);
          struct.e.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.ite != null) {
          oprot.writeFieldBegin(ITE_FIELD_DESC);
          struct.ite.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateTopology_resultTupleSchemeFactory implements SchemeFactory {
      public updateTopology_resultTupleScheme getScheme() {
        return new updateTopology_resultTupleScheme();
      }
    }

    private static class updateTopology_resultTupleScheme extends TupleScheme<updateTopology_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateTopology_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_e()) {
          optionals.set(0);
        }
        if (struct.is_set_ite()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.is_set_e()) {
          struct.e.write(oprot);
        }
        if (struct.is_set_ite()) {
          struct.ite.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateTopology_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.e = new NotAliveException();
          struct.e.read(iprot);
          struct.set_e_isSet(true);
        }
        if (incoming.get(1)) {
          struct.ite = new InvalidTopologyException();
          struct.ite.read(iprot);
          struct.set_ite_isSet(true);
        }
      }
    }

  }

  public static class updateTaskHeartbeat_args implements org.apache.thrift.TBase<updateTaskHeartbeat_args, updateTaskHeartbeat_args._Fields>, java.io.Serializable, Cloneable, Comparable<updateTaskHeartbeat_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateTaskHeartbeat_args");

    private static final org.apache.thrift.protocol.TField TASK_HBS_FIELD_DESC = new org.apache.thrift.protocol.TField("taskHbs", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateTaskHeartbeat_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateTaskHeartbeat_argsTupleSchemeFactory());
    }

    private TopologyTaskHbInfo taskHbs; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      TASK_HBS((short)1, "taskHbs");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // TASK_HBS
            return TASK_HBS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.TASK_HBS, new org.apache.thrift.meta_data.FieldMetaData("taskHbs", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TopologyTaskHbInfo.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateTaskHeartbeat_args.class, metaDataMap);
    }

    public updateTaskHeartbeat_args() {
    }

    public updateTaskHeartbeat_args(
      TopologyTaskHbInfo taskHbs)
    {
      this();
      this.taskHbs = taskHbs;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateTaskHeartbeat_args(updateTaskHeartbeat_args other) {
      if (other.is_set_taskHbs()) {
        this.taskHbs = new TopologyTaskHbInfo(other.taskHbs);
      }
    }

    public updateTaskHeartbeat_args deepCopy() {
      return new updateTaskHeartbeat_args(this);
    }

    @Override
    public void clear() {
      this.taskHbs = null;
    }

    public TopologyTaskHbInfo get_taskHbs() {
      return this.taskHbs;
    }

    public void set_taskHbs(TopologyTaskHbInfo taskHbs) {
      this.taskHbs = taskHbs;
    }

    public void unset_taskHbs() {
      this.taskHbs = null;
    }

    /** Returns true if field taskHbs is set (has been assigned a value) and false otherwise */
    public boolean is_set_taskHbs() {
      return this.taskHbs != null;
    }

    public void set_taskHbs_isSet(boolean value) {
      if (!value) {
        this.taskHbs = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case TASK_HBS:
        if (value == null) {
          unset_taskHbs();
        } else {
          set_taskHbs((TopologyTaskHbInfo)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case TASK_HBS:
        return get_taskHbs();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case TASK_HBS:
        return is_set_taskHbs();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateTaskHeartbeat_args)
        return this.equals((updateTaskHeartbeat_args)that);
      return false;
    }

    public boolean equals(updateTaskHeartbeat_args that) {
      if (that == null)
        return false;

      boolean this_present_taskHbs = true && this.is_set_taskHbs();
      boolean that_present_taskHbs = true && that.is_set_taskHbs();
      if (this_present_taskHbs || that_present_taskHbs) {
        if (!(this_present_taskHbs && that_present_taskHbs))
          return false;
        if (!this.taskHbs.equals(that.taskHbs))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_taskHbs = true && (is_set_taskHbs());
      list.add(present_taskHbs);
      if (present_taskHbs)
        list.add(taskHbs);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateTaskHeartbeat_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(is_set_taskHbs()).compareTo(other.is_set_taskHbs());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (is_set_taskHbs()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.taskHbs, other.taskHbs);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateTaskHeartbeat_args(");
      boolean first = true;

      sb.append("taskHbs:");
      if (this.taskHbs == null) {
        sb.append("null");
      } else {
        sb.append(this.taskHbs);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
      if (taskHbs != null) {
        taskHbs.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateTaskHeartbeat_argsStandardSchemeFactory implements SchemeFactory {
      public updateTaskHeartbeat_argsStandardScheme getScheme() {
        return new updateTaskHeartbeat_argsStandardScheme();
      }
    }

    private static class updateTaskHeartbeat_argsStandardScheme extends StandardScheme<updateTaskHeartbeat_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateTaskHeartbeat_args struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // TASK_HBS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.taskHbs = new TopologyTaskHbInfo();
                struct.taskHbs.read(iprot);
                struct.set_taskHbs_isSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateTaskHeartbeat_args struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.taskHbs != null) {
          oprot.writeFieldBegin(TASK_HBS_FIELD_DESC);
          struct.taskHbs.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateTaskHeartbeat_argsTupleSchemeFactory implements SchemeFactory {
      public updateTaskHeartbeat_argsTupleScheme getScheme() {
        return new updateTaskHeartbeat_argsTupleScheme();
      }
    }

    private static class updateTaskHeartbeat_argsTupleScheme extends TupleScheme<updateTaskHeartbeat_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateTaskHeartbeat_args struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.is_set_taskHbs()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.is_set_taskHbs()) {
          struct.taskHbs.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateTaskHeartbeat_args struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.taskHbs = new TopologyTaskHbInfo();
          struct.taskHbs.read(iprot);
          struct.set_taskHbs_isSet(true);
        }
      }
    }

  }

  public static class updateTaskHeartbeat_result implements org.apache.thrift.TBase<updateTaskHeartbeat_result, updateTaskHeartbeat_result._Fields>, java.io.Serializable, Cloneable, Comparable<updateTaskHeartbeat_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateTaskHeartbeat_result");


    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateTaskHeartbeat_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateTaskHeartbeat_resultTupleSchemeFactory());
    }


    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
;

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateTaskHeartbeat_result.class, metaDataMap);
    }

    public updateTaskHeartbeat_result() {
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateTaskHeartbeat_result(updateTaskHeartbeat_result other) {
    }

    public updateTaskHeartbeat_result deepCopy() {
      return new updateTaskHeartbeat_result(this);
    }

    @Override
    public void clear() {
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateTaskHeartbeat_result)
        return this.equals((updateTaskHeartbeat_result)that);
      return false;
    }

    public boolean equals(updateTaskHeartbeat_result that) {
      if (that == null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      return list.hashCode();
    }

    @Override
    public int compareTo(updateTaskHeartbeat_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateTaskHeartbeat_result(");
      boolean first = true;

      sb.append(")");
      return sb.toString();
    }

    public void validate() throws TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateTaskHeartbeat_resultStandardSchemeFactory implements SchemeFactory {
      public updateTaskHeartbeat_resultStandardScheme getScheme() {
        return new updateTaskHeartbeat_resultStandardScheme();
      }
    }

    private static class updateTaskHeartbeat_resultStandardScheme extends StandardScheme<updateTaskHeartbeat_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateTaskHeartbeat_result struct) throws TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateTaskHeartbeat_result struct) throws TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateTaskHeartbeat_resultTupleSchemeFactory implements SchemeFactory {
      public updateTaskHeartbeat_resultTupleScheme getScheme() {
        return new updateTaskHeartbeat_resultTupleScheme();
      }
    }

    private static class updateTaskHeartbeat_resultTupleScheme extends TupleScheme<updateTaskHeartbeat_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateTaskHeartbeat_result struct) throws TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateTaskHeartbeat_result struct) throws TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
      }
    }

  }

}
