accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From e..@apache.org
Subject [2/2] git commit: ACCUMULO-9998 add waitForBalance API call
Date Wed, 16 Jul 2014 18:51:12 GMT
ACCUMULO-9998 add waitForBalance API call


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/f0a67188
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/f0a67188
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/f0a67188

Branch: refs/heads/master
Commit: f0a67188f0ecf4b7a0a08f1bbd6489b2ae1c01ca
Parents: d749430
Author: Eric C. Newton <eric.newton@gmail.com>
Authored: Wed Jul 16 14:50:40 2014 -0400
Committer: Eric C. Newton <eric.newton@gmail.com>
Committed: Wed Jul 16 14:50:40 2014 -0400

----------------------------------------------------------------------
 .../core/client/admin/InstanceOperations.java   |   5 +
 .../client/impl/InstanceOperationsImpl.java     |  16 +
 .../client/mock/MockInstanceOperations.java     |   4 +
 .../core/master/thrift/MasterClientService.java | 856 +++++++++++++++++++
 core/src/main/thrift/master.thrift              |   1 +
 .../java/org/apache/accumulo/master/Master.java |  18 +
 .../master/MasterClientServiceHandler.java      |   5 +
 .../apache/accumulo/test/WaitForBalanceIT.java  | 108 +++
 8 files changed, 1013 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/core/src/main/java/org/apache/accumulo/core/client/admin/InstanceOperations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/admin/InstanceOperations.java
b/core/src/main/java/org/apache/accumulo/core/client/admin/InstanceOperations.java
index 7b58bd4..04e1d0d 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/admin/InstanceOperations.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/admin/InstanceOperations.java
@@ -116,4 +116,9 @@ public interface InstanceOperations {
    */
   boolean testClassLoad(final String className, final String asTypeName) throws AccumuloException,
AccumuloSecurityException;
   
+  /**
+   *  Waits for the tablet balancer to run and return no migrations.
+   *  @since 1.7.0
+   */
+  void waitForBalance() throws AccumuloException;
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/core/src/main/java/org/apache/accumulo/core/client/impl/InstanceOperationsImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/InstanceOperationsImpl.java
b/core/src/main/java/org/apache/accumulo/core/client/impl/InstanceOperationsImpl.java
index 9a49be9..c5f7634 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/InstanceOperationsImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/InstanceOperationsImpl.java
@@ -211,4 +211,20 @@ public class InstanceOperationsImpl implements InstanceOperations {
       }
     }
   }
