Skip to content

Commit 7fc3676

Browse files
committed
HADOOP-6432. Add Statistics support in FileContext. Contributed by jitendra.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1066282 13f79535-47bb-0310-9956-ffa450edef68
1 parent da8a319 commit 7fc3676

File tree

6 files changed

+264
-18
lines changed

6 files changed

+264
-18
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Trunk (unreleased changes)
44

55
INCOMPATIBLE CHANGES
66

7+
HADOOP-6432. Add Statistics support in FileContext. (jitendra)
8+
79
HADOOP-6904. Support method based RPC compatiblity. (hairong)
810

911
NEW FEATURES

src/java/org/apache/hadoop/fs/AbstractFileSystem.java

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import java.net.URI;
2525
import java.net.URISyntaxException;
2626
import java.util.EnumSet;
27-
import java.util.IdentityHashMap;
27+
import java.util.HashMap;
2828
import java.util.Map;
2929
import java.util.NoSuchElementException;
3030
import java.util.StringTokenizer;
@@ -60,9 +60,8 @@ public abstract class AbstractFileSystem {
6060
static final Log LOG = LogFactory.getLog(AbstractFileSystem.class);
6161

6262
/** Recording statistics per a file system class. */
63-
private static final Map<Class<? extends AbstractFileSystem>, Statistics>
64-
STATISTICS_TABLE =
65-
new IdentityHashMap<Class<? extends AbstractFileSystem>, Statistics>();
63+
private static final Map<URI, Statistics>
64+
STATISTICS_TABLE = new HashMap<URI, Statistics>();
6665

6766
/** Cache of constructors for each file system class. */
6867
private static final Map<Class<?>, Constructor<?>> CONSTRUCTOR_CACHE =
@@ -144,35 +143,68 @@ public static AbstractFileSystem createFileSystem(URI uri, Configuration conf)
144143
}
145144
return (AbstractFileSystem) newInstance(clazz, uri, conf);
146145
}
147-
148-
146+
149147
/**
150148
* Get the statistics for a particular file system.
151-
* @param cls the class to lookup
149+
*
150+
* @param uri
151+
* used as key to lookup STATISTICS_TABLE. Only scheme and authority
152+
* part of the uri are used.
152153
* @return a statistics object
153154
*/
154-
public static synchronized Statistics getStatistics(String scheme,
155-
Class<? extends AbstractFileSystem> cls) {
156-
Statistics result = STATISTICS_TABLE.get(cls);
155+
protected static synchronized Statistics getStatistics(URI uri) {
156+
String scheme = uri.getScheme();
157+
if (scheme == null) {
158+
throw new IllegalArgumentException("Scheme not defined in the uri: "
159+
+ uri);
160+
}
161+
URI baseUri = getBaseUri(uri);
162+
Statistics result = STATISTICS_TABLE.get(baseUri);
157163
if (result == null) {
158164
result = new Statistics(scheme);
159-
STATISTICS_TABLE.put(cls, result);
165+
STATISTICS_TABLE.put(baseUri, result);
160166
}
161167
return result;
162168
}
163169

170+
private static URI getBaseUri(URI uri) {
171+
String scheme = uri.getScheme();
172+
String authority = uri.getAuthority();
173+
String baseUriString = scheme + "://";
174+
if (authority != null) {
175+
baseUriString = baseUriString + authority;
176+
} else {
177+
baseUriString = baseUriString + "/";
178+
}
179+
return URI.create(baseUriString);
180+
}
181+
164182
public static synchronized void clearStatistics() {
165183
for(Statistics stat: STATISTICS_TABLE.values()) {
166184
stat.reset();
167185
}
168186
}
169187

188+
/**
189+
* Prints statistics for all file systems.
190+
*/
170191
public static synchronized void printStatistics() {
171-
for (Map.Entry<Class<? extends AbstractFileSystem>, Statistics> pair:
172-
STATISTICS_TABLE.entrySet()) {
173-
System.out.println(" FileSystem " + pair.getKey().getName() +
174-
": " + pair.getValue());
192+
for (Map.Entry<URI, Statistics> pair : STATISTICS_TABLE.entrySet()) {
193+
System.out.println(" FileSystem " + pair.getKey().getScheme() + "://"
194+
+ pair.getKey().getAuthority() + ": " + pair.getValue());
195+
}
196+
}
197+
198+
protected static synchronized Map<URI, Statistics> getAllStatistics() {
199+
Map<URI, Statistics> statsMap = new HashMap<URI, Statistics>(
200+
STATISTICS_TABLE.size());
201+
for (Map.Entry<URI, Statistics> pair : STATISTICS_TABLE.entrySet()) {
202+
URI key = pair.getKey();
203+
Statistics value = pair.getValue();
204+
Statistics newStatsObj = new Statistics(value);
205+
statsMap.put(URI.create(key.toString()), newStatsObj);
175206
}
207+
return statsMap;
176208
}
177209

178210
/**
@@ -211,7 +243,7 @@ public AbstractFileSystem(final URI uri, final String supportedScheme,
211243
final boolean authorityNeeded, final int defaultPort)
212244
throws URISyntaxException {
213245
myUri = getUri(uri, supportedScheme, authorityNeeded, defaultPort);
214-
statistics = getStatistics(supportedScheme, getClass());
246+
statistics = getStatistics(uri);
215247
}
216248

217249
/**

src/java/org/apache/hadoop/fs/FileContext.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.apache.hadoop.classification.InterfaceAudience;
4040
import org.apache.hadoop.classification.InterfaceStability;
4141
import org.apache.hadoop.conf.Configuration;
42+
import org.apache.hadoop.fs.FileSystem.Statistics;
4243
import org.apache.hadoop.fs.Options.CreateOpts;
4344
import org.apache.hadoop.fs.Options.Rename;
4445
import org.apache.hadoop.fs.permission.FsPermission;
@@ -768,8 +769,8 @@ public Boolean next(final AbstractFileSystem fs, final Path p)
768769
*
769770
* @throws AccessControlException If access is denied
770771
* @throws FileAlreadyExistsException If <code>dst</code> already exists and
771-
* <code>options</options> has {@link Rename#OVERWRITE} option
772-
* false.
772+
* <code>options</options> has {@link Options.Rename#OVERWRITE}
773+
* option false.
773774
* @throws FileNotFoundException If <code>src</code> does not exist
774775
* @throws ParentNotDirectoryException If parent of <code>dst</code> is not a
775776
* directory
@@ -2226,4 +2227,40 @@ public T resolve(final FileContext fc, Path p) throws IOException {
22262227
return in;
22272228
}
22282229
}
2230+
2231+
/**
2232+
* Get the statistics for a particular file system
2233+
*
2234+
* @param uri
2235+
* the uri to lookup the statistics. Only scheme and authority part
2236+
* of the uri are used as the key to store and lookup.
2237+
* @return a statistics object
2238+
*/
2239+
public static Statistics getStatistics(URI uri) {
2240+
return AbstractFileSystem.getStatistics(uri);
2241+
}
2242+
2243+
/**
2244+
* Clears all the statistics stored in AbstractFileSystem, for all the file
2245+
* systems.
2246+
*/
2247+
public static void clearStatistics() {
2248+
AbstractFileSystem.clearStatistics();
2249+
}
2250+
2251+
/**
2252+
* Prints the statistics to standard output. File System is identified by the
2253+
* scheme and authority.
2254+
*/
2255+
public static void printStatistics() {
2256+
AbstractFileSystem.printStatistics();
2257+
}
2258+
2259+
/**
2260+
* @return Map of uri and statistics for each filesystem instantiated. The uri
2261+
* consists of scheme and authority for the filesystem.
2262+
*/
2263+
public static Map<URI, Statistics> getAllStatistics() {
2264+
return AbstractFileSystem.getAllStatistics();
2265+
}
22292266
}

src/java/org/apache/hadoop/fs/FileSystem.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,18 @@ public Statistics(String scheme) {
20072007
this.scheme = scheme;
20082008
}
20092009

2010+
/**
2011+
* Copy constructor.
2012+
*
2013+
* @param st
2014+
* The input Statistics object which is cloned.
2015+
*/
2016+
public Statistics(Statistics st) {
2017+
this.scheme = st.scheme;
2018+
this.bytesRead = new AtomicLong(st.bytesRead.longValue());
2019+
this.bytesWritten = new AtomicLong(st.bytesWritten.longValue());
2020+
}
2021+
20102022
/**
20112023
* Increment the bytes read in the statistics
20122024
* @param newBytes the additional bytes read
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.fs;
20+
21+
import java.io.IOException;
22+
import java.net.URI;
23+
import java.net.URISyntaxException;
24+
import java.util.Map;
25+
26+
import org.apache.hadoop.fs.FileSystem.Statistics;
27+
import org.junit.Assert;
28+
import org.junit.Test;
29+
30+
import static org.apache.hadoop.fs.FileContextTestHelper.*;
31+
32+
/**
33+
* <p>
34+
* Base class to test {@link FileContext} Statistics.
35+
* </p>
36+
*/
37+
public abstract class FCStatisticsBaseTest {
38+
39+
static protected int blockSize = 512;
40+
static protected int numBlocks = 1;
41+
42+
//fc should be set appropriately by the deriving test.
43+
protected static FileContext fc = null;
44+
45+
@Test
46+
public void testStatistics() throws IOException, URISyntaxException {
47+
URI fsUri = getFsUri();
48+
Statistics stats = FileContext.getStatistics(fsUri);
49+
Assert.assertEquals(0, stats.getBytesRead());
50+
Path filePath = getTestRootPath(fc, "file1");
51+
createFile(fc, filePath, numBlocks, blockSize);
52+
53+
Assert.assertEquals(0, stats.getBytesRead());
54+
verifyWrittenBytes(stats);
55+
FSDataInputStream fstr = fc.open(filePath);
56+
byte[] buf = new byte[blockSize];
57+
int bytesRead = fstr.read(buf, 0, blockSize);
58+
Assert.assertEquals(blockSize, bytesRead);
59+
verifyReadBytes(stats);
60+
verifyWrittenBytes(stats);
61+
verifyReadBytes(FileContext.getStatistics(getFsUri()));
62+
Map<URI, Statistics> statsMap = FileContext.getAllStatistics();
63+
URI exactUri = getSchemeAuthorityUri();
64+
verifyWrittenBytes(statsMap.get(exactUri));
65+
fc.delete(filePath, true);
66+
}
67+
68+
/**
69+
* Bytes read may be different for different file systems. This method should
70+
* throw assertion error if bytes read are incorrect.
71+
*
72+
* @param stats
73+
*/
74+
protected abstract void verifyReadBytes(Statistics stats);
75+
76+
/**
77+
* Bytes written may be different for different file systems. This method should
78+
* throw assertion error if bytes written are incorrect.
79+
*
80+
* @param stats
81+
*/
82+
protected abstract void verifyWrittenBytes(Statistics stats);
83+
84+
/**
85+
* Returns the filesystem uri. Should be set
86+
* @return URI
87+
*/
88+
protected abstract URI getFsUri();
89+
90+
protected URI getSchemeAuthorityUri() {
91+
URI uri = getFsUri();
92+
String SchemeAuthString = uri.getScheme() + "://";
93+
if (uri.getAuthority() == null) {
94+
SchemeAuthString += "/";
95+
} else {
96+
SchemeAuthString += uri.getAuthority();
97+
}
98+
return URI.create(SchemeAuthString);
99+
}
100+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.fs;
20+
21+
import java.net.URI;
22+
23+
import org.apache.hadoop.fs.FileSystem.Statistics;
24+
import org.junit.After;
25+
import org.junit.Assert;
26+
import org.junit.Before;
27+
28+
import static org.apache.hadoop.fs.FileContextTestHelper.*;
29+
30+
/**
31+
* <p>
32+
* Tests the File Context Statistics for {@link LocalFileSystem}
33+
* </p>
34+
*/
35+
public class TestLocalFsFCStatistics extends FCStatisticsBaseTest {
36+
37+
static final String LOCAL_FS_ROOT_URI = "file:///tmp/test";
38+
39+
@Before
40+
public void setUp() throws Exception {
41+
fc = FileContext.getLocalFSFileContext();
42+
fc.mkdir(getTestRootPath(fc, "test"), FileContext.DEFAULT_PERM, true);
43+
}
44+
45+
@After
46+
public void tearDown() throws Exception {
47+
fc.delete(getTestRootPath(fc, "test"), true);
48+
}
49+
50+
protected void verifyReadBytes(Statistics stats) {
51+
Assert.assertEquals(blockSize, stats.getBytesRead());
52+
}
53+
54+
protected void verifyWrittenBytes(Statistics stats) {
55+
//Extra 12 bytes are written apart from the block.
56+
Assert.assertEquals(blockSize + 12, stats.getBytesWritten());
57+
}
58+
59+
protected URI getFsUri() {
60+
return URI.create(LOCAL_FS_ROOT_URI);
61+
}
62+
63+
}

0 commit comments

Comments
 (0)