You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by el...@apache.org on 2017/05/22 20:07:34 UTC

[38/49] hbase git commit: HBASE-17259 API to remove space quotas on a table/namespace

HBASE-17259 API to remove space quotas on a table/namespace


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

Branch: refs/heads/master
Commit: 6c9082fe162c2e940b556c9da5edc36e5501906e
Parents: 34ba143
Author: Josh Elser <el...@apache.org>
Authored: Wed Jan 11 12:47:06 2017 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Mon May 22 13:41:35 2017 -0400

----------------------------------------------------------------------
 .../hbase/quotas/QuotaSettingsFactory.java      |  22 +++
 .../hadoop/hbase/quotas/QuotaTableUtil.java     |   6 +-
 .../hadoop/hbase/quotas/SpaceLimitSettings.java |  44 ++++-
 .../hbase/quotas/TestQuotaSettingsFactory.java  |  20 +++
 .../shaded/protobuf/generated/QuotaProtos.java  | 157 +++++++++++++++---
 .../src/main/protobuf/Quota.proto               |   1 +
 .../hbase/protobuf/generated/QuotaProtos.java   | 159 ++++++++++++++++---
 hbase-protocol/src/main/protobuf/Quota.proto    |   1 +
 .../hadoop/hbase/quotas/MasterQuotaManager.java |   9 +-
 .../hadoop/hbase/quotas/TestQuotaAdmin.java     |  49 +++++-
 10 files changed, 423 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java