+
+  @Override
+  public void waitForBalance() throws AccumuloException {
+    try {
+      MasterClient.execute(instance, new ClientExec<MasterClientService.Client>() {
+        @Override
+        public void execute(MasterClientService.Client client) throws Exception {
+          client.waitForBalance(Tracer.traceInfo());
+        }
+      });
+    } catch (AccumuloSecurityException ex) {
+      // should never happen
+      throw new RuntimeException("Unexpected exception thrown", ex);
+    }
+    
+  }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/core/src/main/java/org/apache/accumulo/core/client/mock/MockInstanceOperations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/mock/MockInstanceOperations.java
b/core/src/main/java/org/apache/accumulo/core/client/mock/MockInstanceOperations.java
index 8f01813..87359bc 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/mock/MockInstanceOperations.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/mock/MockInstanceOperations.java
@@ -86,4 +86,8 @@ class MockInstanceOperations implements InstanceOperations {
   public void ping(String tserver) throws AccumuloException {
 
   }
+
+  @Override
+  public void waitForBalance() throws AccumuloException {
+  }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/core/src/main/java/org/apache/accumulo/core/master/thrift/MasterClientService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/master/thrift/MasterClientService.java
b/core/src/main/java/org/apache/accumulo/core/master/thrift/MasterClientService.java
index 0800aa9..9c850a8 100644
--- a/core/src/main/java/org/apache/accumulo/core/master/thrift/MasterClientService.java
+++ b/core/src/main/java/org/apache/accumulo/core/master/thrift/MasterClientService.java
@@ -76,6 +76,8 @@ import org.slf4j.LoggerFactory;
 
     public MasterMonitorInfo getMasterStats(org.apache.accumulo.trace.thrift.TInfo tinfo,
org.apache.accumulo.core.security.thrift.TCredentials credentials) throws org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException,
org.apache.thrift.TException;
 
+    public void waitForBalance(org.apache.accumulo.trace.thrift.TInfo tinfo) throws org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException,
org.apache.thrift.TException;
+
     public void reportSplitExtent(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.accumulo.core.security.thrift.TCredentials
credentials, String serverName, TabletSplit split) throws org.apache.thrift.TException;
 
     public void reportTabletStatus(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.accumulo.core.security.thrift.TCredentials
credentials, String serverName, TabletLoadState status, org.apache.accumulo.core.data.thrift.TKeyExtent
tablet) throws org.apache.thrift.TException;
@@ -108,6 +110,8 @@ import org.slf4j.LoggerFactory;
 
     public void getMasterStats(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.accumulo.core.security.thrift.TCredentials
credentials, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
 
+    public void waitForBalance(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.thrift.async.AsyncMethodCallback
resultHandler) throws org.apache.thrift.TException;
+
     public void reportSplitExtent(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.accumulo.core.security.thrift.TCredentials
credentials, String serverName, TabletSplit split, org.apache.thrift.async.AsyncMethodCallback
resultHandler) throws org.apache.thrift.TException;
 
     public void reportTabletStatus(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.accumulo.core.security.thrift.TCredentials
credentials, String serverName, TabletLoadState status, org.apache.accumulo.core.data.thrift.TKeyExtent
tablet, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
@@ -469,6 +473,29 @@ import org.slf4j.LoggerFactory;
       throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT,
"getMasterStats failed: unknown result");
     }
 
+    public void waitForBalance(org.apache.accumulo.trace.thrift.TInfo tinfo) throws org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException,
org.apache.thrift.TException
+    {
+      send_waitForBalance(tinfo);
+      recv_waitForBalance();
+    }
+
+    public void send_waitForBalance(org.apache.accumulo.trace.thrift.TInfo tinfo) throws
org.apache.thrift.TException
+    {
+      waitForBalance_args args = new waitForBalance_args();
+      args.setTinfo(tinfo);
+      sendBase("waitForBalance", args);
+    }
+
+    public void recv_waitForBalance() throws org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException,
org.apache.thrift.TException
+    {
+      waitForBalance_result result = new waitForBalance_result();
+      receiveBase(result, "waitForBalance");
+      if (result.sec != null) {
+        throw result.sec;
+      }
+      return;
+    }
+
     public void reportSplitExtent(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.accumulo.core.security.thrift.TCredentials
credentials, String serverName, TabletSplit split) throws org.apache.thrift.TException
     {
       send_reportSplitExtent(tinfo, credentials, serverName, split);
@@ -1007,6 +1034,38 @@ import org.slf4j.LoggerFactory;
       }
     }
 
