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