Skip to content

Commit b89d875

Browse files
committed
HADOOP-16954. Add -S option in "Count" command to show only Snapshot Counts. Contributed by hemanthboyina.
1 parent e6455cc commit b89d875

File tree

6 files changed

+110
-9
lines changed

6 files changed

+110
-9
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ContentSummary.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,21 @@ public int hashCode() {
281281

282282
private static final String ALL_HEADER = QUOTA_HEADER + SUMMARY_HEADER;
283283

284+
/**
285+
* Output format:<-------18-------> <----------24---------->
286+
* <----------24---------->. <-------------28------------> SNAPSHOT_LENGTH
287+
* SNAPSHOT_FILE_COUNT SNAPSHOT_DIR_COUNT SNAPSHOT_SPACE_CONSUMED
288+
*/
289+
private static final String SNAPSHOT_FORMAT = "%18s %24s %24s %28s ";
290+
291+
private static final String[] SNAPSHOT_HEADER_FIELDS =
292+
new String[] {"SNAPSHOT_LENGTH", "SNAPSHOT_FILE_COUNT",
293+
"SNAPSHOT_DIR_COUNT", "SNAPSHOT_SPACE_CONSUMED"};
294+
295+
/** The header string. */
296+
private static final String SNAPSHOT_HEADER =
297+
String.format(SNAPSHOT_FORMAT, (Object[]) SNAPSHOT_HEADER_FIELDS);
298+
284299

285300
/** Return the header of the output.
286301
* if qOption is false, output directory count, file count, and content size;
@@ -293,7 +308,9 @@ public static String getHeader(boolean qOption) {
293308
return qOption ? ALL_HEADER : SUMMARY_HEADER;
294309
}
295310

296-
311+
public static String getSnapshotHeader() {
312+
return SNAPSHOT_HEADER;
313+
}
297314

298315
/**
299316
* Returns the names of the fields from the summary header.
@@ -416,7 +433,7 @@ public String toString(boolean qOption, boolean hOption, boolean tOption,
416433
}
417434

418435
/**
419-
* Formats a size to be human readable or in bytes
436+
* Formats a size to be human readable or in bytes.
420437
* @param size value to be formatted
421438
* @param humanReadable flag indicating human readable or not
422439
* @return String representation of the size
@@ -426,4 +443,17 @@ private String formatSize(long size, boolean humanReadable) {
426443
? StringUtils.TraditionalBinaryPrefix.long2String(size, "", 1)
427444
: String.valueOf(size);
428445
}
446+
447+
/**
448+
* Return the string representation of the snapshot counts in the output
449+
* format.
450+
* @param hOption flag indicating human readable or not
451+
* @return String representation of the snapshot counts
452+
*/
453+
public String toSnapshot(boolean hOption) {
454+
return String.format(SNAPSHOT_FORMAT, formatSize(snapshotLength, hOption),
455+
formatSize(snapshotFileCount, hOption),
456+
formatSize(snapshotDirectoryCount, hOption),
457+
formatSize(snapshotSpaceConsumed, hOption));
458+
}
429459
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Count.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@ public static void registerCommands(CommandFactory factory) {
5656
//return the quota, namespace count and disk space usage.
5757
private static final String OPTION_QUOTA_AND_USAGE = "u";
5858
private static final String OPTION_ECPOLICY = "e";
59+
private static final String OPTION_SNAPSHOT_COUNT = "s";
5960

6061
public static final String NAME = "count";
6162
public static final String USAGE =
6263
"[-" + OPTION_QUOTA + "] [-" + OPTION_HUMAN + "] [-" + OPTION_HEADER
6364
+ "] [-" + OPTION_TYPE + " [<storage type>]] [-" +
6465
OPTION_QUOTA_AND_USAGE + "] [-" + OPTION_EXCLUDE_SNAPSHOT
65-
+ "] [-" + OPTION_ECPOLICY
66+
+ "] [-" + OPTION_ECPOLICY + "] [-" + OPTION_SNAPSHOT_COUNT
6667
+ "] <path> ...";
6768
public static final String DESCRIPTION =
6869
"Count the number of directories, files and bytes under the paths\n" +
@@ -93,7 +94,8 @@ public static void registerCommands(CommandFactory factory) {
9394
"the storage types.\n" +
9495
"The -" + OPTION_QUOTA_AND_USAGE + " option shows the quota and \n" +
9596
"the usage against the quota without the detailed content summary."+
96-
"The -"+ OPTION_ECPOLICY +" option shows the erasure coding policy.";
97+
"The -" + OPTION_ECPOLICY + " option shows the erasure coding policy."
98+
+ "The -" + OPTION_SNAPSHOT_COUNT + " option shows snapshot counts.";
9799

98100
private boolean showQuotas;
99101
private boolean humanReadable;
@@ -102,6 +104,7 @@ public static void registerCommands(CommandFactory factory) {
102104
private boolean showQuotasAndUsageOnly;
103105
private boolean excludeSnapshots;
104106
private boolean displayECPolicy;
107+
private boolean showSnapshot;
105108

106109
/** Constructor */
107110
public Count() {}
@@ -123,7 +126,7 @@ protected void processOptions(LinkedList<String> args) {
123126
CommandFormat cf = new CommandFormat(1, Integer.MAX_VALUE,
124127
OPTION_QUOTA, OPTION_HUMAN, OPTION_HEADER, OPTION_QUOTA_AND_USAGE,
125128
OPTION_EXCLUDE_SNAPSHOT,
126-
OPTION_ECPOLICY);
129+
OPTION_ECPOLICY, OPTION_SNAPSHOT_COUNT);
127130
cf.addOptionWithValue(OPTION_TYPE);
128131
cf.parse(args);
129132
if (args.isEmpty()) { // default path is the current working directory
@@ -134,6 +137,7 @@ protected void processOptions(LinkedList<String> args) {
134137
showQuotasAndUsageOnly = cf.getOpt(OPTION_QUOTA_AND_USAGE);
135138
excludeSnapshots = cf.getOpt(OPTION_EXCLUDE_SNAPSHOT);
136139
displayECPolicy = cf.getOpt(OPTION_ECPOLICY);
140+
showSnapshot = cf.getOpt(OPTION_SNAPSHOT_COUNT);
137141

138142
if (showQuotas || showQuotasAndUsageOnly) {
139143
String types = cf.getOptValue(OPTION_TYPE);
@@ -165,6 +169,9 @@ protected void processOptions(LinkedList<String> args) {
165169
if(displayECPolicy){
166170
headString.append("ERASURECODING_POLICY ");
167171
}
172+
if (showSnapshot) {
173+
headString.append(ContentSummary.getSnapshotHeader());
174+
}
168175
headString.append("PATHNAME");
169176
out.println(headString.toString());
170177
}
@@ -205,6 +212,10 @@ protected void processPath(PathData src) throws IOException {
205212
outputString.append(summary.getErasureCodingPolicy())
206213
.append(" ");
207214
}
215+
if (showSnapshot) {
216+
ContentSummary summary = src.fs.getContentSummary(src.path);
217+
outputString.append(summary.toSnapshot(isHumanReadable()));
218+
}
208219
outputString.append(src);
209220
out.println(outputString.toString());
210221
}

hadoop-common-project/hadoop-common/src/site/markdown/FileSystemShell.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ Similar to get command, except that the destination is restricted to a local fil
145145
count
146146
-----
147147

148-
Usage: `hadoop fs -count [-q] [-h] [-v] [-x] [-t [<storage type>]] [-u] [-e] <paths> `
148+
Usage: `hadoop fs -count [-q] [-h] [-v] [-x] [-t [<storage type>]] [-u] [-e] [-s] <paths> `
149149

150150
Count the number of directories, files and bytes under the paths that match the specified file pattern. Get the quota and the usage. The output columns with -count are: DIR\_COUNT, FILE\_COUNT, CONTENT\_SIZE, PATHNAME
151151

@@ -169,6 +169,8 @@ The output columns with -count -e are: DIR\_COUNT, FILE\_COUNT, CONTENT_SIZE, ER
169169

170170
The ERASURECODING\_POLICY is name of the policy for the file. If a erasure coding policy is setted on that file, it will return name of the policy. If no erasure coding policy is setted, it will return \"Replicated\" which means it use replication storage strategy.
171171

172+
The -s option shows the snapshot counts for each directory.
173+
172174
Example:
173175

174176
* `hadoop fs -count hdfs://nn1.example.com/file1 hdfs://nn2.example.com/file2`
@@ -179,6 +181,7 @@ Example:
179181
* `hadoop fs -count -u -h hdfs://nn1.example.com/file1`
180182
* `hadoop fs -count -u -h -v hdfs://nn1.example.com/file1`
181183
* `hadoop fs -count -e hdfs://nn1.example.com/file1`
184+
* `hadoop fs -count -s hdfs://nn1.example.com/file1`
182185

183186
Exit Code:
184187

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestContentSummary.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,40 @@ public void testToStringHumanNoShowQuota() {
253253
String expected = " 32.6 K 211.9 M 8.0 E ";
254254
assertEquals(expected, contentSummary.toString(false, true));
255255
}
256+
257+
// check the toSnapshot method with human readable.
258+
@Test
259+
public void testToSnapshotHumanReadable() {
260+
long snapshotLength = Long.MAX_VALUE;
261+
long snapshotFileCount = 222222222;
262+
long snapshotDirectoryCount = 33333;
263+
long snapshotSpaceConsumed = 222256578;
264+
265+
ContentSummary contentSummary = new ContentSummary.Builder()
266+
.snapshotLength(snapshotLength).snapshotFileCount(snapshotFileCount)
267+
.snapshotDirectoryCount(snapshotDirectoryCount)
268+
.snapshotSpaceConsumed(snapshotSpaceConsumed).build();
269+
String expected =
270+
" 8.0 E 211.9 M 32.6 K "
271+
+ " 212.0 M ";
272+
assertEquals(expected, contentSummary.toSnapshot(true));
273+
}
274+
275+
// check the toSnapshot method with human readable disabled.
276+
@Test
277+
public void testToSnapshotNotHumanReadable() {
278+
long snapshotLength = 1111;
279+
long snapshotFileCount = 2222;
280+
long snapshotDirectoryCount = 3333;
281+
long snapshotSpaceConsumed = 4444;
282+
283+
ContentSummary contentSummary = new ContentSummary.Builder()
284+
.snapshotLength(snapshotLength).snapshotFileCount(snapshotFileCount)
285+
.snapshotDirectoryCount(snapshotDirectoryCount)
286+
.snapshotSpaceConsumed(snapshotSpaceConsumed).build();
287+
String expected =
288+
" 1111 2222 3333 "
289+
+ " 4444 ";
290+
assertEquals(expected, contentSummary.toSnapshot(false));
291+
}
256292
}

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestCount.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,25 @@ public void processPathWithQuotasByMultipleStorageTypes() throws Exception {
411411
verifyNoMoreInteractions(out);
412412
}
413413

414+
@Test
415+
public void processPathWithSnapshotHeader() throws Exception {
416+
Path path = new Path("mockfs:/test");
417+
when(mockFs.getFileStatus(eq(path))).thenReturn(fileStat);
418+
PrintStream out = mock(PrintStream.class);
419+
Count count = new Count();
420+
count.out = out;
421+
LinkedList<String> options = new LinkedList<String>();
422+
options.add("-s");
423+
options.add("-v");
424+
options.add("dummy");
425+
count.processOptions(options);
426+
String withSnapshotHeader = " DIR_COUNT FILE_COUNT CONTENT_SIZE "
427+
+ " SNAPSHOT_LENGTH SNAPSHOT_FILE_COUNT "
428+
+ " SNAPSHOT_DIR_COUNT SNAPSHOT_SPACE_CONSUMED PATHNAME";
429+
verify(out).println(withSnapshotHeader);
430+
verifyNoMoreInteractions(out);
431+
}
432+
414433
@Test
415434
public void getCommandName() {
416435
Count count = new Count();
@@ -448,7 +467,8 @@ public void getUsage() {
448467
Count count = new Count();
449468
String actual = count.getUsage();
450469
String expected =
451-
"-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] [-e] <path> ...";
470+
"-count [-q] [-h] [-v] [-t [<storage type>]]"
471+
+ " [-u] [-x] [-e] [-s] <path> ...";
452472
assertEquals("Count.getUsage", expected, actual);
453473
}
454474

@@ -480,7 +500,8 @@ public void getDescription() {
480500
+ "storage types.\n"
481501
+ "The -u option shows the quota and \n"
482502
+ "the usage against the quota without the detailed content summary."
483-
+ "The -e option shows the erasure coding policy.";
503+
+ "The -e option shows the erasure coding policy."
504+
+ "The -s option shows snapshot counts.";
484505

485506
assertEquals("Count.getDescription", expected, actual);
486507
}

hadoop-common-project/hadoop-common/src/test/resources/testConf.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@
282282
<comparators>
283283
<comparator>
284284
<type>RegexpComparator</type>
285-
<expected-output>^-count \[-q\] \[-h\] \[-v\] \[-t \[&lt;storage type&gt;\]\] \[-u\] \[-x\] \[-e\] &lt;path&gt; \.\.\. :( )*</expected-output>
285+
<expected-output>^-count \[-q\] \[-h\] \[-v\] \[-t \[&lt;storage type&gt;\]\] \[-u\] \[-x\] \[-e\] \[-s\] &lt;path&gt; \.\.\. :( )*</expected-output>
286286
</comparator>
287287
<comparator>
288288
<type>RegexpComparator</type>

0 commit comments

Comments
 (0)