+    public void waitForBalance(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.thrift.async.AsyncMethodCallback
resultHandler) throws org.apache.thrift.TException {
+      checkReady();
+      waitForBalance_call method_call = new waitForBalance_call(tinfo, resultHandler, this,
___protocolFactory, ___transport);
+      this.___currentMethod = method_call;
+      ___manager.call(method_call);
+    }
+
+    public static class waitForBalance_call extends org.apache.thrift.async.TAsyncMethodCall
{
+      private org.apache.accumulo.trace.thrift.TInfo tinfo;
+      public waitForBalance_call(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.thrift.async.AsyncMethodCallback
resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory
protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException
{
+        super(client, protocolFactory, transport, resultHandler, false);
+        this.tinfo = tinfo;
+      }
+
+      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException
{
+        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("waitForBalance",
org.apache.thrift.protocol.TMessageType.CALL, 0));
+        waitForBalance_args args = new waitForBalance_args();
+        args.setTinfo(tinfo);
+        args.write(prot);
+        prot.writeMessageEnd();
+      }
+
+      public void getResult() throws org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException,
org.apache.thrift.TException {
+        if (getState() != org.apache.thrift.async.TAsyncMethodCall.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_waitForBalance();
+      }
+    }
+
     public void reportSplitExtent(org.apache.accumulo.trace.thrift.TInfo tinfo, org.apache.accumulo.core.security.thrift.TCredentials
credentials, String serverName, TabletSplit split, org.apache.thrift.async.AsyncMethodCallback
resultHandler) throws org.apache.thrift.TException {
       checkReady();
       reportSplitExtent_call method_call = new reportSplitExtent_call(tinfo, credentials,
serverName, split, resultHandler, this, ___protocolFactory, ___transport);
@@ -1115,6 +1174,7 @@ import org.slf4j.LoggerFactory;
       processMap.put("setSystemProperty", new setSystemProperty());
       processMap.put("removeSystemProperty", new removeSystemProperty());
       processMap.put("getMasterStats", new getMasterStats());
+      processMap.put("waitForBalance", new waitForBalance());
       processMap.put("reportSplitExtent", new reportSplitExtent());
       processMap.put("reportTabletStatus", new reportTabletStatus());
       return processMap;
@@ -1421,6 +1481,30 @@ import org.slf4j.LoggerFactory;
       }
     }
 
+    public static class waitForBalance<I extends Iface> extends org.apache.thrift.ProcessFunction<I,
waitForBalance_args> {
+      public waitForBalance() {
+        super("waitForBalance");
+      }
+
+      public waitForBalance_args getEmptyArgsInstance() {
+        return new waitForBalance_args();
+      }
+
+      protected boolean isOneway() {
+        return false;
+      }
+
+      public waitForBalance_result getResult(I iface, waitForBalance_args args) throws org.apache.thrift.TException
{
+        waitForBalance_result result = new waitForBalance_result();
+        try {
+          iface.waitForBalance(args.tinfo);
+        } catch (org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException sec)
{
+          result.sec = sec;
+        }
+        return result;
+      }
+    }
+
     public static class reportSplitExtent<I extends Iface> extends org.apache.thrift.ProcessFunction<I,
reportSplitExtent_args> {
       public reportSplitExtent() {
         super("reportSplitExtent");
@@ -1484,6 +1568,7 @@ import org.slf4j.LoggerFactory;
       processMap.put("setSystemProperty", new setSystemProperty());
       processMap.put("removeSystemProperty", new removeSystemProperty());
       processMap.put("getMasterStats", new getMasterStats());
+      processMap.put("waitForBalance", new waitForBalance());
       processMap.put("reportSplitExtent", new reportSplitExtent());
       processMap.put("reportTabletStatus", new reportTabletStatus());
       return processMap;
@@ -2194,6 +2279,62 @@ import org.slf4j.LoggerFactory;
       }
     }
 
