HDFS-8614. OzoneHandler : Add Quota Support. (Contributed by Anu Engineer)
This commit is contained in:
parent
d41245ca56
commit
0a90e6d45c
@ -7,3 +7,6 @@
|
||||
HDFS-8456. Ozone: Introduce STORAGE_CONTAINER_SERVICE as a new NodeType.
|
||||
(Arpit Agarwal)
|
||||
|
||||
HDFS-8641. OzoneHandler : Add Quota Support. (Anu Engineer via
|
||||
Arpit Agarwal)
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.ozone.web.headers;
|
||||
|
||||
/**
|
||||
* OZONE specific HTTP headers.
|
||||
*/
|
||||
public final class Header {
|
||||
public static final String OZONE_QUOTA_BYTES = "BYTES";
|
||||
public static final String OZONE_QUOTA_MB = "MB";
|
||||
public static final String OZONE_QUOTA_GB = "GB";
|
||||
public static final String OZONE_QUOTA_TB = "TB";
|
||||
public static final String OZONE_QUOTA_REMOVE = "remove";
|
||||
private Header() {
|
||||
// Never constructed.
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.ozone.web.request;
|
||||
|
||||
|
||||
import org.apache.hadoop.ozone.web.headers.Header;
|
||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||
|
||||
/**
|
||||
* represents an OzoneQuota Object that can be applied to
|
||||
* a storage volume.
|
||||
*/
|
||||
public class OzoneQuota {
|
||||
private static final long MB_IN_BYTES = 1048576L;
|
||||
private static final long GB_IN_BYTES = 1073741824L;
|
||||
private static final long TB_IN_BYTES = 1099511627776L;
|
||||
|
||||
|
||||
private Units unit;
|
||||
private int size;
|
||||
|
||||
/** Quota Units.*/
|
||||
public enum Units {UNDEFINED, BYTES, MB, GB, TB}
|
||||
|
||||
/**
|
||||
* Returns size.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Units.
|
||||
*
|
||||
* @return Unit in MB, GB or TB
|
||||
*/
|
||||
public Units getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a default Quota object.
|
||||
*/
|
||||
public OzoneQuota() {
|
||||
this.size = 0;
|
||||
this.unit = Units.UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for Ozone Quota.
|
||||
*
|
||||
* @param size - Integer Size
|
||||
* @param unit MB, GB or TB
|
||||
*/
|
||||
public OzoneQuota(int size, Units unit) {
|
||||
this.size = size;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a user provided string and returns the
|
||||
* Quota Object.
|
||||
*
|
||||
* @param quotaString Quota String
|
||||
*
|
||||
* @return OzoneQuota object
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public static OzoneQuota parseQuota(String quotaString)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
if ((quotaString == null) || (quotaString.isEmpty())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Quota string cannot be null or empty.");
|
||||
}
|
||||
|
||||
if (isRemove(quotaString)) {
|
||||
throw new IllegalArgumentException("Remove is invalid in this context.");
|
||||
}
|
||||
|
||||
String uppercase = quotaString.toUpperCase().replaceAll("\\s+", "");
|
||||
String size = "";
|
||||
int nSize;
|
||||
Units currUnit = Units.MB;
|
||||
Boolean found = false;
|
||||
if (uppercase.endsWith(Header.OZONE_QUOTA_MB)) {
|
||||
size = uppercase
|
||||
.substring(0, uppercase.length() - Header.OZONE_QUOTA_MB.length());
|
||||
currUnit = Units.MB;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (uppercase.endsWith(Header.OZONE_QUOTA_GB)) {
|
||||
size = uppercase
|
||||
.substring(0, uppercase.length() - Header.OZONE_QUOTA_GB.length());
|
||||
currUnit = Units.GB;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (uppercase.endsWith(Header.OZONE_QUOTA_TB)) {
|
||||
size = uppercase
|
||||
.substring(0, uppercase.length() - Header.OZONE_QUOTA_TB.length());
|
||||
currUnit = Units.TB;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (uppercase.endsWith(Header.OZONE_QUOTA_BYTES)) {
|
||||
size = uppercase
|
||||
.substring(0, uppercase.length() - Header.OZONE_QUOTA_BYTES.length());
|
||||
currUnit = Units.BYTES;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new IllegalArgumentException(
|
||||
"Quota unit not recognized. Supported values are BYTES, MB, GB and " +
|
||||
"TB.");
|
||||
}
|
||||
|
||||
nSize = Integer.parseInt(size);
|
||||
if (nSize < 0) {
|
||||
throw new IllegalArgumentException("Quota cannot be negative.");
|
||||
}
|
||||
|
||||
return new OzoneQuota(nSize, currUnit);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if Quota String is just as remove operation.
|
||||
*
|
||||
* @param quotaString User provided quota String
|
||||
*
|
||||
* @return True if it is Remove, false otherwise
|
||||
*/
|
||||
public static boolean isRemove(String quotaString) {
|
||||
|
||||
return (quotaString != null) &&
|
||||
(quotaString.compareToIgnoreCase(Header.OZONE_QUOTA_REMOVE) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns size in Bytes or -1 if there is no Quota.
|
||||
*/
|
||||
@JsonIgnore
|
||||
public long sizeInBytes() {
|
||||
switch (this.unit) {
|
||||
case BYTES:
|
||||
return this.getSize();
|
||||
case MB:
|
||||
return this.getSize() * MB_IN_BYTES;
|
||||
case GB:
|
||||
return this.getSize() * GB_IN_BYTES;
|
||||
case TB:
|
||||
return this.getSize() * TB_IN_BYTES;
|
||||
case UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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.ozone.web;
|
||||
|
||||
import org.apache.hadoop.ozone.web.request.OzoneQuota;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
|
||||
public class TestQuota {
|
||||
@Test
|
||||
public void TestParseQuota() {
|
||||
HashMap<String, Boolean> testMatrix;
|
||||
testMatrix = new HashMap<String, Boolean>();
|
||||
|
||||
testMatrix.put("10TB", Boolean.TRUE);
|
||||
testMatrix.put("1 TB", Boolean.TRUE);
|
||||
testMatrix.put("0MB", Boolean.TRUE);
|
||||
testMatrix.put("0 TB", Boolean.TRUE);
|
||||
testMatrix.put(" 1000MB ", Boolean.TRUE);
|
||||
|
||||
testMatrix.put(" 1000MBMB ", Boolean.FALSE);
|
||||
testMatrix.put(" 1000MB00 ", Boolean.FALSE);
|
||||
testMatrix.put("1000ZMB", Boolean.FALSE);
|
||||
testMatrix.put("MB1000", Boolean.FALSE);
|
||||
testMatrix.put("9999", Boolean.FALSE);
|
||||
testMatrix.put("1", Boolean.FALSE);
|
||||
testMatrix.put("remove", Boolean.FALSE);
|
||||
testMatrix.put("1UNDEFINED", Boolean.FALSE);
|
||||
testMatrix.put(null, Boolean.FALSE);
|
||||
testMatrix.put("", Boolean.FALSE);
|
||||
testMatrix.put("-1000MB", Boolean.FALSE);
|
||||
testMatrix.put("1024 bytes", Boolean.TRUE);
|
||||
testMatrix.put("1bytes", Boolean.TRUE);
|
||||
testMatrix.put("0bytes", Boolean.TRUE);
|
||||
testMatrix.put("10000 BYTES",Boolean.TRUE );
|
||||
testMatrix.put("BYTESbytes", Boolean.FALSE);
|
||||
testMatrix.put("bytes", Boolean.FALSE);
|
||||
|
||||
|
||||
Set<String> keys = testMatrix.keySet();
|
||||
for (String key : keys) {
|
||||
if (testMatrix.get(key)) {
|
||||
OzoneQuota.parseQuota(key);
|
||||
} else {
|
||||
try {
|
||||
OzoneQuota.parseQuota(key);
|
||||
// should never get here since the isValid call will throw
|
||||
fail(key);
|
||||
fail("An exception was expected but did not happen.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestVerifyQuota() {
|
||||
OzoneQuota qt = OzoneQuota.parseQuota("10TB");
|
||||
assertEquals(qt.getSize(), 10);
|
||||
assertEquals(qt.getUnit(), OzoneQuota.Units.TB);
|
||||
assertEquals(qt.sizeInBytes(), 10L * (1024L * 1024L * 1024L * 1024L));
|
||||
|
||||
qt = OzoneQuota.parseQuota("10MB");
|
||||
assertEquals(qt.getSize(), 10);
|
||||
assertEquals(qt.getUnit(), OzoneQuota.Units.MB);
|
||||
assertEquals(qt.sizeInBytes(), 10L * (1024L * 1024L));
|
||||
|
||||
qt = OzoneQuota.parseQuota("10GB");
|
||||
assertEquals(qt.getSize(), 10);
|
||||
assertEquals(qt.getUnit(), OzoneQuota.Units.GB);
|
||||
assertEquals(qt.sizeInBytes(), 10L * (1024L * 1024L * 1024L));
|
||||
|
||||
qt = OzoneQuota.parseQuota("10BYTES");
|
||||
assertEquals(qt.getSize(), 10);
|
||||
assertEquals(qt.getUnit(), OzoneQuota.Units.BYTES);
|
||||
assertEquals(qt.sizeInBytes(), 10L);
|
||||
|
||||
OzoneQuota emptyQuota = new OzoneQuota();
|
||||
assertEquals(emptyQuota.sizeInBytes(), -1L);
|
||||
assertEquals(emptyQuota.getSize(), 0);
|
||||
assertEquals(emptyQuota.getUnit(), OzoneQuota.Units.UNDEFINED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestVerifyRemove() {
|
||||
assertTrue(OzoneQuota.isRemove("remove"));
|
||||
assertFalse(OzoneQuota.isRemove("not remove"));
|
||||
assertFalse(OzoneQuota.isRemove(null));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user