/**
* 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.fs;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.DataChecksum;
import org.apache.hadoop.util.Progressable;
/**
* This class contains options related to file system operations.
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public final class Options {
/**
* Class to support the varargs for create() options.
*
*/
public static class CreateOpts {
private CreateOpts() { };
public static BlockSize blockSize(long bs) {
return new BlockSize(bs);
}
public static BufferSize bufferSize(int bs) {
return new BufferSize(bs);
}
public static ReplicationFactor repFac(short rf) {
return new ReplicationFactor(rf);
}
public static BytesPerChecksum bytesPerChecksum(short crc) {
return new BytesPerChecksum(crc);
}
public static ChecksumParam checksumParam(
ChecksumOpt csumOpt) {
return new ChecksumParam(csumOpt);
}
public static Perms perms(FsPermission perm) {
return new Perms(perm);
}
public static CreateParent createParent() {
return new CreateParent(true);
}
public static CreateParent donotCreateParent() {
return new CreateParent(false);
}
public static class BlockSize extends CreateOpts {
private final long blockSize;
protected BlockSize(long bs) {
if (bs <= 0) {
throw new IllegalArgumentException(
"Block size must be greater than 0");
}
blockSize = bs;
}
public long getValue() { return blockSize; }
}
public static class ReplicationFactor extends CreateOpts {
private final short replication;
protected ReplicationFactor(short rf) {
if (rf <= 0) {
throw new IllegalArgumentException(
"Replication must be greater than 0");
}
replication = rf;
}
public short getValue() { return replication; }
}
public static class BufferSize extends CreateOpts {
private final int bufferSize;
protected BufferSize(int bs) {
if (bs <= 0) {
throw new IllegalArgumentException(
"Buffer size must be greater than 0");
}
bufferSize = bs;
}
public int getValue() { return bufferSize; }
}
/** This is not needed if ChecksumParam is specified. **/
public static class BytesPerChecksum extends CreateOpts {
private final int bytesPerChecksum;
protected BytesPerChecksum(short bpc) {
if (bpc <= 0) {
throw new IllegalArgumentException(
"Bytes per checksum must be greater than 0");
}
bytesPerChecksum = bpc;
}
public int getValue() { return bytesPerChecksum; }
}
public static class ChecksumParam extends CreateOpts {
private final ChecksumOpt checksumOpt;
protected ChecksumParam(ChecksumOpt csumOpt) {
checksumOpt = csumOpt;
}
public ChecksumOpt getValue() { return checksumOpt; }
}
public static class Perms extends CreateOpts {
private final FsPermission permissions;
protected Perms(FsPermission perm) {
if(perm == null) {
throw new IllegalArgumentException("Permissions must not be null");
}
permissions = perm;
}
public FsPermission getValue() { return permissions; }
}
public static class Progress extends CreateOpts {
private final Progressable progress;
protected Progress(Progressable prog) {
if(prog == null) {
throw new IllegalArgumentException("Progress must not be null");
}
progress = prog;
}
public Progressable getValue() { return progress; }
}
public static class CreateParent extends CreateOpts {
private final boolean createParent;
protected CreateParent(boolean createPar) {
createParent = createPar;}
public boolean getValue() { return createParent; }
}
/**
* Get an option of desired type
* @param clazz is the desired class of the opt
* @param opts - not null - at least one opt must be passed
* @return an opt from one of the opts of type theClass.
* returns null if there isn't any
*/
static <T extends CreateOpts> T getOpt(Class<T> clazz, CreateOpts... opts) {
if (opts == null) {
throw new IllegalArgumentException("Null opt");
}
T result = null;
for (int i = 0; i < opts.length; ++i) {
if (opts[i].getClass() == clazz) {
if (result != null) {
throw new IllegalArgumentException("multiple opts varargs: " + clazz);
}
@SuppressWarnings("unchecked")
T t = (T)opts[i];
result = t;
}
}
return result;
}
/**
* set an option
* @param newValue the option to be set
* @param opts - the option is set into this array of opts
* @return updated CreateOpts[] == opts + newValue
*/
static <T extends CreateOpts> CreateOpts[] setOpt(final T newValue,
final CreateOpts... opts) {
final Class<?> clazz = newValue.getClass();
boolean alreadyInOpts = false;
if (opts != null) {
for (int i = 0; i < opts.length; ++i) {
if (opts[i].getClass() == clazz) {
if (alreadyInOpts) {
throw new IllegalArgumentException("multiple opts varargs: " + clazz);
}
alreadyInOpts = true;
opts[i] = newValue;
}
}
}
CreateOpts[] resultOpt = opts;
if (!alreadyInOpts) { // no newValue in opt
final int oldLength = opts == null? 0: opts.length;
CreateOpts[] newOpts = new CreateOpts[oldLength + 1];
if (oldLength > 0) {
System.arraycopy(opts, 0, newOpts, 0, oldLength);
}
newOpts[oldLength] = newValue;
resultOpt = newOpts;
}
return resultOpt;
}
}
/**
* Enum to support the varargs for rename() options
*/
public static enum Rename {
NONE((byte) 0), // No options
OVERWRITE((byte) 1),
KEEP_ENCODING_STATUS((byte)2 ); // Overwrite the rename destination
private final byte code;
private Rename(byte code) {
this.code = code;
}
public static Rename valueOf(byte code) {
return code < 0 || code >= values().length ? null : values()[code];
}
public byte value() {
return code;
}
}
/**
* This is used in FileSystem and FileContext to specify checksum options.
*/
public static class ChecksumOpt {
private final DataChecksum.Type checksumType;
private final int bytesPerChecksum;
/**
* Create a uninitialized one
*/
public ChecksumOpt() {
this(DataChecksum.Type.DEFAULT, -1);
}
/**
* Normal ctor
* @param type checksum type
* @param size bytes per checksum
*/
public ChecksumOpt(DataChecksum.Type type, int size) {
checksumType = type;
bytesPerChecksum = size;
}
public int getBytesPerChecksum() {
return bytesPerChecksum;
}
public DataChecksum.Type getChecksumType() {
return checksumType;
}
@Override
public String toString() {
return checksumType + ":" + bytesPerChecksum;
}
/**
* Create a ChecksumOpts that disables checksum
*/
public static ChecksumOpt createDisabled() {
return new ChecksumOpt(DataChecksum.Type.NULL, -1);
}
/**
* A helper method for processing user input and default value to
* create a combined checksum option. This is a bit complicated because
* bytesPerChecksum is kept for backward compatibility.
*
* @param defaultOpt Default checksum option
* @param userOpt User-specified checksum option. Ignored if null.
* @param userBytesPerChecksum User-specified bytesPerChecksum
* Ignored if < 0.
*/
public static ChecksumOpt processChecksumOpt(ChecksumOpt defaultOpt,
ChecksumOpt userOpt, int userBytesPerChecksum) {
final boolean useDefaultType;
final DataChecksum.Type type;
if (userOpt != null
&& userOpt.getChecksumType() != DataChecksum.Type.DEFAULT) {
useDefaultType = false;
type = userOpt.getChecksumType();
} else {
useDefaultType = true;
type = defaultOpt.getChecksumType();
}
// bytesPerChecksum - order of preference
// user specified value in bytesPerChecksum
// user specified value in checksumOpt
// default.
if (userBytesPerChecksum > 0) {
return new ChecksumOpt(type, userBytesPerChecksum);
} else if (userOpt != null && userOpt.getBytesPerChecksum() > 0) {
return !useDefaultType? userOpt
: new ChecksumOpt(type, userOpt.getBytesPerChecksum());
} else {
return useDefaultType? defaultOpt
: new ChecksumOpt(type, defaultOpt.getBytesPerChecksum());
}
}
/**
* A helper method for processing user input and default value to
* create a combined checksum option.
*
* @param defaultOpt Default checksum option
* @param userOpt User-specified checksum option
*/
public static ChecksumOpt processChecksumOpt(ChecksumOpt defaultOpt,
ChecksumOpt userOpt) {
return processChecksumOpt(defaultOpt, userOpt, -1);
}
}
}