Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDDS-11697. Integrate Ozone Filesystem Implementation with Ozone ListStatusLight API #7440

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -985,8 +985,23 @@ public OzoneDataStreamOutput createStreamFile(String keyName, long size,
*/
public List<OzoneFileStatus> listStatus(String keyName, boolean recursive,
String startKey, long numEntries) throws IOException {
return proxy
.listStatus(volumeName, name, keyName, recursive, startKey, numEntries);
return proxy.listStatus(volumeName, name, keyName, recursive, startKey, numEntries);
}

/**
* List the lightweight status for a file or a directory and its contents.
*
* @param keyName Absolute path of the entry to be listed
* @param recursive For a directory if true all the descendants of a
* particular directory are listed
* @param startKey Key from which listing needs to start. If startKey exists
* its status is included in the final list.
* @param numEntries Number of entries to list from the start key
* @return list of file status
*/
public List<OzoneFileStatusLight> listStatusLight(String keyName, boolean recursive,
String startKey, long numEntries) throws IOException {
return proxy.listStatusLight(volumeName, name, keyName, recursive, startKey, numEntries);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,22 @@ List<OzoneFileStatus> listStatus(String volumeName, String bucketName,
String keyName, boolean recursive, String startKey,
long numEntries, boolean allowPartialPrefixes) throws IOException;

/**
* Lightweight listStatus API.
*
* @param volumeName Volume name
* @param bucketName Bucket name
* @param keyName Absolute path of the entry to be listed
* @param recursive For a directory if true all the descendants of a
* particular directory are listed
* @param startKey Key from which listing needs to start. If startKey exists
* its status is included in the final list.
* @param numEntries Number of entries to list from the start key
* @return list of file status
*/
List<OzoneFileStatusLight> listStatusLight(String volumeName,
String bucketName, String keyName, boolean recursive, String startKey, long numEntries) throws IOException;

/**
* Lightweight listStatus API.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2311,6 +2311,22 @@ public List<OzoneFileStatus> listStatus(String volumeName, String bucketName,
allowPartialPrefixes);
}

@Override
public List<OzoneFileStatusLight> listStatusLight(String volumeName, String bucketName, String keyName,
boolean recursive, String startKey, long numEntries) throws IOException {
OmKeyArgs keyArgs = prepareOmKeyArgs(volumeName, bucketName, keyName);
if (omVersion.compareTo(OzoneManagerVersion.LIGHTWEIGHT_LIST_STATUS) >= 0) {
return ozoneManagerClient.listStatusLight(keyArgs, recursive, startKey,
numEntries);
} else {
return ozoneManagerClient.listStatus(keyArgs, recursive, startKey,
numEntries)
.stream()
.map(OzoneFileStatusLight::fromOzoneFileStatus)
.collect(Collectors.toList());
}
}

@Override
public List<OzoneFileStatusLight> listStatusLight(String volumeName,
String bucketName, String keyName, boolean recursive, String startKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ public String getOwnerName() {
return ownerName;
}

public long getReplicatedSize() {
return QuotaUtil.getReplicatedSize(getDataSize(), replicationConfig);
}

/**
* Builder of BasicOmKeyInfo.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,20 @@ List<OzoneFileStatus> listStatus(OmKeyArgs keyArgs, boolean recursive,
boolean allowPartialPrefixes)
throws IOException;

/**
* Lightweight listStatus API.
*
* @param keyArgs Key args
* @param recursive For a directory if true all the descendants of a
* particular directory are listed
* @param startKey Key from which listing needs to start. If startKey exists
* its status is included in the final list.
* @param numEntries Number of entries to list from the start key
* @return list of file status
*/
List<OzoneFileStatusLight> listStatusLight(OmKeyArgs keyArgs, boolean recursive, String startKey,
long numEntries) throws IOException;

/**
* Lightweight listStatus API.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2374,6 +2374,12 @@ public List<OzoneFileStatus> listStatus(OmKeyArgs args, boolean recursive,
return statusList;
}

@Override
public List<OzoneFileStatusLight> listStatusLight(OmKeyArgs args,
boolean recursive, String startKey, long numEntries) throws IOException {
return listStatusLight(args, recursive, startKey, numEntries, false);
}

@Override
public List<OzoneFileStatusLight> listStatusLight(OmKeyArgs args,
boolean recursive, String startKey, long numEntries,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,41 @@ void testListStatus2() throws IOException {
}
}

@Test
public void testOzoneManagerListLocatedStatusAndListStatus() throws IOException {
String data = RandomStringUtils.randomAlphanumeric(20);
String directory = RandomStringUtils.randomAlphanumeric(5);
String filePath = RandomStringUtils.randomAlphanumeric(5);
Path path = createPath("/" + directory + "/" + filePath);
try (FSDataOutputStream stream = fs.create(path)) {
stream.writeBytes(data);
}
RemoteIterator<LocatedFileStatus> listLocatedStatus = fs.listLocatedStatus(path);
int count = 0;
while (listLocatedStatus.hasNext()) {
LocatedFileStatus locatedFileStatus = listLocatedStatus.next();
assertTrue(locatedFileStatus.getBlockLocations().length >= 1);

for (BlockLocation blockLocation : locatedFileStatus.getBlockLocations()) {
assertTrue(blockLocation.getNames().length >= 1);
assertTrue(blockLocation.getHosts().length >= 1);
}
count++;
}
assertEquals(1, count);
count = 0;
RemoteIterator<FileStatus> listStatus = fs.listStatusIterator(path);
while (listStatus.hasNext()) {
FileStatus fileStatus = listStatus.next();
assertFalse(fileStatus instanceof LocatedFileStatus);
count++;
}
assertEquals(1, count);
FileStatus[] fileStatuses = fs.listStatus(path.getParent());
assertEquals(1, fileStatuses.length);
assertFalse(fileStatuses[0] instanceof LocatedFileStatus);
}

@Test
void testOzoneManagerFileSystemInterface() throws IOException {
String dirPath = RandomStringUtils.randomAlphanumeric(5);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@ private void listStatusRecursiveHelper(Path curPath, List<FileStatus> result)
private List<FileStatus> callAdapterListStatus(String pathStr,
boolean recursive, String startPath, long numEntries) throws IOException {
return adapter.listStatus(pathStr, recursive, startPath, numEntries,
ofs.getUri(), ofs.getWorkingDirectory(), ofs.getUsername())
ofs.getUri(), ofs.getWorkingDirectory(), ofs.getUsername(), false)
.stream().map(ofs::convertFileStatus).collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.apache.hadoop.ozone.client.OzoneClientFactory;
import org.apache.hadoop.ozone.client.OzoneVolume;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatusLight;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
Expand Down Expand Up @@ -151,5 +152,11 @@ private void assertListStatus(OzoneBucket bucket, String keyName,

List<?> versions = files.get(0).getKeyInfo().getKeyLocationVersions();
assertEquals(expectedVersionCount, versions.size());

List<OzoneFileStatusLight> lightFiles = bucket.listStatusLight(keyName, false, "", 1);

assertNotNull(lightFiles);
assertEquals(1, lightFiles.size());

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public List<OzoneFileStatusLight> listStatusLight(OmKeyArgs args,
.map(OzoneFileStatusLight::fromOzoneFileStatus)
.collect(Collectors.toList());
}

@Override
public OzoneFileStatus getFileStatus(OmKeyArgs args) throws IOException {
ResolvedBucket bucket = ozoneManager.resolveBucketLink(args);
Expand Down Expand Up @@ -501,7 +501,7 @@ void checkAcls(ResourceType resType, StoreType store,
ozoneManager.getOmRpcServerAddr().getHostName());
}


/**
* CheckAcls for the ozone object.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3802,6 +3802,12 @@ public List<OzoneFileStatus> listStatus(OmKeyArgs args, boolean recursive,
}
}

@Override
public List<OzoneFileStatusLight> listStatusLight(OmKeyArgs args,
boolean recursive, String startKey, long numEntries) throws IOException {
return listStatusLight(args, recursive, startKey, numEntries, false);
}

@Override
public List<OzoneFileStatusLight> listStatusLight(OmKeyArgs args,
boolean recursive, String startKey, long numEntries,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import org.apache.hadoop.ozone.client.rpc.RpcClient;
import org.apache.hadoop.ozone.container.common.helpers.BlockData;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BasicOmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.helpers.LeaseKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
Expand All @@ -77,6 +78,7 @@
import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfoGroup;
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatusLight;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
import org.apache.hadoop.ozone.snapshot.SnapshotDiffReportOzone;
import org.apache.hadoop.ozone.snapshot.SnapshotDiffResponse;
Expand Down Expand Up @@ -436,15 +438,22 @@ public Iterator<BasicKeyInfo> listKeys(String pathKey) throws IOException {
@Override
public List<FileStatusAdapter> listStatus(String keyName, boolean recursive,
String startKey, long numEntries, URI uri,
Path workingDir, String username) throws IOException {
Path workingDir, String username, boolean lite) throws IOException {
try {
incrementCounter(Statistic.OBJECTS_LIST, 1);
List<OzoneFileStatus> statuses = bucket
.listStatus(keyName, recursive, startKey, numEntries);

List<FileStatusAdapter> result = new ArrayList<>();
for (OzoneFileStatus status : statuses) {
result.add(toFileStatusAdapter(status, username, uri, workingDir));
if (lite) {
List<OzoneFileStatusLight> statuses = bucket
.listStatusLight(keyName, recursive, startKey, numEntries);
for (OzoneFileStatusLight status : statuses) {
result.add(toFileStatusAdapter(status, username, uri, workingDir));
}
} else {
List<OzoneFileStatus> statuses = bucket
.listStatus(keyName, recursive, startKey, numEntries);
for (OzoneFileStatus status : statuses) {
result.add(toFileStatusAdapter(status, username, uri, workingDir));
}
}
return result;
} catch (OMException e) {
Expand Down Expand Up @@ -549,6 +558,31 @@ private FileStatusAdapter toFileStatusAdapter(OzoneFileStatus status,
);
}

private FileStatusAdapter toFileStatusAdapter(OzoneFileStatusLight status,
String owner, URI defaultUri, Path workingDir) {
BasicOmKeyInfo keyInfo = status.getKeyInfo();
short replication = (short) keyInfo.getReplicationConfig()
.getRequiredNodes();
return new FileStatusAdapter(
keyInfo.getDataSize(),
keyInfo.getReplicatedSize(),
new Path(OZONE_URI_DELIMITER + keyInfo.getKeyName())
.makeQualified(defaultUri, workingDir),
status.isDirectory(),
replication,
status.getBlockSize(),
keyInfo.getModificationTime(),
keyInfo.getModificationTime(),
status.isDirectory() ? (short) 00777 : (short) 00666,
StringUtils.defaultIfEmpty(keyInfo.getOwnerName(), owner),
owner,
null,
getBlockLocations(null),
false,
OzoneClientUtils.isKeyErasureCode(keyInfo)
);
}

/**
* Helper method to get List of BlockLocation from OM Key info.
* @param fileStatus Ozone key file status.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.apache.hadoop.fs.ozone;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;

import org.apache.hadoop.conf.Configuration;
Expand Down Expand Up @@ -688,7 +689,7 @@ public FileStatus[] listStatus(Path f) throws IOException {
do {
tmpStatusList =
adapter.listStatus(pathToKey(f), false, startKey, numEntries, uri,
workingDir, getUsername())
workingDir, getUsername(), true)
.stream()
.map(this::convertFileStatus)
.collect(Collectors.toList());
Expand Down Expand Up @@ -947,13 +948,15 @@ public RemoteIterator<LocatedFileStatus> listFiles(Path f, boolean recursive)
public RemoteIterator<LocatedFileStatus> listLocatedStatus(Path f)
throws IOException {
incrementCounter(Statistic.INVOCATION_LIST_LOCATED_STATUS);
return super.listLocatedStatus(f);
return new OzoneFileStatusIterator<>(f,
(stat) -> stat instanceof LocatedFileStatus ? (LocatedFileStatus) stat : new LocatedFileStatus(stat, null),
false);
}

@Override
public RemoteIterator<FileStatus> listStatusIterator(Path f)
throws IOException {
return new OzoneFileStatusIterator<>(f);
return new OzoneFileStatusIterator<>(f, stat -> stat, true);
}

@Override
Expand Down Expand Up @@ -986,7 +989,6 @@ public void setTimes(Path f, long mtime, long atime) throws IOException {
String key = pathToKey(qualifiedPath);
adapter.setTimes(key, mtime, atime);
}

/**
* A private class implementation for iterating list of file status.
*
Expand All @@ -999,6 +1001,8 @@ private final class OzoneFileStatusIterator<T extends FileStatus>
private Path p;
private T curStat = null;
private String startPath = "";
private boolean lite;
private Function<FileStatus, T> transformFunc;

/**
* Constructor to initialize OzoneFileStatusIterator.
Expand All @@ -1007,10 +1011,12 @@ private final class OzoneFileStatusIterator<T extends FileStatus>
* @param p path to file/directory.
* @throws IOException
*/
private OzoneFileStatusIterator(Path p) throws IOException {
private OzoneFileStatusIterator(Path p, Function<FileStatus, T> transformFunc, boolean lite) throws IOException {
this.p = p;
this.lite = lite;
this.transformFunc = transformFunc;
// fetch the first batch of entries in the directory
thisListing = listFileStatus(p, startPath);
thisListing = listFileStatus(p, startPath, lite);
if (thisListing != null && !thisListing.isEmpty()) {
startPath = pathToKey(
thisListing.get(thisListing.size() - 1).getPath());
Expand All @@ -1029,7 +1035,7 @@ public boolean hasNext() throws IOException {
while (curStat == null && hasNextNoFilter()) {
T next;
FileStatus fileStat = thisListing.get(i++);
next = (T) (fileStat);
next = this.transformFunc.apply(fileStat);
curStat = next;
}
return curStat != null;
Expand All @@ -1050,7 +1056,7 @@ private boolean hasNextNoFilter() throws IOException {
if (startPath != null && (thisListing.size() == listingPageSize ||
thisListing.size() == listingPageSize - 1)) {
// current listing is exhausted & fetch a new listing
thisListing = listFileStatus(p, startPath);
thisListing = listFileStatus(p, startPath, lite);
if (thisListing != null && !thisListing.isEmpty()) {
startPath = pathToKey(
thisListing.get(thisListing.size() - 1).getPath());
Expand Down Expand Up @@ -1088,15 +1094,15 @@ public T next() throws IOException {
* @return list of file status.
* @throws IOException
*/
private List<FileStatus> listFileStatus(Path f, String startPath)
private List<FileStatus> listFileStatus(Path f, String startPath, boolean lite)
throws IOException {
incrementCounter(Statistic.INVOCATION_LIST_STATUS, 1);
statistics.incrementReadOps(1);
LOG.trace("listFileStatus() path:{}", f);
List<FileStatus> statusList;
statusList =
adapter.listStatus(pathToKey(f), false, startPath,
listingPageSize, uri, workingDir, getUsername())
listingPageSize, uri, workingDir, getUsername(), lite)
.stream()
.map(this::convertFileStatus)
.collect(Collectors.toList());
Expand Down
Loading