Skip to content

Commit 509b10d

Browse files
authored
HADOOP-19650. [ABFS] Fixing NPE when close() called on uninitialized AzureBlobFileSystem (#7880) (#7889)
Contributed by Anuj Modi
1 parent c6ed605 commit 509b10d

File tree

3 files changed

+160
-34
lines changed

3 files changed

+160
-34
lines changed

hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/AzureBlobFileSystem.java

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
import static org.apache.hadoop.fs.azurebfs.constants.FileSystemConfigurations.DATA_BLOCKS_BUFFER_DEFAULT;
132132
import static org.apache.hadoop.fs.azurebfs.constants.InternalConstants.CAPABILITY_SAFE_READAHEAD;
133133
import static org.apache.hadoop.fs.azurebfs.services.AbfsErrors.ERR_CREATE_ON_ROOT;
134+
import static org.apache.hadoop.fs.azurebfs.services.AbfsErrors.ERR_INVALID_ABFS_STATE;
134135
import static org.apache.hadoop.fs.azurebfs.services.AbfsErrors.UNAUTHORIZED_SAS;
135136
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
136137
import static org.apache.hadoop.fs.statistics.IOStatisticsLogging.logIOStatisticsAtLevel;
@@ -148,7 +149,11 @@ public class AzureBlobFileSystem extends FileSystem
148149
private URI uri;
149150
private Path workingDir;
150151
private AzureBlobFileSystemStore abfsStore;
151-
private boolean isClosed;
152+
153+
/**
154+
* Flag to indicate whether the file system is closed or not initiated.
155+
*/
156+
private boolean isClosed = true;
152157
private final String fileSystemId = UUID.randomUUID().toString();
153158

154159
private boolean delegationTokenEnabled = false;
@@ -312,6 +317,7 @@ public void initialize(URI uri, Configuration configuration)
312317
}
313318

314319
rateLimiting = RateLimitingFactory.create(abfsConfiguration.getRateLimit());
320+
isClosed = false;
315321
LOG.debug("Initializing AzureBlobFileSystem for {} complete", uri);
316322
}
317323

@@ -329,8 +335,8 @@ public String toString() {
329335
final StringBuilder sb = new StringBuilder(
330336
"AzureBlobFileSystem{");
331337
sb.append("uri=").append(fullPathUri);
332-
sb.append(", user='").append(abfsStore.getUser()).append('\'');
333-
sb.append(", primaryUserGroup='").append(abfsStore.getPrimaryGroup()).append('\'');
338+
sb.append(", user='").append(getAbfsStore().getUser()).append('\'');
339+
sb.append(", primaryUserGroup='").append(getAbfsStore().getPrimaryGroup()).append('\'');
334340
sb.append("[" + CAPABILITY_SAFE_READAHEAD + "]");
335341
sb.append('}');
336342
return sb.toString();
@@ -354,7 +360,7 @@ public FSDataInputStream open(final Path path, final int bufferSize) throws IOEx
354360
// bufferSize is unused.
355361
LOG.debug(
356362
"AzureBlobFileSystem.open path: {} bufferSize as configured in 'fs.azure.read.request.size': {}",
357-
path, abfsStore.getAbfsConfiguration().getReadBufferSize());
363+
path, getAbfsStore().getAbfsConfiguration().getReadBufferSize());
358364
return open(path, Optional.empty());
359365
}
360366

