Skip to content

Commit 8d42a37

Browse files
authored
HADOOP-19650. [ABFS] Fixing NPE when close() called on uninitialized AzureBlobFileSystem (#7880) (#7888)
Contributed by Anuj Modi
1 parent 84e8b89 commit 8d42a37

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;
@@ -311,6 +316,7 @@ public void initialize(URI uri, Configuration configuration)
311316
}
312317

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

@@ -328,8 +334,8 @@ public String toString() {
328334
final StringBuilder sb = new StringBuilder(
329335
"AzureBlobFileSystem{");
330336
sb.append("uri=").append(fullPathUri);
331-
sb.append(", user='").append(abfsStore.getUser()).append('\'');
332-
sb.append(", primaryUserGroup='").append(abfsStore.getPrimaryGroup()).append('\'');
337+
sb.append(", user='").append(getAbfsStore().getUser()).append('\'');
338+
sb.append(", primaryUserGroup='").append(getAbfsStore().getPrimaryGroup()).append('\'');
333339
sb.append("[" + CAPABILITY_SAFE_READAHEAD + "]");
334340
sb.append('}');
335341
return sb.toString();
@@ -353,7 +359,7 @@ public FSDataInputStream open(final Path path, final int bufferSize) throws IOEx
353359
// bufferSize is unused.
354360
LOG.debug(
355361
"AzureBlobFileSystem.open path: {} bufferSize as configured in 'fs.azure.read.request.size': {}",
356-
path, abfsStore.getAbfsConfiguration().getReadBufferSize());
362+
path, getAbfsStore().getAbfsConfiguration().getReadBufferSize());
357363
return open(path, Optional.empty());
358364
}
359365

