HBASE-16995 Build client Java API and client protobuf messages (Josh Elser)

This commit is contained in:
tedyu 2016-11-17 10:19:52 -08:00 committed by Josh Elser
parent 56cbc68b0d
commit 4dfafd6e50
13 changed files with 4531 additions and 574 deletions

View File

@ -27,6 +27,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRe
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceQuota;
@InterfaceAudience.Public
public class QuotaSettingsFactory {
@ -89,6 +90,9 @@ public class QuotaSettingsFactory {
if (quotas.getBypassGlobals() == true) {
settings.add(new QuotaGlobalsSettingsBypass(userName, tableName, namespace, true));
}
if (quotas.hasSpace()) {
settings.add(fromSpace(tableName, namespace, quotas.getSpace()));
}
return settings;
}
@ -122,6 +126,18 @@ public class QuotaSettingsFactory {
return settings;
}
static QuotaSettings fromSpace(TableName table, String namespace, SpaceQuota protoQuota) {
if ((null == table && null == namespace) || (null != table && null != namespace)) {
throw new IllegalArgumentException("Can only construct SpaceLimitSettings for a table or namespace.");
}
if (null != table) {
return SpaceLimitSettings.fromSpaceQuota(table, protoQuota);
} else {
// namespace must be non-null
return SpaceLimitSettings.fromSpaceQuota(namespace, protoQuota);
}
}
/* ==========================================================================
* RPC Throttle
*/
@ -278,4 +294,35 @@ public class QuotaSettingsFactory {
public static QuotaSettings bypassGlobals(final String userName, final boolean bypassGlobals) {
return new QuotaGlobalsSettingsBypass(userName, null, null, bypassGlobals);
}
/* ==========================================================================
* FileSystem Space Settings
*/
/**
* Creates a {@link QuotaSettings} object to limit the FileSystem space usage for the given table to the given size in bytes.
* When the space usage is exceeded by the table, the provided {@link SpaceViolationPolicy} is enacted on the table.
*
* @param tableName The name of the table on which the quota should be applied.
* @param sizeLimit The limit of a table's size in bytes.
* @param violationPolicy The action to take when the quota is exceeded.
* @return An {@link QuotaSettings} object.
*/
public static QuotaSettings limitTableSpace(final TableName tableName, long sizeLimit, final SpaceViolationPolicy violationPolicy) {
return new SpaceLimitSettings(tableName, sizeLimit, violationPolicy);
}
/**
* 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.
*
* @param namespace The namespace on which the quota should be applied.
* @param sizeLimit The limit of the namespace's size in bytes.
* @param violationPolicy The action to take when the the quota is exceeded.
* @return An {@link QuotaSettings} object.
*/
public static QuotaSettings limitNamespaceSpace(final String namespace, long sizeLimit, final SpaceViolationPolicy violationPolicy) {
return new SpaceLimitSettings(namespace, sizeLimit, violationPolicy);
}
}

View File

@ -26,4 +26,5 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience;
public enum QuotaType {
THROTTLE,
GLOBAL_BYPASS,
SPACE,
}

View File

@ -0,0 +1,166 @@
/*
* 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.hadoop.hbase.quotas;
import java.util.Objects;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest.Builder;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceLimitRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceQuota;
/**
* A {@link QuotaSettings} implementation for implementing filesystem-use quotas.
*/
@InterfaceAudience.Private
@InterfaceStability.Evolving
class SpaceLimitSettings extends QuotaSettings {
private final SpaceLimitRequest proto;
SpaceLimitSettings(TableName tableName, long sizeLimit, SpaceViolationPolicy violationPolicy) {
super(null, Objects.requireNonNull(tableName), null);
if (0L > sizeLimit) {
throw new IllegalArgumentException("Size limit must be a non-negative value.");
}
proto = buildProtoQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
}
SpaceLimitSettings(String namespace, long sizeLimit, SpaceViolationPolicy violationPolicy) {
super(null, null, Objects.requireNonNull(namespace));
if (0L > sizeLimit) {
throw new IllegalArgumentException("Size limit must be a non-negative value.");
}
proto = buildProtoQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
}
/**
* Builds a {@link SpaceQuota} protobuf object given the arguments.
*
* @param sizeLimit The size limit of the quota.
* @param violationPolicy The action to take when the quota is exceeded.
* @return The protobuf SpaceQuota representation.
*/
private SpaceLimitRequest buildProtoQuota(long sizeLimit, SpaceViolationPolicy violationPolicy) {
return SpaceLimitRequest.newBuilder().setQuota(
SpaceQuota.newBuilder()
.setSoftLimit(sizeLimit)
.setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(violationPolicy))
.build())
.build();
}
/**
* Returns a copy of the internal state of <code>this</code>
*/
SpaceLimitRequest getProto() {
return proto.toBuilder().build();
}
@Override
public QuotaType getQuotaType() {
return QuotaType.SPACE;
}
@Override
protected void setupSetQuotaRequest(Builder builder) {
// TableName/Namespace are serialized in QuotaSettings
builder.setSpaceLimit(proto);
}
/**
* Constructs a {@link SpaceLimitSettings} from the provided protobuf message and tablename.
*
* @param tableName The target tablename for the limit.
* @param proto The protobuf representation.
* @return A QuotaSettings.
*/
static SpaceLimitSettings fromSpaceQuota(final TableName tableName,
final QuotaProtos.SpaceQuota proto) {
validateProtoArguments(proto);
return new SpaceLimitSettings(tableName, proto.getSoftLimit(),
ProtobufUtil.toViolationPolicy(proto.getViolationPolicy()));
}
/**
* Constructs a {@link SpaceLimitSettings} from the provided protobuf message and namespace.
*
* @param namespace The target namespace for the limit.
* @param proto The protobuf representation.
* @return A QuotaSettings.
*/
static SpaceLimitSettings fromSpaceQuota(final String namespace,
final QuotaProtos.SpaceQuota proto) {
validateProtoArguments(proto);
return new SpaceLimitSettings(namespace, proto.getSoftLimit(),
ProtobufUtil.toViolationPolicy(proto.getViolationPolicy()));
}
/**
* Validates that the provided protobuf SpaceQuota has the necessary information to construct
* a {@link SpaceLimitSettings}.
*
* @param proto The protobuf message to validate.
*/
static void validateProtoArguments(final QuotaProtos.SpaceQuota proto) {
if (!Objects.requireNonNull(proto).hasSoftLimit()) {
throw new IllegalArgumentException("Cannot handle SpaceQuota without a soft limit");
}
if (!proto.hasViolationPolicy()) {
throw new IllegalArgumentException("Cannot handle SpaceQuota without a violation policy");
}
}
@Override
public int hashCode() {
return Objects.hash(getTableName(), getNamespace(), proto);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof SpaceLimitSettings)) {
return false;
}
// o is non-null and an instance of SpaceLimitSettings
SpaceLimitSettings other = (SpaceLimitSettings) o;
return Objects.equals(getTableName(), other.getTableName()) &&
Objects.equals(getNamespace(), other.getNamespace()) &&
Objects.equals(proto, other.proto);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("TYPE => SPACE");
if (null != getTableName()) {
sb.append(", TABLE => ").append(getTableName());
}
if (null != getNamespace()) {
sb.append(", NAMESPACE => ").append(getNamespace());
}
sb.append(", LIMIT => ").append(proto.getQuota().getSoftLimit());
sb.append(", VIOLATION_POLICY => ").append(proto.getQuota().getViolationPolicy());
return sb.toString();
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.hadoop.hbase.quotas;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
/**
* Enumeration that represents the action HBase will take when a space quota is violated.
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public enum SpaceViolationPolicy {
/**
* Disables the table(s).
*/
DISABLE,
/**
* Disallows any mutations or compactions on the table(s).
*/
NO_WRITES_COMPACTIONS,
/**
* Disallows any mutations (but allows compactions) on the table(s).
*/
NO_WRITES,
/**
* Disallows any updates (but allows deletes and compactions) on the table(s).
*/
NO_INSERTS,
}