@@ -517,7 +523,7 @@ public FSDataOutputStream append(final Path f, final int bufferSize, final Progr
517523
TracingContext tracingContext = new TracingContext(clientCorrelationId,
518524
fileSystemId, FSOperationType.APPEND, tracingHeaderFormat,
519525
listener);
520-
OutputStream outputStream = abfsStore
526+
OutputStream outputStream = getAbfsStore()
521527
.openFileForWrite(qualifiedPath, statistics, false, tracingContext);
522528
return new FSDataOutputStream(outputStream, statistics);
523529
} catch (AzureBlobFileSystemException ex) {
@@ -782,7 +788,7 @@ public boolean mkdirs(final Path f, final FsPermission permission) throws IOExce
782788
TracingContext tracingContext = new TracingContext(clientCorrelationId,
783789
fileSystemId, FSOperationType.MKDIR, false, tracingHeaderFormat,
784790
listener);
785-
abfsStore.createDirectory(qualifiedPath,
791+
getAbfsStore().createDirectory(qualifiedPath,
786792
permission == null ? FsPermission.getDirDefault() : permission,
787793
FsPermission.getUMask(getConf()), tracingContext);
788794
statIncrement(DIRECTORIES_CREATED);
@@ -795,10 +801,10 @@ public boolean mkdirs(final Path f, final FsPermission permission) throws IOExce
795801

796802
@Override
797803
public synchronized void close() throws IOException {
798-
if (isClosed) {
804+
if (isClosed()) {
799805
return;
800806
}
801-
if (abfsStore.getClient().isMetricCollectionEnabled()) {
807+
if (getAbfsStore().getClient().isMetricCollectionEnabled()) {
802808
TracingContext tracingMetricContext = new TracingContext(
803809
clientCorrelationId,
804810
fileSystemId, FSOperationType.GET_ATTR, true,
@@ -819,7 +825,7 @@ public synchronized void close() throws IOException {
819825
IOSTATISTICS_LOGGING_LEVEL_DEFAULT);
820826
logIOStatisticsAtLevel(LOG, iostatisticsLoggingLevel, getIOStatistics());
821827
}
822-
IOUtils.cleanupWithLogger(LOG, abfsStore, delegationTokenManager,
828+
IOUtils.cleanupWithLogger(LOG, getAbfsStore(), delegationTokenManager,
823829
getAbfsClient());
824830
this.isClosed = true;
825831
if (LOG.isDebugEnabled()) {
@@ -866,7 +872,7 @@ public void breakLease(final Path f) throws IOException {
866872
TracingContext tracingContext = new TracingContext(clientCorrelationId,
867873
fileSystemId, FSOperationType.BREAK_LEASE, tracingHeaderFormat,
868874
listener);
869-
abfsStore.breakLease(qualifiedPath, tracingContext);
875+
getAbfsStore().breakLease(qualifiedPath, tracingContext);
870876
} catch (AzureBlobFileSystemException ex) {
871877
checkException(f, ex);
872878
}
@@ -884,6 +890,8 @@ public void breakLease(final Path f) throws IOException {
884890
*/
885891
@Override
886892
public Path makeQualified(Path path) {
893+
// Every API works on qualified paths. If store is null better to fail early.
894+
Preconditions.checkState(getAbfsStore() != null);
887895
// To support format: abfs://{dfs.nameservices}/file/path,
888896
// path need to be first converted to URI, then get the raw path string,
889897
// during which {dfs.nameservices} will be omitted.
@@ -917,7 +925,7 @@ public String getScheme() {
917925
public Path getHomeDirectory() {
918926
return makeQualified(new Path(
919927
FileSystemConfigurations.USER_HOME_DIRECTORY_PREFIX
920-
+ "/" + abfsStore.getUser()));
928+
+ "/" + getAbfsStore().getUser()));
921929
}
922930

923931
/**
@@ -939,7 +947,7 @@ public BlockLocation[] getFileBlockLocations(FileStatus file,
939947
if (file.getLen() < start) {
940948
return new BlockLocation[0];
941949
}
942-
final String blobLocationHost = abfsStore.getAbfsConfiguration().getAzureBlockLocationHost();
950+
final String blobLocationHost = getAbfsStore().getAbfsConfiguration().getAzureBlockLocationHost();
943951

944952
final String[] name = {blobLocationHost};
945953
final String[] host = {blobLocationHost};
@@ -973,15 +981,15 @@ protected void finalize() throws Throwable {
973981
* @return the short name of the user who instantiated the FS
974982
*/
975983
public String getOwnerUser() {
976-
return abfsStore.getUser();
984+
return getAbfsStore().getUser();
977985
}
978986

979987
/**
980988
* Get the group name of the owner of the FS.
981989
* @return primary group name
982990
*/
983991
public String getOwnerUserPrimaryGroup() {
984-
return abfsStore.getPrimaryGroup();
992+
return getAbfsStore().getPrimaryGroup();
985993
}
986994

987995
private boolean deleteRoot() throws IOException {
@@ -1053,7 +1061,7 @@ public void setOwner(final Path path, final String owner, final String group)
10531061
Path qualifiedPath = makeQualified(path);
10541062

10551063
try {
1056-
abfsStore.setOwner(qualifiedPath,
1064+
getAbfsStore().setOwner(qualifiedPath,
10571065
owner,
10581066
group,
10591067
tracingContext);
@@ -1090,15 +1098,15 @@ public void setXAttr(final Path path,
10901098
TracingContext tracingContext = new TracingContext(clientCorrelationId,
10911099
fileSystemId, FSOperationType.SET_ATTR, true, tracingHeaderFormat,
10921100
listener);
1093-
Hashtable<String, String> properties = abfsStore
1101+
Hashtable<String, String> properties = getAbfsStore()
10941102
.getPathStatus(qualifiedPath, tracingContext);
10951103
String xAttrName = ensureValidAttributeName(name);
10961104
boolean xAttrExists = properties.containsKey(xAttrName);
10971105
XAttrSetFlag.validate(name, xAttrExists, flag);
10981106

1099-
String xAttrValue = abfsStore.decodeAttribute(value);
1107+
String xAttrValue = getAbfsStore().decodeAttribute(value);
11001108
properties.put(xAttrName, xAttrValue);
1101-
abfsStore.setPathProperties(qualifiedPath, properties, tracingContext);
1109+
getAbfsStore().setPathProperties(qualifiedPath, properties, tracingContext);
11021110
} catch (AzureBlobFileSystemException ex) {
11031111
checkException(path, ex);
11041112
}
@@ -1130,12 +1138,12 @@ public byte[] getXAttr(final Path path, final String name)
11301138
TracingContext tracingContext = new TracingContext(clientCorrelationId,
11311139
fileSystemId, FSOperationType.GET_ATTR, true, tracingHeaderFormat,
11321140
listener);
1133-
Hashtable<String, String> properties = abfsStore
1141+
Hashtable<String, String> properties = getAbfsStore()
11341142
.getPathStatus(qualifiedPath, tracingContext);
11351143
String xAttrName = ensureValidAttributeName(name);
11361144
if (properties.containsKey(xAttrName)) {
11371145
String xAttrValue = properties.get(xAttrName);
1138-
value = abfsStore.encodeAttribute(xAttrValue);
1146+
value = getAbfsStore().encodeAttribute(xAttrValue);
11391147
}
11401148
} catch (AzureBlobFileSystemException ex) {
11411149
checkException(path, ex);
@@ -1173,7 +1181,7 @@ public void setPermission(final Path path, final FsPermission permission)
11731181
Path qualifiedPath = makeQualified(path);
11741182

11751183
try {
1176-
abfsStore.setPermission(qualifiedPath, permission, tracingContext);
1184+
getAbfsStore().setPermission(qualifiedPath, permission, tracingContext);
11771185
} catch (AzureBlobFileSystemException ex) {
11781186
checkException(path, ex);
11791187
}
@@ -1210,7 +1218,7 @@ public void modifyAclEntries(final Path path, final List<AclEntry> aclSpec)
12101218
Path qualifiedPath = makeQualified(path);
12111219

12121220
try {
1213-
abfsStore.modifyAclEntries(qualifiedPath, aclSpec, tracingContext);
1221+
getAbfsStore().modifyAclEntries(qualifiedPath, aclSpec, tracingContext);
12141222
} catch (AzureBlobFileSystemException ex) {
12151223
checkException(path, ex);
12161224
}
@@ -1245,7 +1253,7 @@ public void removeAclEntries(final Path path, final List<AclEntry> aclSpec)
12451253
Path qualifiedPath = makeQualified(path);
12461254

12471255
try {
1248-
abfsStore.removeAclEntries(qualifiedPath, aclSpec, tracingContext);
1256+
getAbfsStore().removeAclEntries(qualifiedPath, aclSpec, tracingContext);
12491257
} catch (AzureBlobFileSystemException ex) {
12501258
checkException(path, ex);
12511259
}
@@ -1273,7 +1281,7 @@ public void removeDefaultAcl(final Path path) throws IOException {
12731281
Path qualifiedPath = makeQualified(path);
12741282

12751283
try {
1276-
abfsStore.removeDefaultAcl(qualifiedPath, tracingContext);
1284+
getAbfsStore().removeDefaultAcl(qualifiedPath, tracingContext);
12771285
} catch (AzureBlobFileSystemException ex) {
12781286
checkException(path, ex);
12791287
}
@@ -1303,7 +1311,7 @@ public void removeAcl(final Path path) throws IOException {
13031311
Path qualifiedPath = makeQualified(path);
13041312

13051313
try {
1306-
abfsStore.removeAcl(qualifiedPath, tracingContext);
1314+
getAbfsStore().removeAcl(qualifiedPath, tracingContext);
13071315
} catch (AzureBlobFileSystemException ex) {
13081316
checkException(path, ex);
13091317
}
@@ -1340,7 +1348,7 @@ public void setAcl(final Path path, final List<AclEntry> aclSpec)
13401348
Path qualifiedPath = makeQualified(path);
13411349

13421350
try {
1343-
abfsStore.setAcl(qualifiedPath, aclSpec, tracingContext);
1351+
getAbfsStore().setAcl(qualifiedPath, aclSpec, tracingContext);
13441352
} catch (AzureBlobFileSystemException ex) {
13451353
checkException(path, ex);
13461354
}
@@ -1368,7 +1376,7 @@ public AclStatus getAclStatus(final Path path) throws IOException {
13681376
Path qualifiedPath = makeQualified(path);
13691377

13701378
try {
1371-
return abfsStore.getAclStatus(qualifiedPath, tracingContext);
1379+
return getAbfsStore().getAclStatus(qualifiedPath, tracingContext);
13721380
} catch (AzureBlobFileSystemException ex) {
13731381
checkException(path, ex);
13741382
return null;
@@ -1395,7 +1403,7 @@ public void access(final Path path, final FsAction mode) throws IOException {
13951403
TracingContext tracingContext = new TracingContext(clientCorrelationId,
13961404
fileSystemId, FSOperationType.ACCESS, tracingHeaderFormat,
13971405
listener);
1398-
this.abfsStore.access(qualifiedPath, mode, tracingContext);
1406+
this.getAbfsStore().access(qualifiedPath, mode, tracingContext);
13991407
} catch (AzureBlobFileSystemException ex) {
14001408
checkCheckAccessException(path, ex);
14011409
}
@@ -1417,11 +1425,11 @@ public boolean exists(Path f) throws IOException {
14171425
public RemoteIterator<FileStatus> listStatusIterator(Path path)
14181426
throws IOException {
14191427
LOG.debug("AzureBlobFileSystem.listStatusIterator path : {}", path);
1420-
if (abfsStore.getAbfsConfiguration().enableAbfsListIterator()) {
1428+
if (getAbfsStore().getAbfsConfiguration().enableAbfsListIterator()) {
14211429
TracingContext tracingContext = new TracingContext(clientCorrelationId,
14221430
fileSystemId, FSOperationType.LISTSTATUS, true, tracingHeaderFormat, listener);
14231431
AbfsListStatusRemoteIterator abfsLsItr =
1424-
new AbfsListStatusRemoteIterator(path, abfsStore,
1432+
new AbfsListStatusRemoteIterator(path, getAbfsStore(),
14251433
tracingContext);
14261434
return RemoteIterators.typeCastingRemoteIterator(abfsLsItr);
14271435
} else {
@@ -1503,7 +1511,7 @@ private boolean fileSystemExists() throws IOException {
15031511
try {
15041512
TracingContext tracingContext = new TracingContext(clientCorrelationId,
15051513
fileSystemId, FSOperationType.TEST_OP, tracingHeaderFormat, listener);
1506-
abfsStore.getFilesystemProperties(tracingContext);
1514+
getAbfsStore().getFilesystemProperties(tracingContext);
15071515
} catch (AzureBlobFileSystemException ex) {
15081516
try {
15091517
checkException(null, ex);
@@ -1522,7 +1530,7 @@ private void createFileSystem(TracingContext tracingContext) throws IOException
15221530
LOG.debug(
15231531
"AzureBlobFileSystem.createFileSystem uri: {}", uri);
15241532
try {
1525-
abfsStore.createFilesystem(tracingContext);
1533+
getAbfsStore().createFilesystem(tracingContext);
15261534
} catch (AzureBlobFileSystemException ex) {
15271535
checkException(null, ex);
15281536
}
@@ -1745,14 +1753,21 @@ public boolean failed() {
17451753

17461754
@VisibleForTesting
17471755
public AzureBlobFileSystemStore getAbfsStore() {
1756+
if (abfsStore == null) {
1757+
throw new IllegalStateException(ERR_INVALID_ABFS_STATE);
1758+
}
17481759
return abfsStore;
17491760
}
17501761

17511762
@VisibleForTesting
17521763
AbfsClient getAbfsClient() {
1753-
return abfsStore.getClient();
1764+
return getAbfsStore().getClient();
17541765
}
17551766

1767+
@VisibleForTesting
1768+
boolean isClosed() {
1769+
return isClosed;
1770+
}
17561771
/**
17571772
* Get any Delegation Token manager created by the filesystem.
17581773
* @return the DT manager or null.

hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsErrors.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,6 @@ public final class AbfsErrors {
7777
public static final String ERR_BLOB_LIST_PARSING = "Parsing of XML List Response Failed in BlobClient.";
7878
public static final String ERR_DFS_LIST_PARSING = "Parsing of Json List Response Failed in DfsClient.";
7979
public static final String INCORRECT_INGRESS_TYPE = "Ingress Type Cannot be DFS for Blob endpoint configured filesystem.";
80+
public static final String ERR_INVALID_ABFS_STATE = "Invalid state for AzureBlobFilesystem. Either Filesystem was closed or not initialized.";
8081
private AbfsErrors() {}
8182
}

0 commit comments

Comments
 (0)