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 import org.apache.hadoop.HadoopIllegalArgumentException;
026
027 /**
028 * This class contains options related to file system operations.
029 */
030 @InterfaceAudience.Public
031 @InterfaceStability.Evolving
032 public 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 }