001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.fs; 019 020import org.apache.hadoop.classification.InterfaceAudience; 021import org.apache.hadoop.classification.InterfaceStability; 022import org.apache.hadoop.fs.permission.FsPermission; 023import org.apache.hadoop.util.DataChecksum; 024import org.apache.hadoop.util.Progressable; 025import org.apache.hadoop.HadoopIllegalArgumentException; 026 027/** 028 * This class contains options related to file system operations. 029 */ 030@InterfaceAudience.Public 031@InterfaceStability.Evolving 032public final class Options { 033 /** 034 * Class to support the varargs for create() options. 035 * 036 */ 037 public static class CreateOpts { 038 private CreateOpts() { }; 039 public static BlockSize blockSize(long bs) { 040 return new BlockSize(bs); 041 } 042 public static BufferSize bufferSize(int bs) { 043 return new BufferSize(bs); 044 } 045 public static ReplicationFactor repFac(short rf) { 046 return new ReplicationFactor(rf); 047 } 048 public static BytesPerChecksum bytesPerChecksum(short crc) { 049 return new BytesPerChecksum(crc); 050 } 051 public static ChecksumParam checksumParam( 052 ChecksumOpt csumOpt) { 053 return new ChecksumParam(csumOpt); 054 } 055 public static Perms perms(FsPermission perm) { 056 return new Perms(perm); 057 } 058 public static CreateParent createParent() { 059 return new CreateParent(true); 060 } 061 public static CreateParent donotCreateParent() { 062 return new CreateParent(false); 063 } 064 065 public static class BlockSize extends CreateOpts { 066 private final long blockSize; 067 protected BlockSize(long bs) { 068 if (bs <= 0) { 069 throw new IllegalArgumentException( 070 "Block size must be greater than 0"); 071 } 072 blockSize = bs; 073 } 074 public long getValue() { return blockSize; } 075 } 076 077 public static class ReplicationFactor extends CreateOpts { 078 private final short replication; 079 protected ReplicationFactor(short rf) { 080 if (rf <= 0) { 081 throw new IllegalArgumentException( 082 "Replication must be greater than 0"); 083 } 084 replication = rf; 085 } 086 public short getValue() { return replication; } 087 } 088 089 public static class BufferSize extends CreateOpts { 090 private final int bufferSize; 091 protected BufferSize(int bs) { 092 if (bs <= 0) { 093 throw new IllegalArgumentException( 094 "Buffer size must be greater than 0"); 095 } 096 bufferSize = bs; 097 } 098 public int getValue() { return bufferSize; } 099 } 100 101 /** This is not needed if ChecksumParam is specified. **/ 102 public static class BytesPerChecksum extends CreateOpts { 103 private final int bytesPerChecksum; 104 protected BytesPerChecksum(short bpc) { 105 if (bpc <= 0) { 106 throw new IllegalArgumentException( 107 "Bytes per checksum must be greater than 0"); 108 } 109 bytesPerChecksum = bpc; 110 } 111 public int getValue() { return bytesPerChecksum; } 112 } 113 114 public static class ChecksumParam extends CreateOpts { 115 private final ChecksumOpt checksumOpt; 116 protected ChecksumParam(ChecksumOpt csumOpt) { 117 checksumOpt = csumOpt; 118 } 119 public ChecksumOpt getValue() { return checksumOpt; } 120 } 121 122 public static class Perms extends CreateOpts { 123 private final FsPermission permissions; 124 protected Perms(FsPermission perm) { 125 if(perm == null) { 126 throw new IllegalArgumentException("Permissions must not be null"); 127 } 128 permissions = perm; 129 } 130 public FsPermission getValue() { return permissions; } 131 } 132 133 public static class Progress extends CreateOpts { 134 private final Progressable progress; 135 protected Progress(Progressable prog) { 136 if(prog == null) { 137 throw new IllegalArgumentException("Progress must not be null"); 138 } 139 progress = prog; 140 } 141 public Progressable getValue() { return progress; } 142 } 143 144 public static class CreateParent extends CreateOpts { 145 private final boolean createParent; 146 protected CreateParent(boolean createPar) { 147 createParent = createPar;} 148 public boolean getValue() { return createParent; } 149 } 150 151 152 /** 153 * Get an option of desired type 154 * @param theClass is the desired class of the opt 155 * @param opts - not null - at least one opt must be passed 156 * @return an opt from one of the opts of type theClass. 157 * returns null if there isn't any 158 */ 159 protected static CreateOpts getOpt(Class<? extends CreateOpts> theClass, CreateOpts ...opts) { 160 if (opts == null) { 161 throw new IllegalArgumentException("Null opt"); 162 } 163 CreateOpts result = null; 164 for (int i = 0; i < opts.length; ++i) { 165 if (opts[i].getClass() == theClass) { 166 if (result != null) 167 throw new IllegalArgumentException("multiple blocksize varargs"); 168 result = opts[i]; 169 } 170 } 171 return result; 172 } 173 /** 174 * set an option 175 * @param newValue the option to be set 176 * @param opts - the option is set into this array of opts 177 * @return updated CreateOpts[] == opts + newValue 178 */ 179 protected static <T extends CreateOpts> CreateOpts[] setOpt(T newValue, 180 CreateOpts ...opts) { 181 boolean alreadyInOpts = false; 182 if (opts != null) { 183 for (int i = 0; i < opts.length; ++i) { 184 if (opts[i].getClass() == newValue.getClass()) { 185 if (alreadyInOpts) 186 throw new IllegalArgumentException("multiple opts varargs"); 187 alreadyInOpts = true; 188 opts[i] = newValue; 189 } 190 } 191 } 192 CreateOpts[] resultOpt = opts; 193 if (!alreadyInOpts) { // no newValue in opt 194 CreateOpts[] newOpts = new CreateOpts[opts.length + 1]; 195 System.arraycopy(opts, 0, newOpts, 0, opts.length); 196 newOpts[opts.length] = newValue; 197 resultOpt = newOpts; 198 } 199 return resultOpt; 200 } 201 } 202 203 /** 204 * Enum to support the varargs for rename() options 205 */ 206 public static enum Rename { 207 NONE((byte) 0), // No options 208 OVERWRITE((byte) 1); // Overwrite the rename destination 209 210 private final byte code; 211 212 private Rename(byte code) { 213 this.code = code; 214 } 215 216 public static Rename valueOf(byte code) { 217 return code < 0 || code >= values().length ? null : values()[code]; 218 } 219 220 public byte value() { 221 return code; 222 } 223 } 224 225 /** 226 * This is used in FileSystem and FileContext to specify checksum options. 227 */ 228 public static class ChecksumOpt { 229 private final int crcBlockSize; 230 private final DataChecksum.Type crcType; 231 232 /** 233 * Create a uninitialized one 234 */ 235 public ChecksumOpt() { 236 crcBlockSize = -1; 237 crcType = DataChecksum.Type.DEFAULT; 238 } 239 240 /** 241 * Normal ctor 242 * @param type checksum type 243 * @param size bytes per checksum 244 */ 245 public ChecksumOpt(DataChecksum.Type type, int size) { 246 crcBlockSize = size; 247 crcType = type; 248 } 249 250 public int getBytesPerChecksum() { 251 return crcBlockSize; 252 } 253 254 public DataChecksum.Type getChecksumType() { 255 return crcType; 256 } 257 258 /** 259 * Create a ChecksumOpts that disables checksum 260 */ 261 public static ChecksumOpt createDisabled() { 262 return new ChecksumOpt(DataChecksum.Type.NULL, -1); 263 } 264 265 /** 266 * A helper method for processing user input and default value to 267 * create a combined checksum option. This is a bit complicated because 268 * bytesPerChecksum is kept for backward compatibility. 269 * 270 * @param defaultOpt Default checksum option 271 * @param userOpt User-specified checksum option. Ignored if null. 272 * @param userBytesPerChecksum User-specified bytesPerChecksum 273 * Ignored if < 0. 274 */ 275 public static ChecksumOpt processChecksumOpt(ChecksumOpt defaultOpt, 276 ChecksumOpt userOpt, int userBytesPerChecksum) { 277 // The following is done to avoid unnecessary creation of new objects. 278 // tri-state variable: 0 default, 1 userBytesPerChecksum, 2 userOpt 279 short whichSize; 280 // true default, false userOpt 281 boolean useDefaultType; 282 283 // bytesPerChecksum - order of preference 284 // user specified value in bytesPerChecksum 285 // user specified value in checksumOpt 286 // default. 287 if (userBytesPerChecksum > 0) { 288 whichSize = 1; // userBytesPerChecksum 289 } else if (userOpt != null && userOpt.getBytesPerChecksum() > 0) { 290 whichSize = 2; // userOpt 291 } else { 292 whichSize = 0; // default 293 } 294 295 // checksum type - order of preference 296 // user specified value in checksumOpt 297 // default. 298 if (userOpt != null && 299 userOpt.getChecksumType() != DataChecksum.Type.DEFAULT) { 300 useDefaultType = false; 301 } else { 302 useDefaultType = true; 303 } 304 305 // Short out the common and easy cases 306 if (whichSize == 0 && useDefaultType) { 307 return defaultOpt; 308 } else if (whichSize == 2 && !useDefaultType) { 309 return userOpt; 310 } 311 312 // Take care of the rest of combinations 313 DataChecksum.Type type = useDefaultType ? defaultOpt.getChecksumType() : 314 userOpt.getChecksumType(); 315 if (whichSize == 0) { 316 return new ChecksumOpt(type, defaultOpt.getBytesPerChecksum()); 317 } else if (whichSize == 1) { 318 return new ChecksumOpt(type, userBytesPerChecksum); 319 } else { 320 return new ChecksumOpt(type, userOpt.getBytesPerChecksum()); 321 } 322 } 323 324 /** 325 * A helper method for processing user input and default value to 326 * create a combined checksum option. 327 * 328 * @param defaultOpt Default checksum option 329 * @param userOpt User-specified checksum option 330 */ 331 public static ChecksumOpt processChecksumOpt(ChecksumOpt defaultOpt, 332 ChecksumOpt userOpt) { 333 return processChecksumOpt(defaultOpt, userOpt, -1); 334 } 335 } 336}