blob: 54b68663fe9b81abe97d1fdb45fcaafed0b02328 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.fs.s3a.performance;
/**
* Declaration of the costs of head and list calls for various FS IO
* operations.
* <p></p>
* An instance declares the number of head and list calls expected for
* various operations -with a {@link #plus(OperationCost)}
* method to add operation costs together to produce an
* aggregate cost. These can then be validated in tests
* via {@link OperationCostValidator}.
*
*/
public final class OperationCost {
/** Head costs for getFileStatus() directory probe: {@value}. */
public static final int FILESTATUS_DIR_PROBE_H = 0;
/** List costs for getFileStatus() directory probe: {@value}. */
public static final int FILESTATUS_DIR_PROBE_L = 1;
/** Head cost getFileStatus() file probe only. */
public static final int FILESTATUS_FILE_PROBE_H = 1;
/** Liast cost getFileStatus() file probe only. */
public static final int FILESTATUS_FILE_PROBE_L = 0;
/**
* Delete cost when deleting an object.
*/
public static final int DELETE_OBJECT_REQUEST = 1;
/**
* Delete cost when deleting a marker.
*/
public static final int DELETE_MARKER_REQUEST = DELETE_OBJECT_REQUEST;
/**
* No IO takes place.
*/
public static final OperationCost NO_IO =
new OperationCost(0, 0);
/** A HEAD operation. */
public static final OperationCost HEAD_OPERATION = new OperationCost(1, 0);
/** A LIST operation. */
public static final OperationCost LIST_OPERATION = new OperationCost(0, 1);
/**
* Cost of {@link org.apache.hadoop.fs.s3a.impl.StatusProbeEnum#DIRECTORIES}.
*/
public static final OperationCost FILE_STATUS_DIR_PROBE = LIST_OPERATION;
/**
* Cost of {@link org.apache.hadoop.fs.s3a.impl.StatusProbeEnum#FILE}.
*/
public static final OperationCost FILE_STATUS_FILE_PROBE = HEAD_OPERATION;
/**
* Cost of {@link org.apache.hadoop.fs.s3a.impl.StatusProbeEnum#ALL}.
*/
public static final OperationCost FILE_STATUS_ALL_PROBES =
FILE_STATUS_FILE_PROBE.plus(FILE_STATUS_DIR_PROBE);
/** getFileStatus() on a file which exists. */
public static final OperationCost GET_FILE_STATUS_ON_FILE =
FILE_STATUS_FILE_PROBE;
/** List costs for getFileStatus() on a non-empty directory: {@value}. */
public static final OperationCost GET_FILE_STATUS_ON_DIR =
FILE_STATUS_FILE_PROBE.plus(FILE_STATUS_DIR_PROBE);
/** Costs for getFileStatus() on an empty directory: {@value}. */
public static final OperationCost GET_FILE_STATUS_ON_EMPTY_DIR =
GET_FILE_STATUS_ON_DIR;
/** getFileStatus() directory marker which exists. */
public static final OperationCost GET_FILE_STATUS_ON_DIR_MARKER =
GET_FILE_STATUS_ON_EMPTY_DIR;
/** getFileStatus() call which fails to find any entry. */
public static final OperationCost GET_FILE_STATUS_FNFE =
FILE_STATUS_ALL_PROBES;
/** listLocatedStatus always does a LIST. */
public static final OperationCost LIST_LOCATED_STATUS_LIST_OP =
new OperationCost(0, 1);
/** listFiles always does a LIST. */
public static final OperationCost LIST_FILES_LIST_OP = LIST_OPERATION;
/** listStatus always does a LIST. */
public static final OperationCost LIST_STATUS_LIST_OP = LIST_OPERATION;
/**
* Metadata cost of a copy operation, as used during rename.
* This happens even if the store is guarded.
*/
public static final OperationCost COPY_OP =
new OperationCost(1, 0);
/**
* Cost of renaming a file to a different directory.
* <p></p>
* LIST on dest not found, look for dest dir, and then, at
* end of rename, whether a parent dir needs to be created.
*/
public static final OperationCost RENAME_SINGLE_FILE_DIFFERENT_DIR =
FILE_STATUS_FILE_PROBE // source file probe
.plus(GET_FILE_STATUS_FNFE) // dest does not exist
.plus(FILE_STATUS_DIR_PROBE) // parent dir of dest
.plus(FILE_STATUS_DIR_PROBE) // recreate source parent dir?
.plus(COPY_OP); // metadata read on copy
/**
* Cost of renaming a file to the same directory
* <p></p>
* No need to look for parent directories, so only file
* existence checks and the copy.
*/
public static final OperationCost RENAME_SINGLE_FILE_SAME_DIR =
FILE_STATUS_FILE_PROBE // source file probe
.plus(GET_FILE_STATUS_FNFE) // dest must not exist
.plus(COPY_OP); // metadata read on copy
/**
* create(overwrite = true) does not look for the file existing.
*/
public static final OperationCost CREATE_FILE_OVERWRITE =
FILE_STATUS_DIR_PROBE;
/**
* create(overwrite = false) runs all the checks.
*/
public static final OperationCost CREATE_FILE_NO_OVERWRITE =
FILE_STATUS_ALL_PROBES;
/** Expected HEAD count. */
private final int head;
/** Expected LIST count. */
private final int list;
/**
* Constructor.
* @param head head requests.
* @param list list requests.
*/
public OperationCost(final int head,
final int list) {
this.head = head;
this.list = list;
}
/** Expected HEAD count. */
int head() {
return head;
}
/** Expected LIST count. */
int list() {
return list;
}
/**
* Add to create a new cost.
* @param that the other entry
* @return cost of the combined operation.
*/
public OperationCost plus(OperationCost that) {
return new OperationCost(
head + that.head,
list + that.list);
}
@Override
public String toString() {
return "OperationCost{" +
"head=" + head +
", list=" + list +
'}';
}
}