HDFS-8614. OzoneHandler : Add Quota Support. (Contributed by Anu Engineer)

This commit is contained in:
Arpit Agarwal 2015-06-17 08:50:19 -07:00 committed by Owen O'Malley
parent d41245ca56
commit 0a90e6d45c
4 changed files with 331 additions and 0 deletions

View File

@ -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)

View File

@ -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.
}
}

View File

@ -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;
}
}
}

View File

@ -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));
}
}