View File

@ -91,6 +91,7 @@ import org.apache.hadoop.hbase.procedure2.LockInfo;
import org.apache.hadoop.hbase.protobuf.ProtobufMagic;
import org.apache.hadoop.hbase.quotas.QuotaScope;
import org.apache.hadoop.hbase.quotas.QuotaType;
import org.apache.hadoop.hbase.quotas.SpaceViolationPolicy;
import org.apache.hadoop.hbase.quotas.ThrottleType;
import org.apache.hadoop.hbase.replication.ReplicationLoadSink;
import org.apache.hadoop.hbase.replication.ReplicationLoadSource;
@ -2561,6 +2562,7 @@ public final class ProtobufUtil {
public static QuotaType toQuotaScope(final QuotaProtos.QuotaType proto) {
switch (proto) {
case THROTTLE: return QuotaType.THROTTLE;
case SPACE: return QuotaType.SPACE;
}
throw new RuntimeException("Invalid QuotaType " + proto);
}
@ -2574,10 +2576,44 @@ public final class ProtobufUtil {
public static QuotaProtos.QuotaType toProtoQuotaScope(final QuotaType type) {
switch (type) {
case THROTTLE: return QuotaProtos.QuotaType.THROTTLE;
case SPACE: return QuotaProtos.QuotaType.SPACE;
}
throw new RuntimeException("Invalid QuotaType " + type);
}
/**
* Converts a protocol buffer SpaceViolationPolicy to a client SpaceViolationPolicy.
*
* @param proto The protocol buffer space violation policy.
* @return The corresponding client SpaceViolationPolicy.
*/
public static SpaceViolationPolicy toViolationPolicy(final QuotaProtos.SpaceViolationPolicy proto) {
switch (proto) {
case DISABLE: return SpaceViolationPolicy.DISABLE;
case NO_WRITES_COMPACTIONS: return SpaceViolationPolicy.NO_WRITES_COMPACTIONS;
case NO_WRITES: return SpaceViolationPolicy.NO_WRITES;
case NO_INSERTS: return SpaceViolationPolicy.NO_INSERTS;
}
throw new RuntimeException("Invalid SpaceViolationPolicy " + proto);
}
/**
* Converts a client SpaceViolationPolicy to a protocol buffer SpaceViolationPolicy.
*
* @param policy The client SpaceViolationPolicy object.
* @return The corresponding protocol buffer SpaceViolationPolicy.
*/
public static QuotaProtos.SpaceViolationPolicy toProtoViolationPolicy(
final SpaceViolationPolicy policy) {
switch (policy) {
case DISABLE: return QuotaProtos.SpaceViolationPolicy.DISABLE;
case NO_WRITES_COMPACTIONS: return QuotaProtos.SpaceViolationPolicy.NO_WRITES_COMPACTIONS;
case NO_WRITES: return QuotaProtos.SpaceViolationPolicy.NO_WRITES;
case NO_INSERTS: return QuotaProtos.SpaceViolationPolicy.NO_INSERTS;
}
throw new RuntimeException("Invalid SpaceViolationPolicy " + policy);
}
/**
* Build a protocol buffer TimedQuota
*
@ -2595,6 +2631,21 @@ public final class ProtobufUtil {
.build();
}
/**
* Builds a protocol buffer SpaceQuota.
*
* @param limit The maximum space usage for the quota in bytes.
* @param violationPolicy The policy to apply when the quota is violated.
* @return The protocol buffer SpaceQuota.
*/
public static QuotaProtos.SpaceQuota toProtoSpaceQuota(final long limit,
final SpaceViolationPolicy violationPolicy) {
return QuotaProtos.SpaceQuota.newBuilder()
.setSoftLimit(limit)
.setViolationPolicy(toProtoViolationPolicy(violationPolicy))
.build();
}
/**
* Generates a marker for the WAL so that we propagate the notion of a bulk region load
* throughout the WAL.

View File

@ -0,0 +1,148 @@
/*
* 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.hadoop.hbase.quotas;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceLimitRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceQuota;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Throttle;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.TimedQuota;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.junit.Test;
import org.junit.experimental.categories.Category;
/**
* Test class for {@link QuotaSettingsFactory}.
*/
@Category(SmallTests.class)
public class TestQuotaSettingsFactory {
@Test
public void testAllQuotasAddedToList() {
final SpaceQuota spaceQuota = SpaceQuota.newBuilder()
.setSoftLimit(1024L * 1024L * 1024L * 50L) // 50G
.setViolationPolicy(QuotaProtos.SpaceViolationPolicy.DISABLE) // Disable the table
.build();
final long readLimit = 1000;
final long writeLimit = 500;
final Throttle throttle = Throttle.newBuilder()
// 1000 read reqs/min
.setReadNum(TimedQuota.newBuilder().setSoftLimit(readLimit).setTimeUnit(HBaseProtos.TimeUnit.MINUTES).build())
// 500 write reqs/min
.setWriteNum(TimedQuota.newBuilder().setSoftLimit(writeLimit).setTimeUnit(HBaseProtos.TimeUnit.MINUTES).build())
.build();
final Quotas quotas = Quotas.newBuilder()
.setSpace(spaceQuota) // Set the FS quotas
.setThrottle(throttle) // Set some RPC limits
.build();
final TableName tn = TableName.valueOf("my_table");
List<QuotaSettings> settings = QuotaSettingsFactory.fromTableQuotas(tn, quotas);
assertEquals(3, settings.size());
boolean seenRead = false;
boolean seenWrite = false;
boolean seenSpace = false;
for (QuotaSettings setting : settings) {
if (setting instanceof ThrottleSettings) {
ThrottleSettings throttleSettings = (ThrottleSettings) setting;
switch (throttleSettings.getThrottleType()) {
case READ_NUMBER:
assertFalse("Should not have multiple read quotas", seenRead);
assertEquals(readLimit, throttleSettings.getSoftLimit());
assertEquals(TimeUnit.MINUTES, throttleSettings.getTimeUnit());
assertEquals(tn, throttleSettings.getTableName());
assertNull("Username should be null", throttleSettings.getUserName());
assertNull("Namespace should be null", throttleSettings.getNamespace());
seenRead = true;
break;
case WRITE_NUMBER:
assertFalse("Should not have multiple write quotas", seenWrite);
assertEquals(writeLimit, throttleSettings.getSoftLimit());
assertEquals(TimeUnit.MINUTES, throttleSettings.getTimeUnit());
assertEquals(tn, throttleSettings.getTableName());
assertNull("Username should be null", throttleSettings.getUserName());
assertNull("Namespace should be null", throttleSettings.getNamespace());
seenWrite = true;
break;
default:
fail("Unexpected throttle type: " + throttleSettings.getThrottleType());
}
} else if (setting instanceof SpaceLimitSettings) {
assertFalse("Should not have multiple space quotas", seenSpace);
SpaceLimitSettings spaceLimit = (SpaceLimitSettings) setting;
assertEquals(tn, spaceLimit.getTableName());
assertNull("Username should be null", spaceLimit.getUserName());
assertNull("Namespace should be null", spaceLimit.getNamespace());
assertTrue("SpaceLimitSettings should have a SpaceQuota", spaceLimit.getProto().hasQuota());
assertEquals(spaceQuota, spaceLimit.getProto().getQuota());
seenSpace = true;
} else {
fail("Unexpected QuotaSettings implementation: " + setting.getClass());
}
}
assertTrue("Should have seen a read quota", seenRead);
assertTrue("Should have seen a write quota", seenWrite);
assertTrue("Should have seen a space quota", seenSpace);
}
@Test(expected = IllegalArgumentException.class)
public void testNeitherTableNorNamespace() {
final SpaceQuota spaceQuota = SpaceQuota.newBuilder()
.setSoftLimit(1L)
.setViolationPolicy(QuotaProtos.SpaceViolationPolicy.DISABLE)
.build();
QuotaSettingsFactory.fromSpace(null, null, spaceQuota);
}
@Test(expected = IllegalArgumentException.class)
public void testBothTableAndNamespace() {
final SpaceQuota spaceQuota = SpaceQuota.newBuilder()
.setSoftLimit(1L)
.setViolationPolicy(QuotaProtos.SpaceViolationPolicy.DISABLE)
.build();
QuotaSettingsFactory.fromSpace(TableName.valueOf("foo"), "bar", spaceQuota);
}
@Test
public void testSpaceLimitSettings() {
final TableName tableName = TableName.valueOf("foo");
final long sizeLimit = 1024L * 1024L * 1024L * 75; // 75GB
final SpaceViolationPolicy violationPolicy = SpaceViolationPolicy.NO_INSERTS;
QuotaSettings settings = QuotaSettingsFactory.limitTableSpace(tableName, sizeLimit, violationPolicy);
assertNotNull("QuotaSettings should not be null", settings);
assertTrue("Should be an instance of SpaceLimitSettings", settings instanceof SpaceLimitSettings);
SpaceLimitSettings spaceLimitSettings = (SpaceLimitSettings) settings;
SpaceLimitRequest protoRequest = spaceLimitSettings.getProto();
assertTrue("Request should have a SpaceQuota", protoRequest.hasQuota());
SpaceQuota quota = protoRequest.getQuota();
assertEquals(sizeLimit, quota.getSoftLimit());
assertEquals(violationPolicy, ProtobufUtil.toViolationPolicy(quota.getViolationPolicy()));
}
}

View File

@ -0,0 +1,119 @@
/*
* 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.hadoop.hbase.quotas;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceLimitRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceQuota;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.junit.Test;
import org.junit.experimental.categories.Category;
/**
* Test class for {@link SpaceLimitSettings}.
*/
@Category({SmallTests.class})
public class TestSpaceLimitSettings {
@Test(expected = IllegalArgumentException.class)
public void testInvalidTableQuotaSizeLimit() {
new SpaceLimitSettings(TableName.valueOf("foo"), -1, SpaceViolationPolicy.NO_INSERTS);
}
@Test(expected = NullPointerException.class)
public void testNullTableName() {
TableName tn = null;
new SpaceLimitSettings(tn, 1, SpaceViolationPolicy.NO_INSERTS);
}
@Test(expected = NullPointerException.class)
public void testNullTableViolationPolicy() {
new SpaceLimitSettings(TableName.valueOf("foo"), 1, null);
}
@Test(expected = IllegalArgumentException.class)
public void testInvalidNamespaceQuotaSizeLimit() {
new SpaceLimitSettings("foo_ns", -1, SpaceViolationPolicy.NO_INSERTS);
}
@Test(expected = NullPointerException.class)
public void testNullNamespace() {
String ns = null;
new SpaceLimitSettings(ns, 1, SpaceViolationPolicy.NO_INSERTS);
}
@Test(expected = NullPointerException.class)
public void testNullNamespaceViolationPolicy() {
new SpaceLimitSettings("foo_ns", 1, null);
}
@Test
public void testTableQuota() {
final TableName tableName = TableName.valueOf("foo");
final long sizeLimit = 1024 * 1024;
final SpaceViolationPolicy policy = SpaceViolationPolicy.NO_WRITES;
SpaceLimitSettings settings = new SpaceLimitSettings(tableName, sizeLimit, policy);
SetQuotaRequest proto = QuotaSettings.buildSetQuotaRequestProto(settings);
assertFalse("User should be missing", proto.hasUserName());
assertFalse("Namespace should be missing", proto.hasNamespace());
assertEquals(ProtobufUtil.toProtoTableName(tableName), proto.getTableName());
SpaceLimitRequest spaceLimitReq = proto.getSpaceLimit();
assertNotNull("SpaceLimitRequest was null", spaceLimitReq);
SpaceQuota spaceQuota = spaceLimitReq.getQuota();
assertNotNull("SpaceQuota was null", spaceQuota);
assertEquals(sizeLimit, spaceQuota.getSoftLimit());
assertEquals(ProtobufUtil.toProtoViolationPolicy(policy), spaceQuota.getViolationPolicy());
assertEquals(QuotaType.SPACE, settings.getQuotaType());
SpaceLimitSettings copy = new SpaceLimitSettings(tableName, sizeLimit, policy);
assertEquals(settings, copy);
assertEquals(settings.hashCode(), copy.hashCode());
}
@Test
public void testNamespaceQuota() {
final String namespace = "foo_ns";
final long sizeLimit = 1024 * 1024;
final SpaceViolationPolicy policy = SpaceViolationPolicy.NO_WRITES;
SpaceLimitSettings settings = new SpaceLimitSettings(namespace, sizeLimit, policy);
SetQuotaRequest proto = QuotaSettings.buildSetQuotaRequestProto(settings);
assertFalse("User should be missing", proto.hasUserName());
assertFalse("TableName should be missing", proto.hasTableName());
assertEquals(namespace, proto.getNamespace());
SpaceLimitRequest spaceLimitReq = proto.getSpaceLimit();
assertNotNull("SpaceLimitRequest was null", spaceLimitReq);
SpaceQuota spaceQuota = spaceLimitReq.getQuota();
assertNotNull("SpaceQuota was null", spaceQuota);
assertEquals(sizeLimit, spaceQuota.getSoftLimit());
assertEquals(ProtobufUtil.toProtoViolationPolicy(policy), spaceQuota.getViolationPolicy());
assertEquals(QuotaType.SPACE, settings.getQuotaType());
SpaceLimitSettings copy = new SpaceLimitSettings(namespace, sizeLimit, policy);
assertEquals(settings, copy);
assertEquals(settings.hashCode(), copy.hashCode());
}
}

View File

@ -553,6 +553,8 @@ message SetQuotaRequest {
optional bool remove_all = 5;
optional bool bypass_globals = 6;
optional ThrottleRequest throttle = 7;
optional SpaceLimitRequest space_limit = 8;
}
message SetQuotaResponse {

View File

@ -65,12 +65,33 @@ message ThrottleRequest {
enum QuotaType {
THROTTLE = 1;
SPACE = 2;
}
message Quotas {
optional bool bypass_globals = 1 [default = false];
optional Throttle throttle = 2;
optional SpaceQuota space = 3;
}
message QuotaUsage {
}
// Defines what action should be taken when the SpaceQuota is violated
enum SpaceViolationPolicy {
DISABLE = 1; // Disable the table(s)
NO_WRITES_COMPACTIONS = 2; // No writes, bulk-loads, or compactions
NO_WRITES = 3; // No writes or bulk-loads
NO_INSERTS = 4; // No puts or bulk-loads, but deletes are allowed
}
// Defines a limit on the amount of filesystem space used by a table/namespace
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
}
// The Request to limit space usage (to allow for schema evolution not tied to SpaceQuota).
message SpaceLimitRequest {
optional SpaceQuota quota = 1;
}

View File

@ -65,12 +65,33 @@ message ThrottleRequest {
enum QuotaType {
THROTTLE = 1;
SPACE = 2;
}
message Quotas {
optional bool bypass_globals = 1 [default = false];
optional Throttle throttle = 2;
optional SpaceQuota space = 3;
}
message QuotaUsage {
}
// Defines what action should be taken when the SpaceQuota is violated
enum SpaceViolationPolicy {
DISABLE = 1; // Disable the table(s)
NO_WRITES_COMPACTIONS = 2; // No writes, bulk-loads, or compactions
NO_WRITES = 3; // No writes or bulk-loads
NO_INSERTS = 4; // No puts or bulk-loads, but deletes are allowed
}
// Defines a limit on the amount of filesystem space used by a table/namespace
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
}
// The Request to limit space usage (to allow for schema evolution not tied to SpaceQuota).
message SpaceLimitRequest {
optional SpaceQuota quota = 1;
}