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 }