@@ -516,7 +522,7 @@ public FSDataOutputStream append(final Path f, final int bufferSize, final Progr
516522
TracingContext tracingContext = new TracingContext(clientCorrelationId,
517523
fileSystemId, FSOperationType.APPEND, tracingHeaderFormat,
518524
listener);
519-
OutputStream outputStream = abfsStore
525+
OutputStream outputStream = getAbfsStore()
520526
.openFileForWrite(qualifiedPath, statistics, false, tracingContext);
521527
return new FSDataOutputStream(outputStream, statistics);
522528
} catch (AzureBlobFileSystemException ex) {
@@ -781,7 +787,7 @@ public boolean mkdirs(final Path f, final FsPermission permission) throws IOExce
781787
TracingContext tracingContext = new TracingContext(clientCorrelationId,
782788
fileSystemId, FSOperationType.MKDIR, false, tracingHeaderFormat,
783789
listener);
784-
abfsStore.createDirectory(qualifiedPath,
790+
getAbfsStore().createDirectory(qualifiedPath,
785791
permission == null ? FsPermission.getDirDefault() : permission,
786792
FsPermission.getUMask(getConf()), tracingContext);
787793
statIncrement(DIRECTORIES_CREATED);
@@ -794,10 +800,10 @@ public boolean mkdirs(final Path f, final FsPermission permission) throws IOExce
794800

795801
@Override
796802
public synchronized void close() throws IOException {
797-
if (isClosed) {
803+
if (isClosed()) {
798804
return;
799805
}
800-
if (abfsStore.getClient().isMetricCollectionEnabled()) {
806+
if (getAbfsStore().getClient().isMetricCollectionEnabled()) {
801807
TracingContext tracingMetricContext = new TracingContext(
802808
clientCorrelationId,
803809
fileSystemId, FSOperationType.GET_ATTR, true,
@@ -818,7 +824,7 @@ public synchronized void close() throws IOException {
818824
IOSTATISTICS_LOGGING_LEVEL_DEFAULT);
819825
logIOStatisticsAtLevel(LOG, iostatisticsLoggingLevel, getIOStatistics());
820826
}
821-
IOUtils.cleanupWithLogger(LOG, abfsStore, delegationTokenManager,
827+
IOUtils.cleanupWithLogger(LOG, getAbfsStore(), delegationTokenManager,
822828
getAbfsClient());
823829
this.isClosed = true;
824830
if (LOG.isDebugEnabled()) {
@@ -865,7 +871,7 @@ public void breakLease(final Path f) throws IOException {
865871
TracingContext tracingContext = new TracingContext(clientCorrelationId,
866872
fileSystemId, FSOperationType.BREAK_LEASE, tracingHeaderFormat,
867873
listener);
868-
abfsStore.breakLease(qualifiedPath, tracingContext);
874+
getAbfsStore().breakLease(qualifiedPath, tracingContext);
869875
} catch (AzureBlobFileSystemException ex) {
870876
checkException(f, ex);
871877
}
@@ -883,6 +889,8 @@ public void breakLease(final Path f) throws IOException {
883889
*/
884890
@Override
885891
public Path makeQualified(Path path) {
892+
// Every API works on qualified paths. If store is null better to fail early.
893+
Preconditions.checkState(getAbfsStore() != null);
886894
// To support format: abfs://{dfs.nameservices}/file/path,
887895
// path need to be first converted to URI, then get the raw path string,
888896
// during which {dfs.nameservices} will be omitted.
@@ -916,7 +924,7 @@ public String getScheme() {
916924
public Path getHomeDirectory() {
917925
return makeQualified(new Path(
918926
FileSystemConfigurations.USER_HOME_DIRECTORY_PREFIX
919-
+ "/" + abfsStore.getUser()));
927+
+ "/" + getAbfsStore().getUser()));
920928
}
921929

922930
/**
@@ -938,7 +946,7 @@ public BlockLocation[] getFileBlockLocations(FileStatus file,
938946
if (file.getLen() < start) {
939947
return new BlockLocation[0];
940948
}
941-
final String blobLocationHost = abfsStore.getAbfsConfiguration().getAzureBlockLocationHost();
949+
final String blobLocationHost = getAbfsStore().getAbfsConfiguration().getAzureBlockLocationHost();
942950

943951
final String[] name = {blobLocationHost};
944952
final String[] host = {blobLocationHost};
@@ -972,15 +980,15 @@ protected void finalize() throws Throwable {
972980
* @return the short name of the user who instantiated the FS
973981
*/
974982
public String getOwnerUser() {
975-
return abfsStore.getUser();
983+
return getAbfsStore().getUser();
976984
}
977985

978986
/**
979987
* Get the group name of the owner of the FS.
980988
* @return primary group name
981989
*/
982990
public String getOwnerUserPrimaryGroup() {
983-
return abfsStore.getPrimaryGroup();
991+
return getAbfsStore().getPrimaryGroup();
984992
}
985993

986994
private boolean deleteRoot() throws IOException {
@@ -1052,7 +1060,7 @@ public void setOwner(final Path path, final String owner, final String group)
10521060
Path qualifiedPath = makeQualified(path);
10531061

10541062
try {
1055-
abfsStore.setOwner(qualifiedPath,
1063+
getAbfsStore().setOwner(qualifiedPath,
10561064
owner,
10571065
group,
10581066
tracingContext);
@@ -1089,15 +1097,15 @@ public void setXAttr(final Path path,
10891097
TracingContext tracingContext = new TracingContext(clientCorrelationId,
10901098
fileSystemId, FSOperationType.SET_ATTR, true, tracingHeaderFormat,
10911099
listener);
1092-
Hashtable<String, String> properties = abfsStore
1100+
Hashtable<String, String> properties = getAbfsStore()
10931101
.getPathStatus(qualifiedPath, tracingContext);
10941102
String xAttrName = ensureValidAttributeName(name);
10951103
boolean xAttrExists = properties.containsKey(xAttrName);
10961104
XAttrSetFlag.validate(name, xAttrExists, flag);
10971105

1098-
String xAttrValue = abfsStore.decodeAttribute(value);
1106+
String xAttrValue = getAbfsStore().decodeAttribute(value);
10991107
properties.put(xAttrName, xAttrValue);
1100-
abfsStore.setPathProperties(qualifiedPath, properties, tracingContext);
1108+
getAbfsStore().setPathProperties(qualifiedPath, properties, tracingContext);
11011109
} catch (AzureBlobFileSystemException ex) {
11021110
checkException(path, ex);
11031111
}
@@ -1129,12 +1137,12 @@ public byte[] getXAttr(final Path path, final String name)
11291137
TracingContext tracingContext = new TracingContext(clientCorrelationId,
11301138
fileSystemId, FSOperationType.GET_ATTR, true, tracingHeaderFormat,
11311139
listener);
1132-
Hashtable<String, String> properties = abfsStore
1140+
Hashtable<String, String> properties = getAbfsStore()
11331141
.getPathStatus(qualifiedPath, tracingContext);
11341142
String xAttrName = ensureValidAttributeName(name);
11351143
if (properties.containsKey(xAttrName)) {
11361144
String xAttrValue = properties.get(xAttrName);
1137-
value = abfsStore.encodeAttribute(xAttrValue);
1145+
value = getAbfsStore().encodeAttribute(xAttrValue);
11381146
}
11391147
} catch (AzureBlobFileSystemException ex) {
11401148
checkException(path, ex);
@@ -1172,7 +1180,7 @@ public void setPermission(final Path path, final FsPermission permission)
11721180
Path qualifiedPath = makeQualified(path);
11731181

11741182
try {
1175-
abfsStore.setPermission(qualifiedPath, permission, tracingContext);
1183+
getAbfsStore().setPermission(qualifiedPath, permission, tracingContext);
11761184
} catch (AzureBlobFileSystemException ex) {
11771185
checkException(path, ex);
11781186
}
@@ -1209,7 +1217,7 @@ public void modifyAclEntries(final Path path, final List<AclEntry> aclSpec)
12091217
Path qualifiedPath = makeQualified(path);
12101218

12111219
try {
1212-
abfsStore.modifyAclEntries(qualifiedPath, aclSpec, tracingContext);
1220+
getAbfsStore().modifyAclEntries(qualifiedPath, aclSpec, tracingContext);
12131221
} catch (AzureBlobFileSystemException ex) {
12141222
checkException(path, ex);
12151223
}
@@ -1244,7 +1252,7 @@ public void removeAclEntries(final Path path, final List<AclEntry> aclSpec)
12441252
Path qualifiedPath = makeQualified(path);
12451253

12461254
try {
1247-
abfsStore.removeAclEntries(qualifiedPath, aclSpec, tracingContext);
1255+
getAbfsStore().removeAclEntries(qualifiedPath, aclSpec, tracingContext);
12481256
} catch (AzureBlobFileSystemException ex) {
12491257
checkException(path, ex);
12501258
}
@@ -1272,7 +1280,7 @@ public void removeDefaultAcl(final Path path) throws IOException {
12721280
Path qualifiedPath = makeQualified(path);
12731281

12741282
try {
1275-
abfsStore.removeDefaultAcl(qualifiedPath, tracingContext);
1283+
getAbfsStore().removeDefaultAcl(qualifiedPath, tracingContext);
12761284
} catch (AzureBlobFileSystemException ex) {
12771285
checkException(path, ex);
12781286
}
@@ -1302,7 +1310,7 @@ public void removeAcl(final Path path) throws IOException {
13021310
Path qualifiedPath = makeQualified(path);
13031311

13041312
try {
1305-
abfsStore.removeAcl(qualifiedPath, tracingContext);
1313+
getAbfsStore().removeAcl(qualifiedPath, tracingContext);
13061314
} catch (AzureBlobFileSystemException ex) {
13071315
checkException(path, ex);
13081316
}
@@ -1339,7 +1347,7 @@ public void setAcl(final Path path, final List<AclEntry> aclSpec)
13391347
Path qualifiedPath = makeQualified(path);
13401348

13411349
try {
1342-
abfsStore.setAcl(qualifiedPath, aclSpec, tracingContext);
1350+
getAbfsStore().setAcl(qualifiedPath, aclSpec, tracingContext);
13431351
} catch (AzureBlobFileSystemException ex) {
13441352
checkException(path, ex);
13451353
}
@@ -1367,7 +1375,7 @@ public AclStatus getAclStatus(final Path path) throws IOException {
13671375
Path qualifiedPath = makeQualified(path);
13681376

13691377
try {
1370-
return abfsStore.getAclStatus(qualifiedPath, tracingContext);
1378+
return getAbfsStore().getAclStatus(qualifiedPath, tracingContext);
13711379
} catch (AzureBlobFileSystemException ex) {
13721380
checkException(path, ex);
13731381
return null;
@@ -1394,7 +1402,7 @@ public void access(final Path path, final FsAction mode) throws IOException {
13941402
TracingContext tracingContext = new TracingContext(clientCorrelationId,
13951403
fileSystemId, FSOperationType.ACCESS, tracingHeaderFormat,
13961404
listener);
1397-
this.abfsStore.access(qualifiedPath, mode, tracingContext);
1405+
this.getAbfsStore().access(qualifiedPath, mode, tracingContext);
13981406
} catch (AzureBlobFileSystemException ex) {
13991407
checkCheckAccessException(path, ex);
14001408
}
@@ -1416,11 +1424,11 @@ public boolean exists(Path f) throws IOException {
14161424
public RemoteIterator<FileStatus> listStatusIterator(Path path)
14171425
throws IOException {
14181426
LOG.debug("AzureBlobFileSystem.listStatusIterator path : {}", path);
1419-
if (abfsStore.getAbfsConfiguration().enableAbfsListIterator()) {
1427+
if (getAbfsStore().getAbfsConfiguration().enableAbfsListIterator()) {
14201428
TracingContext tracingContext = new TracingContext(clientCorrelationId,
14211429
fileSystemId, FSOperationType.LISTSTATUS, true, tracingHeaderFormat, listener);
14221430
AbfsListStatusRemoteIterator abfsLsItr =
1423-
new AbfsListStatusRemoteIterator(path, abfsStore,
1431+
new AbfsListStatusRemoteIterator(path, getAbfsStore(),
14241432
tracingContext);
14251433
return RemoteIterators.typeCastingRemoteIterator(abfsLsItr);
14261434
} else {
@@ -1502,7 +1510,7 @@ private boolean fileSystemExists() throws IOException {
15021510
try {
15031511
TracingContext tracingContext = new TracingContext(clientCorrelationId,
15041512
fileSystemId, FSOperationType.TEST_OP, tracingHeaderFormat, listener);
1505-
abfsStore.getFilesystemProperties(tracingContext);
1513+
getAbfsStore().getFilesystemProperties(tracingContext);
15061514
} catch (AzureBlobFileSystemException ex) {
15071515
try {
15081516
checkException(null, ex);
@@ -1521,7 +1529,7 @@ private void createFileSystem(TracingContext tracingContext) throws IOException
15211529
LOG.debug(
15221530
"AzureBlobFileSystem.createFileSystem uri: {}", uri);
15231531
try {
1524-
abfsStore.createFilesystem(tracingContext);
1532+
getAbfsStore().createFilesystem(tracingContext);
15251533
} catch (AzureBlobFileSystemException ex) {
15261534
checkException(null, ex);
15271535
}
@@ -1744,14 +1752,21 @@ public boolean failed() {
17441752

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

17501761
@VisibleForTesting
17511762
AbfsClient getAbfsClient() {
1752-
return abfsStore.getClient();
1763+
return getAbfsStore().getClient();
17531764
}
17541765

1766+
@VisibleForTesting
1767+
boolean isClosed() {
1768+
return isClosed;
1769+
}
17551770
/**
17561771
* Get any Delegation Token manager created by the filesystem.
17571772
* @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)