|
@@ -33,6 +33,7 @@ import org.apache.hadoop.conf.Configuration;
|
|
import org.apache.hadoop.conf.Configured;
|
|
import org.apache.hadoop.conf.Configured;
|
|
import org.apache.hadoop.fs.Path;
|
|
import org.apache.hadoop.fs.Path;
|
|
import org.apache.hadoop.fs.PathNotFoundException;
|
|
import org.apache.hadoop.fs.PathNotFoundException;
|
|
|
|
+import org.apache.hadoop.fs.RemoteIterator;
|
|
import org.apache.hadoop.util.StringUtils;
|
|
import org.apache.hadoop.util.StringUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -325,20 +326,68 @@ abstract public class Command extends Configured {
|
|
*/
|
|
*/
|
|
protected void processPaths(PathData parent, PathData ... items)
|
|
protected void processPaths(PathData parent, PathData ... items)
|
|
throws IOException {
|
|
throws IOException {
|
|
- // TODO: this really should be iterative
|
|
|
|
for (PathData item : items) {
|
|
for (PathData item : items) {
|
|
try {
|
|
try {
|
|
- processPath(item);
|
|
|
|
- if (recursive && isPathRecursable(item)) {
|
|
|
|
- recursePath(item);
|
|
|
|
- }
|
|
|
|
- postProcessPath(item);
|
|
|
|
|
|
+ processPathInternal(item);
|
|
} catch (IOException e) {
|
|
} catch (IOException e) {
|
|
displayError(e);
|
|
displayError(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Iterates over the given expanded paths and invokes
|
|
|
|
+ * {@link #processPath(PathData)} on each element. If "recursive" is true,
|
|
|
|
+ * will do a post-visit DFS on directories.
|
|
|
|
+ * @param parent if called via a recurse, will be the parent dir, else null
|
|
|
|
+ * @param itemsIterator a iterator of {@link PathData} objects to process
|
|
|
|
+ * @throws IOException if anything goes wrong...
|
|
|
|
+ */
|
|
|
|
+ protected void processPaths(PathData parent,
|
|
|
|
+ RemoteIterator<PathData> itemsIterator) throws IOException {
|
|
|
|
+ int groupSize = getListingGroupSize();
|
|
|
|
+ if (groupSize == 0) {
|
|
|
|
+ // No grouping of contents required.
|
|
|
|
+ while (itemsIterator.hasNext()) {
|
|
|
|
+ processPaths(parent, itemsIterator.next());
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ List<PathData> items = new ArrayList<PathData>(groupSize);
|
|
|
|
+ while (itemsIterator.hasNext()) {
|
|
|
|
+ items.add(itemsIterator.next());
|
|
|
|
+ if (!itemsIterator.hasNext() || items.size() == groupSize) {
|
|
|
|
+ processPaths(parent, items.toArray(new PathData[items.size()]));
|
|
|
|
+ items.clear();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void processPathInternal(PathData item) throws IOException {
|
|
|
|
+ processPath(item);
|
|
|
|
+ if (recursive && isPathRecursable(item)) {
|
|
|
|
+ recursePath(item);
|
|
|
|
+ }
|
|
|
|
+ postProcessPath(item);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Whether the directory listing for a path should be sorted.?
|
|
|
|
+ * @return true/false.
|
|
|
|
+ */
|
|
|
|
+ protected boolean isSorted() {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * While using iterator method for listing for a path, whether to group items
|
|
|
|
+ * and process as array? If so what is the size of array?
|
|
|
|
+ * @return size of the grouping array.
|
|
|
|
+ */
|
|
|
|
+ protected int getListingGroupSize() {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Determines whether a {@link PathData} item is recursable. Default
|
|
* Determines whether a {@link PathData} item is recursable. Default
|
|
* implementation is to recurse directories but can be overridden to recurse
|
|
* implementation is to recurse directories but can be overridden to recurse
|
|
@@ -384,7 +433,13 @@ abstract public class Command extends Configured {
|
|
protected void recursePath(PathData item) throws IOException {
|
|
protected void recursePath(PathData item) throws IOException {
|
|
try {
|
|
try {
|
|
depth++;
|
|
depth++;
|
|
- processPaths(item, item.getDirectoryContents());
|
|
|
|
|
|
+ if (isSorted()) {
|
|
|
|
+ // use the non-iterative method for listing because explicit sorting is
|
|
|
|
+ // required. Iterators not guaranteed to return sorted elements
|
|
|
|
+ processPaths(item, item.getDirectoryContents());
|
|
|
|
+ } else {
|
|
|
|
+ processPaths(item, item.getDirectoryContentsIterator());
|
|
|
|
+ }
|
|
} finally {
|
|
} finally {
|
|
depth--;
|
|
depth--;
|
|
}
|
|
}
|