index 7f1c180..184277d 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java
@@ -316,6 +316,17 @@ public class QuotaSettingsFactory {
   }
 
   /**
+   * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given
+   * table.
+   *
+   * @param tableName The name of the table to remove the quota for.
+   * @return A {@link QuotaSettings} object.
+   */
+  public static QuotaSettings removeTableSpaceLimit(TableName tableName) {
+    return new SpaceLimitSettings(tableName, true);
+  }
+
+  /**
    * Creates a {@link QuotaSettings} object to limit the FileSystem space usage for the given
    * namespace to the given size in bytes. When the space usage is exceeded by all tables in the
    * namespace, the provided {@link SpaceViolationPolicy} is enacted on all tables in the namespace.
@@ -329,4 +340,15 @@ public class QuotaSettingsFactory {
       final String namespace, long sizeLimit, final SpaceViolationPolicy violationPolicy) {
     return new SpaceLimitSettings(namespace, sizeLimit, violationPolicy);
   }
+
+  /**
+   * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given
+	 * namespace.
+   *
+   * @param namespace The namespace to remove the quota on.
+   * @return A {@link QuotaSettings} object.
+   */
+  public static QuotaSettings removeNamespaceSpaceLimit(String namespace) {
+    return new SpaceLimitSettings(namespace, true);
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java
index 66535b2..ce4cd04 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java
@@ -422,7 +422,11 @@ public class QuotaTableUtil {
     boolean hasSettings = false;
     hasSettings |= quotas.hasThrottle();
     hasSettings |= quotas.hasBypassGlobals();
-    hasSettings |= quotas.hasSpace();
+    // Only when there is a space quota, make sure there's actually both fields provided
+    // Otherwise, it's a noop.
+    if (quotas.hasSpace()) {
+      hasSettings |= (quotas.getSpace().hasSoftLimit() && quotas.getSpace().hasViolationPolicy());
+    }
     return !hasSettings;
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java
index e54882e..8ff7623 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java
@@ -41,7 +41,15 @@ class SpaceLimitSettings extends QuotaSettings {
     if (0L > sizeLimit) {
       throw new IllegalArgumentException("Size limit must be a non-negative value.");
     }
-    proto = buildProtoQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
+    proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
+  }
+
+  SpaceLimitSettings(TableName tableName, boolean remove) {
+    super(null, Objects.requireNonNull(tableName), null);
+    if (!remove) {
+      throw new IllegalArgumentException("A value of 'false' for removing a quota makes no sense");
+    }
+    proto = buildProtoRemoveQuota();
   }
 
   SpaceLimitSettings(String namespace, long sizeLimit, SpaceViolationPolicy violationPolicy) {
@@ -49,7 +57,15 @@ class SpaceLimitSettings extends QuotaSettings {
     if (0L > sizeLimit) {
       throw new IllegalArgumentException("Size limit must be a non-negative value.");
     }
-    proto = buildProtoQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
+    proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
+  }
+
+  SpaceLimitSettings(String namespace, boolean remove) {
+    super(null, null, Objects.requireNonNull(namespace));
+    if (!remove) {
+      throw new IllegalArgumentException("A value of 'false' for removing a quota makes no sense");
+    }
+    proto = buildProtoRemoveQuota();
   }
 
   /**
@@ -59,7 +75,8 @@ class SpaceLimitSettings extends QuotaSettings {
    * @param violationPolicy The action to take when the quota is exceeded.
    * @return The protobuf SpaceQuota representation.
    */
-  private SpaceLimitRequest buildProtoQuota(long sizeLimit, SpaceViolationPolicy violationPolicy) {
+  private SpaceLimitRequest buildProtoAddQuota(
+      long sizeLimit, SpaceViolationPolicy violationPolicy) {
     return SpaceLimitRequest.newBuilder().setQuota(
         SpaceQuota.newBuilder()
             .setSoftLimit(sizeLimit)
@@ -69,6 +86,19 @@ class SpaceLimitSettings extends QuotaSettings {
   }
 
   /**
+   * Builds a {@link SpaceQuota} protobuf object to remove a quota.
+   *
+   * @return The protobuf SpaceQuota representation.
+   */
+  private SpaceLimitRequest buildProtoRemoveQuota() {
+    return SpaceLimitRequest.newBuilder().setQuota(
+        SpaceQuota.newBuilder()
+            .setRemove(true)
+            .build())
+        .build();
+  }
+
+  /**
    * Returns a copy of the internal state of <code>this</code>
    */
   SpaceLimitRequest getProto() {
@@ -159,8 +189,12 @@ class SpaceLimitSettings extends QuotaSettings {
     if (null != getNamespace()) {
       sb.append(", NAMESPACE => ").append(getNamespace());
     }
-    sb.append(", LIMIT => ").append(proto.getQuota().getSoftLimit());
-    sb.append(", VIOLATION_POLICY => ").append(proto.getQuota().getViolationPolicy());
+    if (proto.getQuota().getRemove()) {
+      sb.append(", REMOVE => ").append(proto.getQuota().getRemove());
+    } else {
+      sb.append(", LIMIT => ").append(proto.getQuota().getSoftLimit());
+      sb.append(", VIOLATION_POLICY => ").append(proto.getQuota().getViolationPolicy());
+    }
     return sb.toString();
   }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java b/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java
index e0012a7..edf6926 100644
--- a/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java
+++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java
@@ -144,5 +144,25 @@ public class TestQuotaSettingsFactory {
     SpaceQuota quota = protoRequest.getQuota();
     assertEquals(sizeLimit, quota.getSoftLimit());
     assertEquals(violationPolicy, ProtobufUtil.toViolationPolicy(quota.getViolationPolicy()));
+    assertFalse("The remove attribute should be false", quota.getRemove());
   }
+
+  @Test
+  public void testSpaceLimitSettingsForDeletes() {
+    final String ns = "ns1";
+    final TableName tn = TableName.valueOf("tn1");
+    QuotaSettings nsSettings = QuotaSettingsFactory.removeNamespaceSpaceLimit(ns);
+    assertNotNull("QuotaSettings should not be null", nsSettings);
+    assertTrue("Should be an instance of SpaceLimitSettings", nsSettings instanceof SpaceLimitSettings);
+    SpaceLimitRequest nsProto = ((SpaceLimitSettings) nsSettings).getProto();
+    assertTrue("Request should have a SpaceQuota", nsProto.hasQuota());
+    assertTrue("The remove attribute should be true", nsProto.getQuota().getRemove());
+
+    QuotaSettings tableSettings = QuotaSettingsFactory.removeTableSpaceLimit(tn);
+    assertNotNull("QuotaSettings should not be null", tableSettings);
+    assertTrue("Should be an instance of SpaceLimitSettings", tableSettings instanceof SpaceLimitSettings);
+    SpaceLimitRequest tableProto = ((SpaceLimitSettings) tableSettings).getProto();
+    assertTrue("Request should have a SpaceQuota", tableProto.hasQuota());
+    assertTrue("The remove attribute should be true", tableProto.getQuota().getRemove());
+   }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java
----------------------------------------------------------------------
diff --git a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java
index 117e839..a4c6095 100644
--- a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java
+++ b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java
@@ -4833,6 +4833,23 @@ public final class QuotaProtos {
      * <code>optional .hbase.pb.SpaceViolationPolicy violation_policy = 2;</code>
      */
     org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceViolationPolicy getViolationPolicy();
+
+    /**
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     *
+     * <code>optional bool remove = 3 [default = false];</code>
+     */
+    boolean hasRemove();
+    /**
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     *
+     * <code>optional bool remove = 3 [default = false];</code>
+     */
+    boolean getRemove();
   }
   /**
    * <pre>
@@ -4852,6 +4869,7 @@ public final class QuotaProtos {
     private SpaceQuota() {
       softLimit_ = 0L;
       violationPolicy_ = 1;
+      remove_ = false;
     }
 
     @java.lang.Override
@@ -4898,6 +4916,11 @@ public final class QuotaProtos {
               }
               break;
             }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              remove_ = input.readBool();
+              break;
+            }
           }
         }
       } catch (org.apache.hadoop.hbase.shaded.com.google.protobuf.InvalidProtocolBufferException e) {
@@ -4970,6 +4993,29 @@ public final class QuotaProtos {
       return result == null ? org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceViolationPolicy.DISABLE : result;
     }
 
+    public static final int REMOVE_FIELD_NUMBER = 3;
+    private boolean remove_;
+    /**
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     *
+     * <code>optional bool remove = 3 [default = false];</code>
+     */
+    public boolean hasRemove() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     *
+     * <code>optional bool remove = 3 [default = false];</code>
+     */
+    public boolean getRemove() {
+      return remove_;
+    }
+
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
       byte isInitialized = memoizedIsInitialized;
@@ -4988,6 +5034,9 @@ public final class QuotaProtos {
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         output.writeEnum(2, violationPolicy_);
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBool(3, remove_);
+      }
       unknownFields.writeTo(output);
     }
 
@@ -5004,6 +5053,10 @@ public final class QuotaProtos {
         size += org.apache.hadoop.hbase.shaded.com.google.protobuf.CodedOutputStream
           .computeEnumSize(2, violationPolicy_);
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += org.apache.hadoop.hbase.shaded.com.google.protobuf.CodedOutputStream
+          .computeBoolSize(3, remove_);
+      }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
       return size;
@@ -5030,6 +5083,11 @@ public final class QuotaProtos {
       if (hasViolationPolicy()) {
         result = result && violationPolicy_ == other.violationPolicy_;
       }
+      result = result && (hasRemove() == other.hasRemove());
+      if (hasRemove()) {
+        result = result && (getRemove()
+            == other.getRemove());
+      }
       result = result && unknownFields.equals(other.unknownFields);
       return result;
     }
@@ -5050,6 +5108,11 @@ public final class QuotaProtos {
         hash = (37 * hash) + VIOLATION_POLICY_FIELD_NUMBER;
         hash = (53 * hash) + violationPolicy_;
       }
+      if (hasRemove()) {
+        hash = (37 * hash) + REMOVE_FIELD_NUMBER;
+        hash = (53 * hash) + org.apache.hadoop.hbase.shaded.com.google.protobuf.Internal.hashBoolean(
+            getRemove());
+      }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
@@ -5176,6 +5239,8 @@ public final class QuotaProtos {
         bitField0_ = (bitField0_ & ~0x00000001);
         violationPolicy_ = 1;
         bitField0_ = (bitField0_ & ~0x00000002);
+        remove_ = false;
+        bitField0_ = (bitField0_ & ~0x00000004);
         return this;
       }
 
@@ -5208,6 +5273,10 @@ public final class QuotaProtos {
           to_bitField0_ |= 0x00000002;
         }
         result.violationPolicy_ = violationPolicy_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.remove_ = remove_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -5256,6 +5325,9 @@ public final class QuotaProtos {
         if (other.hasViolationPolicy()) {
           setViolationPolicy(other.getViolationPolicy());
         }
+        if (other.hasRemove()) {
+          setRemove(other.getRemove());
+        }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
         return this;
@@ -5383,6 +5455,54 @@ public final class QuotaProtos {
         onChanged();
         return this;
       }
+
+      private boolean remove_ ;
+      /**
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       *
+       * <code>optional bool remove = 3 [default = false];</code>
+       */
+      public boolean hasRemove() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       *
+       * <code>optional bool remove = 3 [default = false];</code>
+       */
+      public boolean getRemove() {
+        return remove_;
+      }
+      /**
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       *
+       * <code>optional bool remove = 3 [default = false];</code>
+       */
+      public Builder setRemove(boolean value) {
+        bitField0_ |= 0x00000004;
+        remove_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       *
+       * <code>optional bool remove = 3 [default = false];</code>
+       */
+      public Builder clearRemove() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        remove_ = false;
+        onChanged();
+        return this;
+      }
       public final Builder setUnknownFields(
           final org.apache.hadoop.hbase.shaded.com.google.protobuf.UnknownFieldSet unknownFields) {
         return super.setUnknownFields(unknownFields);
@@ -7426,24 +7546,25 @@ public final class QuotaProtos {
       "edQuota\"r\n\006Quotas\022\035\n\016bypass_globals\030\001 \001(" +
       "\010:\005false\022$\n\010throttle\030\002 \001(\0132\022.hbase.pb.Th" +
       "rottle\022#\n\005space\030\003 \001(\0132\024.hbase.pb.SpaceQu" +
-      "ota\"\014\n\nQuotaUsage\"Z\n\nSpaceQuota\022\022\n\nsoft_" +
+      "ota\"\014\n\nQuotaUsage\"q\n\nSpaceQuota\022\022\n\nsoft_" +
       "limit\030\001 \001(\004\0228\n\020violation_policy\030\002 \001(\0162\036." +
-      "hbase.pb.SpaceViolationPolicy\"8\n\021SpaceLi" +
-      "mitRequest\022#\n\005quota\030\001 \001(\0132\024.hbase.pb.Spa",
-      "ceQuota\"X\n\020SpaceQuotaStatus\022.\n\006policy\030\001 " +
-      "\001(\0162\036.hbase.pb.SpaceViolationPolicy\022\024\n\014i" +
-      "n_violation\030\002 \001(\010\"^\n\022SpaceQuotaSnapshot\022" +
-      "*\n\006status\030\001 \001(\0132\032.hbase.pb.SpaceQuotaSta" +
-      "tus\022\r\n\005usage\030\002 \001(\004\022\r\n\005limit\030\003 \001(\004*&\n\nQuo" +
-      "taScope\022\013\n\007CLUSTER\020\001\022\013\n\007MACHINE\020\002*v\n\014Thr" +
-      "ottleType\022\022\n\016REQUEST_NUMBER\020\001\022\020\n\014REQUEST" +
-      "_SIZE\020\002\022\020\n\014WRITE_NUMBER\020\003\022\016\n\nWRITE_SIZE\020" +
-      "\004\022\017\n\013READ_NUMBER\020\005\022\r\n\tREAD_SIZE\020\006*$\n\tQuo" +
-      "taType\022\014\n\010THROTTLE\020\001\022\t\n\005SPACE\020\002*]\n\024Space",
-      "ViolationPolicy\022\013\n\007DISABLE\020\001\022\031\n\025NO_WRITE" +
-      "S_COMPACTIONS\020\002\022\r\n\tNO_WRITES\020\003\022\016\n\nNO_INS" +
-      "ERTS\020\004BH\n1org.apache.hadoop.hbase.shaded" +
-      ".protobuf.generatedB\013QuotaProtosH\001\210\001\001\240\001\001"
+      "hbase.pb.SpaceViolationPolicy\022\025\n\006remove\030" +
+      "\003 \001(\010:\005false\"8\n\021SpaceLimitRequest\022#\n\005quo",
+      "ta\030\001 \001(\0132\024.hbase.pb.SpaceQuota\"X\n\020SpaceQ" +
+      "uotaStatus\022.\n\006policy\030\001 \001(\0162\036.hbase.pb.Sp" +
+      "aceViolationPolicy\022\024\n\014in_violation\030\002 \001(\010" +
+      "\"^\n\022SpaceQuotaSnapshot\022*\n\006status\030\001 \001(\0132\032" +
+      ".hbase.pb.SpaceQuotaStatus\022\r\n\005usage\030\002 \001(" +
+      "\004\022\r\n\005limit\030\003 \001(\004*&\n\nQuotaScope\022\013\n\007CLUSTE" +
+      "R\020\001\022\013\n\007MACHINE\020\002*v\n\014ThrottleType\022\022\n\016REQU" +
+      "EST_NUMBER\020\001\022\020\n\014REQUEST_SIZE\020\002\022\020\n\014WRITE_" +
+      "NUMBER\020\003\022\016\n\nWRITE_SIZE\020\004\022\017\n\013READ_NUMBER\020" +
+      "\005\022\r\n\tREAD_SIZE\020\006*$\n\tQuotaType\022\014\n\010THROTTL",
+      "E\020\001\022\t\n\005SPACE\020\002*]\n\024SpaceViolationPolicy\022\013" +
+      "\n\007DISABLE\020\001\022\031\n\025NO_WRITES_COMPACTIONS\020\002\022\r" +
+      "\n\tNO_WRITES\020\003\022\016\n\nNO_INSERTS\020\004BH\n1org.apa" +
+      "che.hadoop.hbase.shaded.protobuf.generat" +
+      "edB\013QuotaProtosH\001\210\001\001\240\001\001"
     };
     org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
         new org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
@@ -7493,7 +7614,7 @@ public final class QuotaProtos {
     internal_static_hbase_pb_SpaceQuota_fieldAccessorTable = new
       org.apache.hadoop.hbase.shaded.com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_hbase_pb_SpaceQuota_descriptor,
-        new java.lang.String[] { "SoftLimit", "ViolationPolicy", });
+        new java.lang.String[] { "SoftLimit", "ViolationPolicy", "Remove", });
     internal_static_hbase_pb_SpaceLimitRequest_descriptor =
       getDescriptor().getMessageTypes().get(6);
     internal_static_hbase_pb_SpaceLimitRequest_fieldAccessorTable = new

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-protocol-shaded/src/main/protobuf/Quota.proto
----------------------------------------------------------------------
diff --git a/hbase-protocol-shaded/src/main/protobuf/Quota.proto b/hbase-protocol-shaded/src/main/protobuf/Quota.proto
index 5ea1ddb..597b059 100644
--- a/hbase-protocol-shaded/src/main/protobuf/Quota.proto
+++ b/hbase-protocol-shaded/src/main/protobuf/Quota.proto
@@ -89,6 +89,7 @@ enum SpaceViolationPolicy {
 message SpaceQuota {
   optional uint64 soft_limit = 1; // The limit of bytes for this quota
   optional SpaceViolationPolicy violation_policy = 2; // The action to take when the quota is violated
+  optional bool remove = 3 [default = false]; // When true, remove the quota.
 }
 
 // The Request to limit space usage (to allow for schema evolution not tied to SpaceQuota).

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java
----------------------------------------------------------------------
diff --git a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java
index d466e59..3f65424 100644
--- a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java
+++ b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java
@@ -4658,6 +4658,24 @@ public final class QuotaProtos {
      * </pre>
      */
     org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceViolationPolicy getViolationPolicy();
+
+    // optional bool remove = 3 [default = false];
+    /**
+     * <code>optional bool remove = 3 [default = false];</code>
+     *
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     */
+    boolean hasRemove();
+    /**
+     * <code>optional bool remove = 3 [default = false];</code>
+     *
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     */
+    boolean getRemove();
   }
   /**
    * Protobuf type {@code hbase.pb.SpaceQuota}
@@ -4730,6 +4748,11 @@ public final class QuotaProtos {
               }
               break;
             }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              remove_ = input.readBool();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -4818,9 +4841,34 @@ public final class QuotaProtos {
       return violationPolicy_;
     }
 
+    // optional bool remove = 3 [default = false];
+    public static final int REMOVE_FIELD_NUMBER = 3;
+    private boolean remove_;
+    /**
+     * <code>optional bool remove = 3 [default = false];</code>
+     *
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     */
+    public boolean hasRemove() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional bool remove = 3 [default = false];</code>
+     *
+     * <pre>
+     * When true, remove the quota.
+     * </pre>
+     */
+    public boolean getRemove() {
+      return remove_;
+    }
+
     private void initFields() {
       softLimit_ = 0L;
       violationPolicy_ = org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceViolationPolicy.DISABLE;
+      remove_ = false;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -4840,6 +4888,9 @@ public final class QuotaProtos {
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         output.writeEnum(2, violationPolicy_.getNumber());
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBool(3, remove_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -4857,6 +4908,10 @@ public final class QuotaProtos {
         size += com.google.protobuf.CodedOutputStream
           .computeEnumSize(2, violationPolicy_.getNumber());
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(3, remove_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -4890,6 +4945,11 @@ public final class QuotaProtos {
         result = result &&
             (getViolationPolicy() == other.getViolationPolicy());
       }
+      result = result && (hasRemove() == other.hasRemove());
+      if (hasRemove()) {
+        result = result && (getRemove()
+            == other.getRemove());
+      }
       result = result &&
           getUnknownFields().equals(other.getUnknownFields());
       return result;
@@ -4911,6 +4971,10 @@ public final class QuotaProtos {
         hash = (37 * hash) + VIOLATION_POLICY_FIELD_NUMBER;
         hash = (53 * hash) + hashEnum(getViolationPolicy());
       }
+      if (hasRemove()) {
+        hash = (37 * hash) + REMOVE_FIELD_NUMBER;
+        hash = (53 * hash) + hashBoolean(getRemove());
+      }
       hash = (29 * hash) + getUnknownFields().hashCode();
       memoizedHashCode = hash;
       return hash;
@@ -5028,6 +5092,8 @@ public final class QuotaProtos {
         bitField0_ = (bitField0_ & ~0x00000001);
         violationPolicy_ = org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceViolationPolicy.DISABLE;
         bitField0_ = (bitField0_ & ~0x00000002);
+        remove_ = false;
+        bitField0_ = (bitField0_ & ~0x00000004);
         return this;
       }
 
@@ -5064,6 +5130,10 @@ public final class QuotaProtos {
           to_bitField0_ |= 0x00000002;
         }
         result.violationPolicy_ = violationPolicy_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.remove_ = remove_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -5086,6 +5156,9 @@ public final class QuotaProtos {
         if (other.hasViolationPolicy()) {
           setViolationPolicy(other.getViolationPolicy());
         }
+        if (other.hasRemove()) {
+          setRemove(other.getRemove());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -5214,6 +5287,55 @@ public final class QuotaProtos {
         return this;
       }
 
+      // optional bool remove = 3 [default = false];
+      private boolean remove_ ;
+      /**
+       * <code>optional bool remove = 3 [default = false];</code>
+       *
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       */
+      public boolean hasRemove() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional bool remove = 3 [default = false];</code>
+       *
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       */
+      public boolean getRemove() {
+        return remove_;
+      }
+      /**
+       * <code>optional bool remove = 3 [default = false];</code>
+       *
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       */
+      public Builder setRemove(boolean value) {
+        bitField0_ |= 0x00000004;
+        remove_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool remove = 3 [default = false];</code>
+       *
+       * <pre>
+       * When true, remove the quota.
+       * </pre>
+       */
+      public Builder clearRemove() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        remove_ = false;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:hbase.pb.SpaceQuota)
     }
 
@@ -7126,24 +7248,25 @@ public final class QuotaProtos {
       "edQuota\"r\n\006Quotas\022\035\n\016bypass_globals\030\001 \001(" +
       "\010:\005false\022$\n\010throttle\030\002 \001(\0132\022.hbase.pb.Th" +
       "rottle\022#\n\005space\030\003 \001(\0132\024.hbase.pb.SpaceQu" +
-      "ota\"\014\n\nQuotaUsage\"Z\n\nSpaceQuota\022\022\n\nsoft_" +
+      "ota\"\014\n\nQuotaUsage\"q\n\nSpaceQuota\022\022\n\nsoft_" +
       "limit\030\001 \001(\004\0228\n\020violation_policy\030\002 \001(\0162\036." +
-      "hbase.pb.SpaceViolationPolicy\"8\n\021SpaceLi" +
-      "mitRequest\022#\n\005quota\030\001 \001(\0132\024.hbase.pb.Spa",
-      "ceQuota\"X\n\020SpaceQuotaStatus\022.\n\006policy\030\001 " +
-      "\001(\0162\036.hbase.pb.SpaceViolationPolicy\022\024\n\014i" +
-      "n_violation\030\002 \001(\010\"^\n\022SpaceQuotaSnapshot\022" +
-      "*\n\006status\030\001 \001(\0132\032.hbase.pb.SpaceQuotaSta" +
-      "tus\022\r\n\005usage\030\002 \001(\004\022\r\n\005limit\030\003 \001(\004*&\n\nQuo" +
-      "taScope\022\013\n\007CLUSTER\020\001\022\013\n\007MACHINE\020\002*v\n\014Thr" +
-      "ottleType\022\022\n\016REQUEST_NUMBER\020\001\022\020\n\014REQUEST" +
-      "_SIZE\020\002\022\020\n\014WRITE_NUMBER\020\003\022\016\n\nWRITE_SIZE\020" +
-      "\004\022\017\n\013READ_NUMBER\020\005\022\r\n\tREAD_SIZE\020\006*$\n\tQuo" +
-      "taType\022\014\n\010THROTTLE\020\001\022\t\n\005SPACE\020\002*]\n\024Space",
-      "ViolationPolicy\022\013\n\007DISABLE\020\001\022\031\n\025NO_WRITE" +
-      "S_COMPACTIONS\020\002\022\r\n\tNO_WRITES\020\003\022\016\n\nNO_INS" +
-      "ERTS\020\004BA\n*org.apache.hadoop.hbase.protob" +
-      "uf.generatedB\013QuotaProtosH\001\210\001\001\240\001\001"
+      "hbase.pb.SpaceViolationPolicy\022\025\n\006remove\030" +
+      "\003 \001(\010:\005false\"8\n\021SpaceLimitRequest\022#\n\005quo",
+      "ta\030\001 \001(\0132\024.hbase.pb.SpaceQuota\"X\n\020SpaceQ" +
+      "uotaStatus\022.\n\006policy\030\001 \001(\0162\036.hbase.pb.Sp" +
+      "aceViolationPolicy\022\024\n\014in_violation\030\002 \001(\010" +
+      "\"^\n\022SpaceQuotaSnapshot\022*\n\006status\030\001 \001(\0132\032" +
+      ".hbase.pb.SpaceQuotaStatus\022\r\n\005usage\030\002 \001(" +
+      "\004\022\r\n\005limit\030\003 \001(\004*&\n\nQuotaScope\022\013\n\007CLUSTE" +
+      "R\020\001\022\013\n\007MACHINE\020\002*v\n\014ThrottleType\022\022\n\016REQU" +
+      "EST_NUMBER\020\001\022\020\n\014REQUEST_SIZE\020\002\022\020\n\014WRITE_" +
+      "NUMBER\020\003\022\016\n\nWRITE_SIZE\020\004\022\017\n\013READ_NUMBER\020" +
+      "\005\022\r\n\tREAD_SIZE\020\006*$\n\tQuotaType\022\014\n\010THROTTL",
+      "E\020\001\022\t\n\005SPACE\020\002*]\n\024SpaceViolationPolicy\022\013" +
+      "\n\007DISABLE\020\001\022\031\n\025NO_WRITES_COMPACTIONS\020\002\022\r" +
+      "\n\tNO_WRITES\020\003\022\016\n\nNO_INSERTS\020\004BA\n*org.apa" +
+      "che.hadoop.hbase.protobuf.generatedB\013Quo" +
+      "taProtosH\001\210\001\001\240\001\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -7185,7 +7308,7 @@ public final class QuotaProtos {
           internal_static_hbase_pb_SpaceQuota_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_hbase_pb_SpaceQuota_descriptor,
-              new java.lang.String[] { "SoftLimit", "ViolationPolicy", });
+              new java.lang.String[] { "SoftLimit", "ViolationPolicy", "Remove", });
           internal_static_hbase_pb_SpaceLimitRequest_descriptor =
             getDescriptor().getMessageTypes().get(6);
           internal_static_hbase_pb_SpaceLimitRequest_fieldAccessorTable = new

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-protocol/src/main/protobuf/Quota.proto
----------------------------------------------------------------------
diff --git a/hbase-protocol/src/main/protobuf/Quota.proto b/hbase-protocol/src/main/protobuf/Quota.proto
index 02d825b..d55918a 100644
--- a/hbase-protocol/src/main/protobuf/Quota.proto
+++ b/hbase-protocol/src/main/protobuf/Quota.proto
@@ -89,6 +89,7 @@ enum SpaceViolationPolicy {
 message SpaceQuota {
   optional uint64 soft_limit = 1; // The limit of bytes for this quota
   optional SpaceViolationPolicy violation_policy = 2; // The action to take when the quota is violated
+  optional bool remove = 3 [default = false]; // When true, remove the quota.
 }
 
 // The Request to limit space usage (to allow for schema evolution not tied to SpaceQuota).

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java
index 206d81d..a5832f9 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java
@@ -454,7 +454,14 @@ public class MasterQuotaManager implements RegionStateListener {
    */
   void applySpaceLimit(final Quotas.Builder quotas, final SpaceLimitRequest req) {
     if (req.hasQuota()) {
-      applySpaceQuota(quotas, req.getQuota());
+      SpaceQuota spaceQuota = req.getQuota();
+      // If we have the remove flag, unset the space quota.
+      if (spaceQuota.getRemove()) {
+        quotas.setSpace(SpaceQuota.getDefaultInstance());
+      } else {
+        // Otherwise, update the new quota
+        applySpaceQuota(quotas, req.getQuota());
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c9082fe/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java
index be93c2f..52921af 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java
@@ -47,6 +47,7 @@ import org.junit.experimental.categories.Category;
 import com.google.common.collect.Iterables;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -246,7 +247,7 @@ public class TestQuotaAdmin {
   }
 
   @Test
-  public void testSetAndGetSpaceQuota() throws Exception {
+  public void testSetGetRemoveSpaceQuota() throws Exception {
     Admin admin = TEST_UTIL.getAdmin();
     final TableName tn = TableName.valueOf("table1");
     final long sizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB
@@ -274,10 +275,32 @@ public class TestQuotaAdmin {
     } finally {
       scanner.close();
     }
+
+    // Now, remove the quota
+    QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn);
+    admin.setQuota(removeQuota);
+
+    // Verify that the record doesn't exist in the table
+    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
+      ResultScanner rs = quotaTable.getScanner(new Scan());
+      try {
+        assertNull("Did not expect to find a quota entry", rs.next());
+      } finally {
+        rs.close();
+      }
+    }
+
+    // Verify that we can also not fetch it via the API
+    scanner = QuotaRetriever.open(admin.getConfiguration());
+    try {
+      assertNull("Did not expect to find a quota entry", scanner.next());
+    } finally {
+      scanner.close();
+    }
   }
 
   @Test
-  public void testSetAndModifyQuota() throws Exception {
+  public void testSetModifyRemoveQuota() throws Exception {
     Admin admin = TEST_UTIL.getAdmin();
     final TableName tn = TableName.valueOf("table1");
     final long originalSizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB
@@ -334,6 +357,28 @@ public class TestQuotaAdmin {
     } finally {
       quotaScanner.close();
     }
+
+    // Now, remove the quota
+    QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn);
+    admin.setQuota(removeQuota);
+
+    // Verify that the record doesn't exist in the table
+    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
+      ResultScanner scanner = quotaTable.getScanner(new Scan());
+      try {
+        assertNull("Did not expect to find a quota entry", scanner.next());
+      } finally {
+        scanner.close();
+      }
+    }
+
+    // Verify that we can also not fetch it via the API
+    quotaScanner = QuotaRetriever.open(admin.getConfiguration());
+    try {
+      assertNull("Did not expect to find a quota entry", quotaScanner.next());
+    } finally {
+      quotaScanner.close();
+    }
   }
 
   private void assertNumResults(int expected, final QuotaFilter filter) throws Exception {