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 clazz 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 static <T extends CreateOpts> T getOpt(Class<T> clazz, CreateOpts... opts) {
159 if (opts == null) {
160 throw new IllegalArgumentException("Null opt");
161 }
162 T result = null;
163 for (int i = 0; i < opts.length; ++i) {
164 if (opts[i].getClass() == clazz) {
165 if (result != null) {
166 throw new IllegalArgumentException("multiple opts varargs: " + clazz);
167 }
168
169 @SuppressWarnings("unchecked")
170 T t = (T)opts[i];
171 result = t;
172 }
173 }
174 return result;
175 }
176 /**
177 * set an option
178 * @param newValue the option to be set
179 * @param opts - the option is set into this array of opts
180 * @return updated CreateOpts[] == opts + newValue
181 */
182 static <T extends CreateOpts> CreateOpts[] setOpt(final T newValue,
183 final CreateOpts... opts) {
184 final Class<?> clazz = newValue.getClass();
185 boolean alreadyInOpts = false;
186 if (opts != null) {
187 for (int i = 0; i < opts.length; ++i) {
188 if (opts[i].getClass() == clazz) {
189 if (alreadyInOpts) {
190 throw new IllegalArgumentException("multiple opts varargs: " + clazz);
191 }
192 alreadyInOpts = true;
193 opts[i] = newValue;
194 }
195 }
196 }
197 CreateOpts[] resultOpt = opts;
198 if (!alreadyInOpts) { // no newValue in opt
199 final int oldLength = opts == null? 0: opts.length;
200 CreateOpts[] newOpts = new CreateOpts[oldLength + 1];
201 if (oldLength > 0) {
202 System.arraycopy(opts, 0, newOpts, 0, oldLength);
203 }
204 newOpts[oldLength] = newValue;
205 resultOpt = newOpts;
206 }
207 return resultOpt;
208 }
209 }
210
211 /**
212 * Enum to support the varargs for rename() options
213 */
214 public static enum Rename {
215 NONE((byte) 0), // No options
216 OVERWRITE((byte) 1); // Overwrite the rename destination
217
218 private final byte code;
219
220 private Rename(byte code) {
221 this.code = code;
222 }
223
224 public static Rename valueOf(byte code) {
225 return code < 0 || code >= values().length ? null : values()[code];
226 }
227
228 public byte value() {
229 return code;
230 }
231 }
232
233 /**
234 * This is used in FileSystem and FileContext to specify checksum options.
235 */
236 public static class ChecksumOpt {
237 private final int crcBlockSize;
238 private final DataChecksum.Type crcType;
239
240 /**
241 * Create a uninitialized one
242 */
243 public ChecksumOpt() {
244 crcBlockSize = -1;
245 crcType = DataChecksum.Type.DEFAULT;
246 }
247
248 /**
249 * Normal ctor
250 * @param type checksum type
251 * @param size bytes per checksum
252 */
253 public ChecksumOpt(DataChecksum.Type type, int size) {
254 crcBlockSize = size;
255 crcType = type;
256 }
257
258 public int getBytesPerChecksum() {
259 return crcBlockSize;
260 }
261
262 public DataChecksum.Type getChecksumType() {
263 return crcType;
264 }
265
266 /**
267 * Create a ChecksumOpts that disables checksum
268 */
269 public static ChecksumOpt createDisabled() {
270 return new ChecksumOpt(DataChecksum.Type.NULL, -1);
271 }
272
273 /**
274 * A helper method for processing user input and default value to
275 * create a combined checksum option. This is a bit complicated because
276 * bytesPerChecksum is kept for backward compatibility.
277 *
278 * @param defaultOpt Default checksum option
279 * @param userOpt User-specified checksum option. Ignored if null.
280 * @param userBytesPerChecksum User-specified bytesPerChecksum
281 * Ignored if < 0.
282 */
283 public static ChecksumOpt processChecksumOpt(ChecksumOpt defaultOpt,
284 ChecksumOpt userOpt, int userBytesPerChecksum) {
285 final boolean useDefaultType;
286 final DataChecksum.Type type;
287 if (userOpt != null
288 && userOpt.getChecksumType() != DataChecksum.Type.DEFAULT) {
289 useDefaultType = false;
290 type = userOpt.getChecksumType();
291 } else {
292 useDefaultType = true;
293 type = defaultOpt.getChecksumType();
294 }
295
296 // bytesPerChecksum - order of preference
297 // user specified value in bytesPerChecksum
298 // user specified value in checksumOpt
299 // default.
300 if (userBytesPerChecksum > 0) {
301 return new ChecksumOpt(type, userBytesPerChecksum);
302 } else if (userOpt != null && userOpt.getBytesPerChecksum() > 0) {
303 return !useDefaultType? userOpt
304 : new ChecksumOpt(type, userOpt.getBytesPerChecksum());
305 } else {
306 return useDefaultType? defaultOpt
307 : new ChecksumOpt(type, defaultOpt.getBytesPerChecksum());
308 }
309 }
310
311 /**
312 * A helper method for processing user input and default value to
313 * create a combined checksum option.
314 *
315 * @param defaultOpt Default checksum option
316 * @param userOpt User-specified checksum option
317 */
318 public static ChecksumOpt processChecksumOpt(ChecksumOpt defaultOpt,
319 ChecksumOpt userOpt) {
320 return processChecksumOpt(defaultOpt, userOpt, -1);
321 }
322 }
323 }