+    public static class waitForBalance<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I,
waitForBalance_args, Void> {
+      public waitForBalance() {
+        super("waitForBalance");
+      }
+
+      public waitForBalance_args getEmptyArgsInstance() {
+        return new waitForBalance_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) {
+            waitForBalance_result result = new waitForBalance_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;
+            waitForBalance_result result = new waitForBalance_result();
+            if (e instanceof org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException)
{
+                        result.sec = (org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException)
e;
+                        result.setSecIsSet(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, waitForBalance_args args, org.apache.thrift.async.AsyncMethodCallback<Void>
resultHandler) throws TException {
+        iface.waitForBalance(args.tinfo,resultHandler);
+      }
+    }
+
     public static class reportSplitExtent<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I,
reportSplitExtent_args, Void> {
       public reportSplitExtent() {
         super("reportSplitExtent");
@@ -15235,6 +15376,721 @@ import org.slf4j.LoggerFactory;
 
   }
 
+  public static class waitForBalance_args implements org.apache.thrift.TBase<waitForBalance_args,
waitForBalance_args._Fields>, java.io.Serializable, Cloneable, Comparable<waitForBalance_args>
  {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("waitForBalance_args");
+
+    private static final org.apache.thrift.protocol.TField TINFO_FIELD_DESC = new org.apache.thrift.protocol.TField("tinfo",
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 waitForBalance_argsStandardSchemeFactory());
+      schemes.put(TupleScheme.class, new waitForBalance_argsTupleSchemeFactory());
+    }
+
+    public org.apache.accumulo.trace.thrift.TInfo tinfo; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding
and manipulating them. */
+    @SuppressWarnings("all") public enum _Fields implements org.apache.thrift.TFieldIdEnum
{
+      TINFO((short)1, "tinfo");
+
+      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: // TINFO
+            return TINFO;
+          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.TINFO, new org.apache.thrift.meta_data.FieldMetaData("tinfo", org.apache.thrift.TFieldRequirementType.DEFAULT,

+          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT,
org.apache.accumulo.trace.thrift.TInfo.class)));
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(waitForBalance_args.class,
metaDataMap);
+    }
+
+    public waitForBalance_args() {
+    }
+
+    public waitForBalance_args(
+      org.apache.accumulo.trace.thrift.TInfo tinfo)
+    {
+      this();
+      this.tinfo = tinfo;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public waitForBalance_args(waitForBalance_args other) {
+      if (other.isSetTinfo()) {
+        this.tinfo = new org.apache.accumulo.trace.thrift.TInfo(other.tinfo);
+      }
+    }
+
+    public waitForBalance_args deepCopy() {
+      return new waitForBalance_args(this);
+    }
+
+    @Override
+    public void clear() {
+      this.tinfo = null;
+    }
+
+    public org.apache.accumulo.trace.thrift.TInfo getTinfo() {
+      return this.tinfo;
+    }
+
+    public waitForBalance_args setTinfo(org.apache.accumulo.trace.thrift.TInfo tinfo) {
+      this.tinfo = tinfo;
+      return this;
+    }
+
+    public void unsetTinfo() {
+      this.tinfo = null;
+    }
+
+    /** Returns true if field tinfo is set (has been assigned a value) and false otherwise
*/
+    public boolean isSetTinfo() {
+      return this.tinfo != null;
+    }
+
+    public void setTinfoIsSet(boolean value) {
+      if (!value) {
+        this.tinfo = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case TINFO:
+        if (value == null) {
+          unsetTinfo();
+        } else {
+          setTinfo((org.apache.accumulo.trace.thrift.TInfo)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case TINFO:
+        return getTinfo();
+
+      }
+      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 TINFO:
+        return isSetTinfo();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof waitForBalance_args)
+        return this.equals((waitForBalance_args)that);
+      return false;
+    }
+
+    public boolean equals(waitForBalance_args that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_tinfo = true && this.isSetTinfo();
+      boolean that_present_tinfo = true && that.isSetTinfo();
+      if (this_present_tinfo || that_present_tinfo) {
+        if (!(this_present_tinfo && that_present_tinfo))
+          return false;
+        if (!this.tinfo.equals(that.tinfo))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    @Override
+    public int compareTo(waitForBalance_args other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+
+      lastComparison = Boolean.valueOf(isSetTinfo()).compareTo(other.isSetTinfo());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetTinfo()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tinfo, other.tinfo);
+        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 org.apache.thrift.TException
{
+      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException
{
+      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("waitForBalance_args(");
+      boolean first = true;
+
+      sb.append("tinfo:");
+      if (this.tinfo == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.tinfo);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+      // check for sub-struct validity
+      if (tinfo != null) {
+        tinfo.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 (org.apache.thrift.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 (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private static class waitForBalance_argsStandardSchemeFactory implements SchemeFactory
{
+      public waitForBalance_argsStandardScheme getScheme() {
+        return new waitForBalance_argsStandardScheme();
+      }
+    }
+
+    private static class waitForBalance_argsStandardScheme extends StandardScheme<waitForBalance_args>
{
+
+      public void read(org.apache.thrift.protocol.TProtocol iprot, waitForBalance_args struct)
throws org.apache.thrift.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: // TINFO
+              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
+                struct.tinfo = new org.apache.accumulo.trace.thrift.TInfo();
+                struct.tinfo.read(iprot);
+                struct.setTinfoIsSet(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();
+
+        // check for required fields of primitive type, which can't be checked in the validate
method
+        struct.validate();
+      }
+
+      public void write(org.apache.thrift.protocol.TProtocol oprot, waitForBalance_args struct)
throws org.apache.thrift.TException {
+        struct.validate();
+
+        oprot.writeStructBegin(STRUCT_DESC);
+        if (struct.tinfo != null) {
+          oprot.writeFieldBegin(TINFO_FIELD_DESC);
+          struct.tinfo.write(oprot);
+          oprot.writeFieldEnd();
+        }
+        oprot.writeFieldStop();
+        oprot.writeStructEnd();
+      }
+
+    }
+
+    private static class waitForBalance_argsTupleSchemeFactory implements SchemeFactory {
+      public waitForBalance_argsTupleScheme getScheme() {
+        return new waitForBalance_argsTupleScheme();
+      }
+    }
+
+    private static class waitForBalance_argsTupleScheme extends TupleScheme<waitForBalance_args>
{
+
+      @Override
+      public void write(org.apache.thrift.protocol.TProtocol prot, waitForBalance_args struct)
throws org.apache.thrift.TException {
+        TTupleProtocol oprot = (TTupleProtocol) prot;
+        BitSet optionals = new BitSet();
+        if (struct.isSetTinfo()) {
+          optionals.set(0);
+        }
+        oprot.writeBitSet(optionals, 1);
+        if (struct.isSetTinfo()) {
+          struct.tinfo.write(oprot);
+        }
+      }
+
+      @Override
+      public void read(org.apache.thrift.protocol.TProtocol prot, waitForBalance_args struct)
throws org.apache.thrift.TException {
+        TTupleProtocol iprot = (TTupleProtocol) prot;
+        BitSet incoming = iprot.readBitSet(1);
+        if (incoming.get(0)) {
+          struct.tinfo = new org.apache.accumulo.trace.thrift.TInfo();
+          struct.tinfo.read(iprot);
+          struct.setTinfoIsSet(true);
+        }
+      }
+    }
+
+  }
+
+  public static class waitForBalance_result implements org.apache.thrift.TBase<waitForBalance_result,
waitForBalance_result._Fields>, java.io.Serializable, Cloneable, Comparable<waitForBalance_result>
  {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("waitForBalance_result");
+
+    private static final org.apache.thrift.protocol.TField SEC_FIELD_DESC = new org.apache.thrift.protocol.TField("sec",
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 waitForBalance_resultStandardSchemeFactory());
+      schemes.put(TupleScheme.class, new waitForBalance_resultTupleSchemeFactory());
+    }
+
+    public org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException sec; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding
and manipulating them. */
+    @SuppressWarnings("all") public enum _Fields implements org.apache.thrift.TFieldIdEnum
{
+      SEC((short)1, "sec");
+
+      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: // SEC
+            return SEC;
+          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.SEC, new org.apache.thrift.meta_data.FieldMetaData("sec", 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(waitForBalance_result.class,
metaDataMap);
+    }
+
+    public waitForBalance_result() {
+    }
+
+    public waitForBalance_result(
+      org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException sec)
+    {
+      this();
+      this.sec = sec;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public waitForBalance_result(waitForBalance_result other) {
+      if (other.isSetSec()) {
+        this.sec = new org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException(other.sec);
+      }
+    }
+
+    public waitForBalance_result deepCopy() {
+      return new waitForBalance_result(this);
+    }
+
+    @Override
+    public void clear() {
+      this.sec = null;
+    }
+
+    public org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException getSec() {
+      return this.sec;
+    }
+
+    public waitForBalance_result setSec(org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException
sec) {
+      this.sec = sec;
+      return this;
+    }
+
+    public void unsetSec() {
+      this.sec = null;
+    }
+
+    /** Returns true if field sec is set (has been assigned a value) and false otherwise
*/
+    public boolean isSetSec() {
+      return this.sec != null;
+    }
+
+    public void setSecIsSet(boolean value) {
+      if (!value) {
+        this.sec = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case SEC:
+        if (value == null) {
+          unsetSec();
+        } else {
+          setSec((org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case SEC:
+        return getSec();
+
+      }
+      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 SEC:
+        return isSetSec();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof waitForBalance_result)
+        return this.equals((waitForBalance_result)that);
+      return false;
+    }
+
+    public boolean equals(waitForBalance_result that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_sec = true && this.isSetSec();
+      boolean that_present_sec = true && that.isSetSec();
+      if (this_present_sec || that_present_sec) {
+        if (!(this_present_sec && that_present_sec))
+          return false;
+        if (!this.sec.equals(that.sec))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    @Override
+    public int compareTo(waitForBalance_result other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+
+      lastComparison = Boolean.valueOf(isSetSec()).compareTo(other.isSetSec());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetSec()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sec, other.sec);
+        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 org.apache.thrift.TException
{
+      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException
{
+      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+      }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("waitForBalance_result(");
+      boolean first = true;
+
+      sb.append("sec:");
+      if (this.sec == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.sec);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.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 (org.apache.thrift.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 (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private static class waitForBalance_resultStandardSchemeFactory implements SchemeFactory
{
+      public waitForBalance_resultStandardScheme getScheme() {
+        return new waitForBalance_resultStandardScheme();
+      }
+    }
+
+    private static class waitForBalance_resultStandardScheme extends StandardScheme<waitForBalance_result>
{
+
+      public void read(org.apache.thrift.protocol.TProtocol iprot, waitForBalance_result
struct) throws org.apache.thrift.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: // SEC
+              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
+                struct.sec = new org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException();
+                struct.sec.read(iprot);
+                struct.setSecIsSet(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();
+
+        // check for required fields of primitive type, which can't be checked in the validate
method
+        struct.validate();
+      }
+
+      public void write(org.apache.thrift.protocol.TProtocol oprot, waitForBalance_result
struct) throws org.apache.thrift.TException {
+        struct.validate();
+
+        oprot.writeStructBegin(STRUCT_DESC);
+        if (struct.sec != null) {
+          oprot.writeFieldBegin(SEC_FIELD_DESC);
+          struct.sec.write(oprot);
+          oprot.writeFieldEnd();
+        }
+        oprot.writeFieldStop();
+        oprot.writeStructEnd();
+      }
+
+    }
+
+    private static class waitForBalance_resultTupleSchemeFactory implements SchemeFactory
{
+      public waitForBalance_resultTupleScheme getScheme() {
+        return new waitForBalance_resultTupleScheme();
+      }
+    }
+
+    private static class waitForBalance_resultTupleScheme extends TupleScheme<waitForBalance_result>
{
+
+      @Override
+      public void write(org.apache.thrift.protocol.TProtocol prot, waitForBalance_result
struct) throws org.apache.thrift.TException {
+        TTupleProtocol oprot = (TTupleProtocol) prot;
+        BitSet optionals = new BitSet();
+        if (struct.isSetSec()) {
+          optionals.set(0);
+        }
+        oprot.writeBitSet(optionals, 1);
+        if (struct.isSetSec()) {
+          struct.sec.write(oprot);
+        }
+      }
+
+      @Override
+      public void read(org.apache.thrift.protocol.TProtocol prot, waitForBalance_result struct)
throws org.apache.thrift.TException {
+        TTupleProtocol iprot = (TTupleProtocol) prot;
+        BitSet incoming = iprot.readBitSet(1);
+        if (incoming.get(0)) {
+          struct.sec = new org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException();
+          struct.sec.read(iprot);
+          struct.setSecIsSet(true);
+        }
+      }
+    }
+
+  }
+
   public static class reportSplitExtent_args implements org.apache.thrift.TBase<reportSplitExtent_args,
reportSplitExtent_args._Fields>, java.io.Serializable, Cloneable, Comparable<reportSplitExtent_args>
  {
     private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("reportSplitExtent_args");
 

http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/core/src/main/thrift/master.thrift
----------------------------------------------------------------------
diff --git a/core/src/main/thrift/master.thrift b/core/src/main/thrift/master.thrift
index 38e9227..49fa262 100644
--- a/core/src/main/thrift/master.thrift
+++ b/core/src/main/thrift/master.thrift
@@ -164,6 +164,7 @@ service MasterClientService extends FateService {
 
   // system monitoring methods
   MasterMonitorInfo getMasterStats(2:trace.TInfo tinfo, 1:security.TCredentials credentials)
throws (1:client.ThriftSecurityException sec)
+  void waitForBalance(1:trace.TInfo tinfo) 
 
   // tablet server reporting
   oneway void reportSplitExtent(4:trace.TInfo tinfo, 1:security.TCredentials credentials,
2:string serverName, 3:TabletSplit split)

http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/server/master/src/main/java/org/apache/accumulo/master/Master.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/Master.java b/server/master/src/main/java/org/apache/accumulo/master/Master.java
index 85012d4..ff8390a 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/Master.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/Master.java
@@ -124,6 +124,7 @@ import org.apache.accumulo.server.zookeeper.ZooLock;
 import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
 import org.apache.accumulo.start.classloader.vfs.AccumuloVFSClassLoader;
 import org.apache.accumulo.start.classloader.vfs.ContextManager;
+import org.apache.accumulo.trace.thrift.TInfo;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.io.DataInputBuffer;
 import org.apache.hadoop.io.DataOutputBuffer;
@@ -163,6 +164,7 @@ public class Master implements LiveTServerSet.Listener, TableObserver,
CurrentSt
   final VolumeManager fs;
   final private Instance instance;
   final private String hostname;
+  final private Object balanceLock = new Object();
   final LiveTServerSet tserverSet;
   final private List<TabletGroupWatcher> watchers = new ArrayList<TabletGroupWatcher>();
   final SecurityOperation security;
@@ -868,6 +870,10 @@ public class Master implements LiveTServerSet.Listener, TableObserver,
CurrentSt
       }
       if (migrationsOut.size() > 0) {
         nextEvent.event("Migrating %d more tablets, %d total", migrationsOut.size(), migrations.size());
+      } else {
+        synchronized (balanceLock) {
+          balanceLock.notify();
+        }
       }
       return wait;
     }
@@ -1306,4 +1312,16 @@ public class Master implements LiveTServerSet.Listener, TableObserver,
CurrentSt
       }
     }
   }
+
+  public void waitForBalance(TInfo tinfo) {
+    synchronized (balanceLock) {
+      while (displayUnassigned() > 0 || migrations.size() > 0) {
+        try {
+          balanceLock.wait();
+        } catch (InterruptedException e) {
+          log.debug(e.toString(), e);
+        }
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/server/master/src/main/java/org/apache/accumulo/master/MasterClientServiceHandler.java
----------------------------------------------------------------------
diff --git a/server/master/src/main/java/org/apache/accumulo/master/MasterClientServiceHandler.java
b/server/master/src/main/java/org/apache/accumulo/master/MasterClientServiceHandler.java
index 8023169..60884c2 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/MasterClientServiceHandler.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/MasterClientServiceHandler.java
@@ -466,4 +466,9 @@ class MasterClientServiceHandler extends FateServiceHandler implements
MasterCli
     }
   }
 
+  @Override
+  public void waitForBalance(TInfo tinfo) throws TException {
+    master.waitForBalance(tinfo);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/f0a67188/test/src/test/java/org/apache/accumulo/test/WaitForBalanceIT.java
----------------------------------------------------------------------
diff --git a/test/src/test/java/org/apache/accumulo/test/WaitForBalanceIT.java b/test/src/test/java/org/apache/accumulo/test/WaitForBalanceIT.java
new file mode 100644
index 0000000..1b046ae
--- /dev/null
+++ b/test/src/test/java/org/apache/accumulo/test/WaitForBalanceIT.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.Scanner;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.metadata.MetadataTable;
+import org.apache.accumulo.core.metadata.RootTable;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema;
+import org.apache.accumulo.core.security.Authorizations;
+import org.apache.accumulo.test.functional.ConfigurableMacIT;
+import org.apache.hadoop.io.Text;
+import org.junit.Test;
+
+public class WaitForBalanceIT extends ConfigurableMacIT {
+  
+  @Test(timeout = 30 * 1000)
+  public void test() throws Exception {
+    final Connector c = getConnector();
+    c.instanceOperations().waitForBalance();
+    assertTrue(isBalanced());
+    final String tableName = getUniqueNames(1)[0];
+    c.tableOperations().create(tableName);
+    c.instanceOperations().waitForBalance();
+    final SortedSet<Text> partitionKeys = new TreeSet<Text>();
+    for (int i = 0; i < 1000; i++) {
+      partitionKeys.add(new Text("" + i));
+    }
+    c.tableOperations().addSplits(tableName, partitionKeys);
+    assertFalse(isBalanced());
+    c.instanceOperations().waitForBalance();
+    assertTrue(isBalanced());
+  }
+
+  private boolean isBalanced() throws Exception {
+    final Map<String, Integer> counts = new HashMap<String, Integer>();
+    int offline = 0;
+    final Connector c = getConnector();
+    for (String tableName : new String[]{MetadataTable.NAME, RootTable.NAME}) {
+      final Scanner s = c.createScanner(tableName, Authorizations.EMPTY);
+      s.setRange(MetadataSchema.TabletsSection.getRange());
+      s.fetchColumnFamily(MetadataSchema.TabletsSection.CurrentLocationColumnFamily.NAME);
+      MetadataSchema.TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.fetch(s);
+      String location = null;
+      for (Entry<Key,Value> entry : s) {
+        Key key = entry.getKey();
+        if (key.getColumnFamily().equals(MetadataSchema.TabletsSection.CurrentLocationColumnFamily.NAME))
{
+          location = key.getColumnQualifier().toString();
+        } else if (MetadataSchema.TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.hasColumns(key))
{
+          if (location == null) {
+            offline++;
+          } else {
+            Integer count = counts.get(location);
+            if (count == null)
+              count = new Integer(0);
+            count = new Integer(count.intValue() + 1);
+            counts.put(location, count);
+          }
+          location = null;
+        }
+      }
+    }
+    if (offline > 0) {
+      System.out.println("Offline tablets " + offline);
+      return false;
+    }
+    int average = 0;
+    for (Integer i : counts.values()) {
+      average += i;
+    }
+    average /= counts.size();
+    System.out.println(counts);
+    int tablesCount = c.tableOperations().list().size();
+    for (Entry<String,Integer> hostCount : counts.entrySet()) {
+      if (Math.abs(average - hostCount.getValue()) > tablesCount) {
+        System.out.println("Average " + average + " count " + hostCount.getKey() + ": " +
hostCount.getValue());
+        return false;
+      }
+    }
+    return true;
+  }
+  
+}


Mime
View raw message