From 0ed3de7dfa156381f17ccea03a73ff5a51673266 Mon Sep 17 00:00:00 2001 From: thu-david Date: Wed, 18 Oct 2023 18:06:07 +0800 Subject: [PATCH 01/14] Create locationCommandTest and fix some bugs --- .../cli/fs/command/LocationCommand.java | 2 +- .../fs/AbstractDoraShellIntegrationTest.java | 2 + .../cli/fs/AbstractShellIntegrationTest.java | 3 + .../fs/command/CatCommandIntegrationTest.java | 6 -- .../ChecksumCommandIntegrationTest.java | 14 ++-- .../DoraFileLocationIntegrationTest.java | 72 +++++++++++++++++++ .../fs/DoraFileSystemIntegrationTest.java | 4 +- 7 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraFileLocationIntegrationTest.java diff --git a/dora/shell/src/main/java/alluxio/cli/fs/command/LocationCommand.java b/dora/shell/src/main/java/alluxio/cli/fs/command/LocationCommand.java index bed120d19e25..96c6abcbdef0 100644 --- a/dora/shell/src/main/java/alluxio/cli/fs/command/LocationCommand.java +++ b/dora/shell/src/main/java/alluxio/cli/fs/command/LocationCommand.java @@ -74,7 +74,7 @@ protected void runPlainPath(AlluxioURI plainPath, CommandLine cl) if (workersThatHaveDataList != null && !workersThatHaveDataList.isEmpty()) { dataOnPreferredWorker = workersThatHaveDataList.contains(preferredWorker); workersThatHaveDataSet = workersThatHaveDataList.stream() - .map(workerNetAddress -> workerNetAddress.getHost()).collect(Collectors.toSet()); + .map(WorkerNetAddress::getHost).collect(Collectors.toSet()); } } } diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraShellIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraShellIntegrationTest.java index 09345f5519ef..acb416b5b1f5 100644 --- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraShellIntegrationTest.java +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraShellIntegrationTest.java @@ -50,6 +50,8 @@ public AbstractDoraShellIntegrationTest(int numWorkers) throws IOException { .setProperty(PropertyKey.WORKER_PAGE_STORE_PAGE_SIZE, Constants.KB) .setProperty(PropertyKey.WORKER_PAGE_STORE_SIZES, "1GB") .setProperty(PropertyKey.MASTER_WORKER_REGISTER_LEASE_ENABLED, false) + .setProperty(PropertyKey.DORA_CLIENT_UFS_FALLBACK_ENABLED, false) + // current s3 ufs mock don't support setXattr, disable the flag to bypass it .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false) .setNumWorkers(numWorkers) .setStartCluster(false) diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractShellIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractShellIntegrationTest.java index fa8f940c92bf..c5857f9a3b59 100644 --- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractShellIntegrationTest.java +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractShellIntegrationTest.java @@ -44,6 +44,9 @@ public abstract class AbstractShellIntegrationTest extends BaseIntegrationTest { .setProperty(PropertyKey.USER_FILE_WRITE_TYPE_DEFAULT, WriteType.CACHE_THROUGH) .setProperty(PropertyKey.USER_FILE_RESERVED_BYTES, SIZE_BYTES / 2) .setProperty(PropertyKey.CONF_DYNAMIC_UPDATE_ENABLED, true) + .setProperty(PropertyKey.DORA_CLIENT_UFS_FALLBACK_ENABLED, false) + // current s3 ufs mock don't support setXattr, disable the flag to bypass it + .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false) .build(); @Rule diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/CatCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/CatCommandIntegrationTest.java index 3cf5376bf3d1..562e178c05c7 100644 --- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/CatCommandIntegrationTest.java +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/CatCommandIntegrationTest.java @@ -16,7 +16,6 @@ import static org.junit.Assert.assertTrue; import alluxio.AlluxioURI; -import alluxio.annotation.dora.DoraTestTodoItem; import alluxio.client.cli.fs.AbstractFileSystemShellTest; import alluxio.client.cli.fs.FileSystemShellUtilsTest; import alluxio.client.file.FileInStream; @@ -27,7 +26,6 @@ import alluxio.util.io.BufferUtils; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import java.io.File; @@ -36,10 +34,6 @@ /** * Tests for cat command. */ -@DoraTestTodoItem(action = DoraTestTodoItem.Action.FIX, owner = "bowen", - comment = "the cluster is not properly cleaned up before each test run, " - + "see alluxio.testutils.LocalAlluxioClusterResource.ResetRule.resetCluster") -@Ignore("ignored due to broken test infrastructure") public final class CatCommandIntegrationTest extends AbstractFileSystemShellTest { @Test public void catDirectory() throws Exception { diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/ChecksumCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/ChecksumCommandIntegrationTest.java index 624aa217bdb9..c713ca03968f 100644 --- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/ChecksumCommandIntegrationTest.java +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/ChecksumCommandIntegrationTest.java @@ -11,7 +11,7 @@ package alluxio.client.cli.fs.command; -import alluxio.annotation.dora.DoraTestTodoItem; +import alluxio.AlluxioURI; import alluxio.client.cli.fs.AbstractFileSystemShellTest; import alluxio.client.file.FileSystemTestUtils; import alluxio.exception.ExceptionMessage; @@ -19,15 +19,13 @@ import org.apache.commons.codec.digest.DigestUtils; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; +import java.util.Objects; + /** * Tests checksum command. */ -@Ignore -@DoraTestTodoItem(action = DoraTestTodoItem.Action.FIX, owner = "Jiacheng", - comment = "need to check if this command will still exist in Dora") public final class ChecksumCommandIntegrationTest extends AbstractFileSystemShellTest { /** @@ -76,7 +74,11 @@ public void checksumWildCard() throws Exception { @Test public void checksumInvalidArgs() throws Exception { sFsShell.run("checksum", "/testFile"); - String expected = ExceptionMessage.PATH_DOES_NOT_EXIST.getMessage("/testFile") + "\n"; + AlluxioURI expectedUri = + Objects.requireNonNull(sFileSystem.getDoraCacheFileSystem()) + .convertToUfsPath(new AlluxioURI("/testFile")); + String expected = + ExceptionMessage.PATH_DOES_NOT_EXIST.getMessage(expectedUri.toString()) + "\n"; Assert.assertEquals(expected, mOutput.toString()); sFsShell.run("mkdir", "/testFolder"); int ret = sFsShell.run("checksum", "/testFolder"); diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraFileLocationIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraFileLocationIntegrationTest.java new file mode 100644 index 000000000000..5afe655a1e26 --- /dev/null +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraFileLocationIntegrationTest.java @@ -0,0 +1,72 @@ +/* + * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 + * (the "License"). You may not use this work except in compliance with the License, which is + * available at www.apache.org/licenses/LICENSE-2.0 + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied, as more fully set forth in the License. + * + * See the NOTICE file distributed with this work for information regarding copyright ownership. + */ + +package alluxio.client.cli.fs.command; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import alluxio.AlluxioURI; +import alluxio.Constants; +import alluxio.client.cli.fs.AbstractDoraFileSystemShellTest; +import alluxio.client.file.DoraCacheFileSystem; +import alluxio.client.file.FileSystemUtils; +import alluxio.conf.PropertyKey; +import alluxio.wire.WorkerNetAddress; + +import org.junit.Test; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +public class DoraFileLocationIntegrationTest extends AbstractDoraFileSystemShellTest { + + public DoraFileLocationIntegrationTest() throws IOException { + super(3); + } + + @Override + public void before() throws Exception { + mLocalAlluxioClusterResource.setProperty( + PropertyKey.JOB_BATCH_SIZE, 3 + ); + mLocalAlluxioClusterResource.setProperty( + PropertyKey.MASTER_SCHEDULER_INITIAL_DELAY, "1s" + ); + super.before(); + } + + @Test + public void testCommand() throws Exception { + mTestFolder.newFolder("testRoot"); + + AlluxioURI uriA = new AlluxioURI("/testRoot/testFileA"); + createByteFileInUfs("/testRoot/testFileA", Constants.MB); + assertEquals(0, mFsShell.run("load", "/testRoot", "--submit", "--verify")); + FileSystemUtils.waitForAlluxioPercentage(mFileSystem, uriA, 100); + + assertEquals(100, mFileSystem.getStatus(uriA).getInAlluxioPercentage()); + assertEquals(0, mFsShell.run("location", "/testRoot/testFileA")); + + DoraCacheFileSystem doraCacheFileSystem = mFileSystem.getDoraCacheFileSystem(); + assert doraCacheFileSystem != null; + AlluxioURI ufsFullPath = doraCacheFileSystem.convertToUfsPath(uriA); + String ufsPath = ufsFullPath.toString(); + Set workersThatHaveDataSet = new HashSet<>(); + WorkerNetAddress workerNetAddress = doraCacheFileSystem.getWorkerNetAddress(uriA); + workersThatHaveDataSet.add(workerNetAddress.getHost()); + assertTrue(mOutput.toString().contains(ufsPath)); + assertTrue(mOutput.toString().contains(workerNetAddress.getHost())); + assertTrue(mOutput.toString().contains(Boolean.TRUE.toString())); + assertTrue(mOutput.toString().contains(workersThatHaveDataSet.stream().iterator().next())); + } +} diff --git a/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java index 08014fe82926..48ddbd829ad2 100644 --- a/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java +++ b/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java @@ -75,8 +75,8 @@ public final class DoraFileSystemIntegrationTest extends BaseIntegrationTest { .setProperty(PropertyKey.UNDERFS_S3_ENDPOINT, "localhost:8001") .setProperty(PropertyKey.UNDERFS_S3_ENDPOINT_REGION, "us-west-2") .setProperty(PropertyKey.UNDERFS_S3_DISABLE_DNS_BUCKETS, true) - .setProperty(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS, "s3://" + TEST_BUCKET) - .setProperty(PropertyKey.DORA_CLIENT_UFS_ROOT, "s3://" + TEST_BUCKET) + .setProperty(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS, "s3://" + TEST_BUCKET + "/") + .setProperty(PropertyKey.DORA_CLIENT_UFS_ROOT, "s3://" + TEST_BUCKET + "/") .setProperty(PropertyKey.WORKER_HTTP_SERVER_ENABLED, false) .setProperty(PropertyKey.S3A_ACCESS_KEY, mS3Proxy.getAccessKey()) .setProperty(PropertyKey.S3A_SECRET_KEY, mS3Proxy.getSecretKey()) From 488307003ce7f340570aea001077a6febc87b507 Mon Sep 17 00:00:00 2001 From: thu-david Date: Wed, 25 Oct 2023 13:31:30 +0800 Subject: [PATCH 02/14] create DoraLsCommandIntegrationTest --- .../fs/AbstractDoraFileSystemShellTest.java | 13 ++ .../command/DoraLsCommandIntegrationTest.java | 219 ++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraFileSystemShellTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraFileSystemShellTest.java index b3947900a452..5a685b35f661 100644 --- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraFileSystemShellTest.java +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/AbstractDoraFileSystemShellTest.java @@ -11,9 +11,14 @@ package alluxio.client.cli.fs; +import alluxio.AlluxioURI; import alluxio.cli.fs.FileSystemShell; +import alluxio.client.file.FileOutStream; import alluxio.client.file.FileSystem; import alluxio.conf.Configuration; +import alluxio.exception.AlluxioException; +import alluxio.grpc.CreateFilePOptions; +import alluxio.grpc.WritePType; import alluxio.master.LocalAlluxioCluster; import alluxio.util.io.BufferUtils; @@ -51,4 +56,12 @@ protected void createByteFileInUfs(String fileName, int length) throws IOExcepti File f = mTestFolder.newFile(fileName); Files.write(f.toPath(), BufferUtils.getIncreasingByteArray(length)); } + + protected void createByteFileInAlluxio(String filename, byte[] bytes, WritePType writePType) + throws IOException, AlluxioException { + FileOutStream fos = mFileSystem.createFile(new AlluxioURI(filename), + CreateFilePOptions.newBuilder().setWriteType(writePType).setRecursive(true).build()); + fos.write(bytes); + fos.close(); + } } diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java new file mode 100644 index 000000000000..5b2fd4683cfe --- /dev/null +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java @@ -0,0 +1,219 @@ +/* + * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 + * (the "License"). You may not use this work except in compliance with the License, which is + * available at www.apache.org/licenses/LICENSE-2.0 + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied, as more fully set forth in the License. + * + * See the NOTICE file distributed with this work for information regarding copyright ownership. + */ + +package alluxio.client.cli.fs.command; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import alluxio.Constants; +import alluxio.client.cli.fs.AbstractDoraFileSystemShellTest; +import alluxio.conf.PropertyKey; +import alluxio.exception.AlluxioException; +import alluxio.grpc.WritePType; +import alluxio.util.io.BufferUtils; + +import org.junit.Test; + +import java.io.IOException; + +public class DoraLsCommandIntegrationTest extends AbstractDoraFileSystemShellTest { + public DoraLsCommandIntegrationTest() throws IOException { + super(3); + } + + @Override + public void before() throws Exception { + mLocalAlluxioClusterResource.setProperty(PropertyKey.MASTER_SCHEDULER_INITIAL_DELAY, "1s") + .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false); + super.before(); + } + + private void createFiles() throws Exception { + createByteFileInAlluxio("/testRoot/testFileA", BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + createByteFileInAlluxio("/testRoot/testFileB", BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + createByteFileInAlluxio("/testRoot/testDirectory/testFileC", + BufferUtils.getIncreasingByteArray(Constants.MB), WritePType.CACHE_THROUGH); + createByteFileInAlluxio("/testRoot/testDirectory/testFileD", + BufferUtils.getIncreasingByteArray(Constants.MB), WritePType.THROUGH); + } + + @Test + public void testLsPath() throws Exception { + createFiles(); + assertEquals(0, mFsShell.run("ls", "--sort", "path", "/testRoot")); + checkOutput( + ".*DIR /testRoot/testDirectory", + ".*FILE /testRoot/testFileA", + ".*FILE /testRoot/testFileB" + ); + + assertEquals(0, mFsShell.run("ls", "--sort", "path", "/testRoot/testDirectory")); + checkOutput( + ".*FILE /testRoot/testDirectory/testFileC", + ".*FILE /testRoot/testDirectory/testFileD" + ); + + assertEquals(0, mFsShell.run("ls", "--sort", "path", "/testRoot/testDirectory/testFileC")); + checkOutput( + ".*FILE /testRoot/testDirectory/testFileC" + ); + + assertEquals(0, mFsShell.run("ls", "--sort", "path", "/testRoot/testDirectory/testFileD")); + checkOutput( + ".*FILE /testRoot/testDirectory/testFileD" + ); + } + + @Test + public void testLsMultipleDirs() throws Exception { + createFiles(); + assertEquals(0, mFsShell.run("ls", "--sort", "path", "/testRoot/testDirectory", "/testRoot")); + checkOutput( + ".*FILE /testRoot/testDirectory/testFileC", + ".*FILE /testRoot/testDirectory/testFileD", + ".*DIR /testRoot/testDirectory", + ".*FILE /testRoot/testFileA", + ".*FILE /testRoot/testFileB" + ); + } + + @Test + public void testLsDirectory() throws Exception { + createFiles(); + assertEquals(0, mFsShell.run("ls", "-d", "/testRoot")); + checkOutput( + ".*DIR /testRoot" + ); + + assertEquals(0, mFsShell.run("ls", "-d", "/testRoot/testDirectory")); + checkOutput( + ".*DIR /testRoot/testDirectory" + ); + } + + @Test + public void testLsRoot() throws Exception { + createFiles(); + assertEquals(0, mFsShell.run("ls", "/")); + checkOutput( + ".*DIR /testRoot" + ); + } + + @Test + public void testLsWildcard() throws Exception { + createFiles(); + assertEquals(0, mFsShell.run("ls", "/testRoot/testFile*")); + checkOutput( + ".*FILE /testRoot/testFileA", + ".*FILE /testRoot/testFileB" + ); + } + + @Test + public void testLsR() throws Exception { + createFiles(); + assertEquals(0, mFsShell.run("ls", "-R", "--sort", "path", "/testRoot")); + checkOutput( + ".*DIR /testRoot/testDirectory", + ".*FILE /testRoot/testDirectory/testFileC", + ".*FILE /testRoot/testDirectory/testFileD", + ".*FILE /testRoot/testFileA", + ".*FILE /testRoot/testFileB" + ); + } + + @Test + public void testLsWithSortByAccessTime() throws IOException, AlluxioException { + String oldFile = "/testRoot/oldFile"; + String newFile = "/testRoot/newFile"; + createByteFileInAlluxio(oldFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + assertEquals(0, mFsShell.run("ls", "--sort", "lastAccessTime", "/testRoot")); + checkOutput( + ".*FILE " + oldFile, + ".*FILE " + newFile + ); + } + + @Test + public void testLsWithSortBySize() throws IOException, AlluxioException { + String smallFile = "/testRoot/smallFile"; + String largeFile = "/testRoot/largeFile"; + createByteFileInAlluxio(smallFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + createByteFileInAlluxio(largeFile, BufferUtils.getIncreasingByteArray(2 * Constants.MB), + WritePType.CACHE_THROUGH); + assertEquals(0, mFsShell.run("ls", "--sort", "size", "/testRoot")); + checkOutput( + ".*FILE " + smallFile, + ".*FILE " + largeFile + ); + } + + @Test + public void testLsWithSortBySizeAndReverse() throws IOException, AlluxioException { + String smallFile = "/testRoot/smallFile"; + String largeFile = "/testRoot/largeFile"; + createByteFileInAlluxio(smallFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + createByteFileInAlluxio(largeFile, BufferUtils.getIncreasingByteArray(2 * Constants.MB), + WritePType.CACHE_THROUGH); + assertEquals(0, mFsShell.run("ls", "--sort", "size", "-r", "/testRoot")); + checkOutput( + ".*FILE " + largeFile, + ".*FILE " + smallFile + ); + } + + @Test + public void testLsWithSortByCreationTime() throws IOException, AlluxioException { + String oldFile = "/testRoot/oldFile"; + String newFile = "/testRoot/newFile"; + createByteFileInAlluxio(oldFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + assertEquals(0, mFsShell.run("ls", "--sort", "creationTime", "/testRoot")); + checkOutput( + ".*FILE " + oldFile, + ".*FILE " + newFile + ); + } + + @Test + public void testLsWithInvalidSortOption() throws IOException, AlluxioException { + String oldFile = "/testRoot/oldFile"; + String newFile = "/testRoot/newFile"; + createByteFileInAlluxio(oldFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB), + WritePType.CACHE_THROUGH); + assertEquals(-1, mFsShell.run("ls", "--sort", "invalidOption", "/testRoot")); + String expected = "Invalid sort option `invalidOption` for --sort\n"; + assertEquals(expected, mOutput.toString()); + } + + private void checkOutput(String... linePatterns) { + String[] actualLines = mOutput.toString().split("\n"); + assertEquals("Output: ", linePatterns.length, actualLines.length); + + for (int i = 0; i < linePatterns.length; i++) { + assertTrue("mOutput: " + mOutput.toString(), actualLines[i].matches(linePatterns[i])); + } + mOutput.reset(); + } +} From 7c1453de7fab7c95f0fb1a8758db8173724a94b3 Mon Sep 17 00:00:00 2001 From: thu-david Date: Thu, 26 Oct 2023 11:19:46 +0800 Subject: [PATCH 03/14] Create DoraMkdirCommandIntegrationTest.java --- .../DoraMkdirCommandIntegrationTest.java | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java new file mode 100644 index 000000000000..a0d7042a67c7 --- /dev/null +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java @@ -0,0 +1,118 @@ +/* + * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 + * (the "License"). You may not use this work except in compliance with the License, which is + * available at www.apache.org/licenses/LICENSE-2.0 + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied, as more fully set forth in the License. + * + * See the NOTICE file distributed with this work for information regarding copyright ownership. + */ + +package alluxio.client.cli.fs.command; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import alluxio.AlluxioURI; +import alluxio.client.cli.fs.AbstractDoraFileSystemShellTest; +import alluxio.client.file.URIStatus; +import alluxio.conf.PropertyKey; + +import org.junit.Test; + +import java.io.IOException; + +public class DoraMkdirCommandIntegrationTest extends AbstractDoraFileSystemShellTest { + public DoraMkdirCommandIntegrationTest() throws IOException { + super(3); + } + + @Override + public void before() throws Exception { + mLocalAlluxioClusterResource.setProperty(PropertyKey.MASTER_SCHEDULER_INITIAL_DELAY, "1s") + .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false); + super.before(); + } + + @Test + public void testMkdir() throws Exception { + AlluxioURI uri = new AlluxioURI("/testRoot/testDir"); + assertEquals(0, mFsShell.run("mkdir", uri.toString())); + URIStatus status = mFileSystem.getStatus(uri); + assertNotNull(status); + assertTrue(status.isFolder()); + checkOutput("Successfully created directory " + uri); + } + + @Test + public void testMkdirComplexPath() throws Exception { + AlluxioURI uri = new AlluxioURI("/testRoot/Complex!@#$%^&*()-_=+[]{};\"'<>,.?/File"); + assertEquals(0, mFsShell.run("mkdir", uri.toString())); + URIStatus status = mFileSystem.getStatus(uri); + assertNotNull(status); + assertTrue(status.isFolder()); + assertTrue(mOutput.toString().contains("Successfully created directory " + uri)); + } + + @Test + public void testMkdirExisting() throws Exception { + AlluxioURI uri = new AlluxioURI("/testRoot/testDir"); + assertEquals(0, mFsShell.run("mkdir", uri.toString())); + assertEquals(-1, mFsShell.run("mkdir", uri.toString())); + } + + @Test + public void testMkdirPathWithWhiteSpaces() throws Exception { + String[] paths = new String[]{ + "/ ", + "/x y z", + "/ x y z", + "/ x y z / a b c" + }; + for (String path : paths) { + AlluxioURI uri = new AlluxioURI(path); + assertEquals(0, mFsShell.run("mkdir", uri.toString())); + URIStatus status = mFileSystem.getStatus(uri); + assertNotNull(status); + assertTrue(status.isFolder()); + assertTrue(mOutput.toString().contains("Successfully created directory " + uri)); + } + } + + @Test + public void testMkdirInvalidPath() throws Exception { + assertEquals(-1, mFsShell.run("mkdir", "")); + } + + @Test + public void testMkdirMultiPath() throws Exception { + String path1 = "/testDir1"; + String path2 = "/testDir2"; + String path3 = "/testDir2/testDir2.1"; + assertEquals(0, mFsShell.run("mkdir", path1, path2, path3)); + + URIStatus status = mFileSystem.getStatus(new AlluxioURI(path1)); + assertNotNull(status); + assertTrue(status.isFolder()); + + status = mFileSystem.getStatus(new AlluxioURI(path2)); + assertNotNull(status); + assertTrue(status.isFolder()); + + status = mFileSystem.getStatus(new AlluxioURI(path3)); + assertNotNull(status); + assertTrue(status.isFolder()); + } + + private void checkOutput(String... linePatterns) { + String[] actualLines = mOutput.toString().split("\n"); + assertEquals("Output: ", linePatterns.length, actualLines.length); + + for (int i = 0; i < linePatterns.length; i++) { + assertTrue("mOutput: " + mOutput.toString(), actualLines[i].matches(linePatterns[i])); + } + mOutput.reset(); + } +} From 0a0d63e8f224df71f0ede8a30b6ffc1e5a68acda Mon Sep 17 00:00:00 2001 From: thu-david Date: Thu, 26 Oct 2023 18:26:25 +0800 Subject: [PATCH 04/14] Update DoraMkdirCommandIntegrationTest.java --- .../DoraMkdirCommandIntegrationTest.java | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java index a0d7042a67c7..9985036db2a2 100644 --- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java +++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraMkdirCommandIntegrationTest.java @@ -31,8 +31,7 @@ public DoraMkdirCommandIntegrationTest() throws IOException { @Override public void before() throws Exception { - mLocalAlluxioClusterResource.setProperty(PropertyKey.MASTER_SCHEDULER_INITIAL_DELAY, "1s") - .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false); + mLocalAlluxioClusterResource.setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false); super.before(); } @@ -47,25 +46,17 @@ public void testMkdir() throws Exception { } @Test - public void testMkdirComplexPath() throws Exception { - AlluxioURI uri = new AlluxioURI("/testRoot/Complex!@#$%^&*()-_=+[]{};\"'<>,.?/File"); - assertEquals(0, mFsShell.run("mkdir", uri.toString())); - URIStatus status = mFileSystem.getStatus(uri); - assertNotNull(status); - assertTrue(status.isFolder()); - assertTrue(mOutput.toString().contains("Successfully created directory " + uri)); - } - - @Test - public void testMkdirExisting() throws Exception { + public void testMkdirExisting() { AlluxioURI uri = new AlluxioURI("/testRoot/testDir"); assertEquals(0, mFsShell.run("mkdir", uri.toString())); assertEquals(-1, mFsShell.run("mkdir", uri.toString())); + assertTrue( + mOutput.toString().contains("UNKNOWN: alluxio.exception.FileAlreadyExistsException")); } @Test public void testMkdirPathWithWhiteSpaces() throws Exception { - String[] paths = new String[]{ + String[] paths = new String[] { "/ ", "/x y z", "/ x y z", @@ -82,8 +73,10 @@ public void testMkdirPathWithWhiteSpaces() throws Exception { } @Test - public void testMkdirInvalidPath() throws Exception { + public void testMkdirInvalidPath() { assertEquals(-1, mFsShell.run("mkdir", "")); + assertTrue( + mOutput.toString().contains("UNKNOWN: alluxio.exception.FileAlreadyExistsException")); } @Test @@ -106,6 +99,20 @@ public void testMkdirMultiPath() throws Exception { assertTrue(status.isFolder()); } + @Test + public void testMkdirRecursive() throws Exception { + String path1 = "/testDir2/testDir2.1"; + String path2 = "/testDir2"; + assertEquals(0, mFsShell.run("mkdir", path1)); + + URIStatus status = mFileSystem.getStatus(new AlluxioURI(path1)); + URIStatus status1 = mFileSystem.getStatus(new AlluxioURI(path2)); + assertNotNull(status); + assertNotNull(status1); + assertTrue(status.isFolder()); + assertTrue(status1.isFolder()); + } + private void checkOutput(String... linePatterns) { String[] actualLines = mOutput.toString().split("\n"); assertEquals("Output: ", linePatterns.length, actualLines.length); From a1a335a9a82b63af7c5ff579a26a494b547231a0 Mon Sep 17 00:00:00 2001 From: thu-david Date: Fri, 3 Nov 2023 15:38:50 +0800 Subject: [PATCH 05/14] [FIX] Fix the bugs in DoraFileSystemIntegrationTest.java --- .../alluxio/master/LocalAlluxioCluster.java | 33 ++++++++++- .../fs/DoraFileSystemIntegrationTest.java | 58 +++++++------------ 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java index 95c7e132ed14..ffe53ad4f987 100644 --- a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java +++ b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java @@ -11,14 +11,20 @@ package alluxio.master; +import alluxio.AlluxioURI; import alluxio.ClientContext; import alluxio.ConfigurationTestUtils; import alluxio.client.block.BlockMasterClient; import alluxio.client.block.BlockWorkerInfo; +import alluxio.client.block.stream.BlockWorkerClient; +import alluxio.client.file.DoraCacheFileSystem; import alluxio.client.file.FileSystem; import alluxio.client.file.FileSystemContext; import alluxio.conf.Configuration; import alluxio.conf.PropertyKey; +import alluxio.grpc.GetStatusPRequest; +import alluxio.grpc.GetStatusPResponse; +import alluxio.resource.CloseableResource; import alluxio.util.CommonUtils; import alluxio.util.WaitForOptions; import alluxio.wire.WorkerInfo; @@ -36,7 +42,7 @@ /** * Local Alluxio cluster for integration tests. - * + *

* Example to use *

  * // Create a cluster instance
@@ -64,7 +70,7 @@ public LocalAlluxioCluster() {
   }
 
   /**
-   * @param numWorkers the number of workers to run
+   * @param numWorkers   the number of workers to run
    * @param includeProxy weather to include the proxy
    */
   public LocalAlluxioCluster(int numWorkers, boolean includeProxy) {
@@ -185,8 +191,29 @@ protected void waitForWorkersServing() throws TimeoutException, InterruptedExcep
     CommonUtils.waitFor("worker starts serving RPCs", () -> {
       try (FileSystemContext fsContext = FileSystemContext.create()) {
         List workerInfoList = fsContext.getCachedWorkers();
+        if (mNumWorkers != workerInfoList.size()) {
+          return false;
+        }
         LOG.info("Observed {} workers in the cluster", workerInfoList.size());
-        return workerInfoList.size() == mNumWorkers;
+        for (BlockWorkerInfo workerInfo : workerInfoList) {
+          try (CloseableResource blockWorkerClient =
+                   fsContext.acquireBlockWorkerClient(workerInfo.getNetAddress())) {
+            AlluxioURI rootUri = new AlluxioURI("/");
+            FileSystem masterFs = mMaster.getClient();
+            DoraCacheFileSystem doraCacheFs = masterFs.getDoraCacheFileSystem();
+            assert doraCacheFs != null;
+            AlluxioURI uri = doraCacheFs.convertToUfsPath(rootUri);
+            GetStatusPResponse getStatusPResponse = blockWorkerClient.get()
+                .getStatus(GetStatusPRequest.newBuilder().setPath(uri.toString()).build());
+            if (getStatusPResponse == null) {
+              return false;
+            }
+          } catch (IOException ioe) {
+            LOG.error("Failed to connect to worker {}: {}", workerInfo.getNetAddress(), ioe);
+            return false;
+          }
+        }
+        return true;
       } catch (IOException ioe) {
         LOG.error(ioe.getMessage());
         return false;
diff --git a/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java
index c5a68ae47cbd..292e689cf00b 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java
@@ -17,7 +17,6 @@
 
 import alluxio.AlluxioURI;
 import alluxio.Constants;
-import alluxio.annotation.dora.DoraTestTodoItem;
 import alluxio.client.WriteType;
 import alluxio.client.file.FileInStream;
 import alluxio.client.file.FileOutStream;
@@ -42,7 +41,6 @@
 import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 import org.apache.commons.io.IOUtils;
 import org.gaul.s3proxy.junit.S3ProxyRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -52,20 +50,15 @@
 /**
  * Integration tests for Alluxio Client (reuse the {@link LocalAlluxioCluster}).
  */
-@Ignore
-@DoraTestTodoItem(action = DoraTestTodoItem.Action.FIX, owner = "yichuan",
-    comment = "Bring back but not passed, need to fix.")
 public final class DoraFileSystemIntegrationTest extends BaseIntegrationTest {
   @Rule
-  public S3ProxyRule mS3Proxy = S3ProxyRule.builder()
-      .withBlobStoreProvider("transient")
-      .withPort(8001)
-      .withCredentials("_", "_")
-      .build();
+  public S3ProxyRule mS3Proxy =
+      S3ProxyRule.builder().withBlobStoreProvider("transient").withPort(8001)
+          .withCredentials("_", "_").build();
 
   LocalAlluxioClusterResource.Builder mLocalAlluxioClusterResourceBuilder =
-      new LocalAlluxioClusterResource.Builder()
-          .setProperty(PropertyKey.MASTER_PERSISTENCE_CHECKER_INTERVAL_MS, "10ms")
+      new LocalAlluxioClusterResource.Builder().setProperty(
+              PropertyKey.MASTER_PERSISTENCE_CHECKER_INTERVAL_MS, "10ms")
           .setProperty(PropertyKey.MASTER_PERSISTENCE_SCHEDULER_INTERVAL_MS, "10ms")
           .setProperty(PropertyKey.JOB_MASTER_WORKER_HEARTBEAT_INTERVAL, "200ms")
           .setProperty(PropertyKey.USER_BLOCK_SIZE_BYTES_DEFAULT, Constants.MB * 16)
@@ -87,8 +80,7 @@ public final class DoraFileSystemIntegrationTest extends BaseIntegrationTest {
           .setProperty(PropertyKey.S3A_SECRET_KEY, mS3Proxy.getSecretKey())
           .setProperty(PropertyKey.DORA_CLIENT_UFS_FALLBACK_ENABLED, false)
           // current s3 ufs mock don't support setXattr, disable the flag to bypass it
-          .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false)
-          .setNumWorkers(2)
+          .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false).setNumWorkers(2)
           .setStartCluster(false);
 
   private static final String TEST_BUCKET = "test-bucket";
@@ -107,16 +99,12 @@ private void startCluster(LocalAlluxioClusterResource cluster) throws Exception
     mFileSystem = cluster.get().getClient();
 
     if (mS3Client == null) {
-      mS3Client = AmazonS3ClientBuilder
-          .standard()
-          .withPathStyleAccessEnabled(true)
-          .withCredentials(
+      mS3Client = AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true).withCredentials(
               new AWSStaticCredentialsProvider(
                   new BasicAWSCredentials(mS3Proxy.getAccessKey(), mS3Proxy.getSecretKey())))
           .withEndpointConfiguration(
               new AwsClientBuilder.EndpointConfiguration(mS3Proxy.getUri().toString(),
-                  Regions.US_WEST_2.getName()))
-          .build();
+                  Regions.US_WEST_2.getName())).build();
       mS3Client.createBucket(TEST_BUCKET);
     }
   }
@@ -144,22 +132,19 @@ private void writeThenDeleteFromUfs(boolean clientWriteToUFS)
     fos.close();
 
     mS3Client.deleteObject(TEST_BUCKET, TEST_FILE);
-    assertNotNull(mFileSystem.getStatus(TEST_FILE_URI, GetStatusPOptions.newBuilder()
-        .setCommonOptions(optionNoSync())
-        .build()));
+    assertNotNull(mFileSystem.getStatus(TEST_FILE_URI,
+        GetStatusPOptions.newBuilder().setCommonOptions(optionNoSync()).build()));
     try (FileInStream fis = mFileSystem.openFile(TEST_FILE_URI,
         OpenFilePOptions.newBuilder().setCommonOptions(optionNoSync()).build())) {
       String content = IOUtils.toString(fis);
       assertEquals(TEST_CONTENT, content);
     }
 
-    assertThrows(FileDoesNotExistException.class, () ->
-        mFileSystem.getStatus(TEST_FILE_URI, GetStatusPOptions.newBuilder()
-            .setCommonOptions(optionSync()).build()));
+    assertThrows(FileDoesNotExistException.class, () -> mFileSystem.getStatus(TEST_FILE_URI,
+        GetStatusPOptions.newBuilder().setCommonOptions(optionSync()).build()));
 
-    assertThrows(FileDoesNotExistException.class, () ->
-        mFileSystem.getStatus(TEST_FILE_URI, GetStatusPOptions.newBuilder()
-            .setCommonOptions(optionNoSync()).build()));
+    assertThrows(FileDoesNotExistException.class, () -> mFileSystem.getStatus(TEST_FILE_URI,
+        GetStatusPOptions.newBuilder().setCommonOptions(optionNoSync()).build()));
 
     stopCluster(clusterResource);
   }
@@ -182,9 +167,8 @@ private void writeThenUpdateFromUfs(boolean clientWriteToUFS)
     fos.close();
 
     mS3Client.putObject(TEST_BUCKET, TEST_FILE, UPDATED_TEST_CONTENT);
-    assertNotNull(mFileSystem.getStatus(TEST_FILE_URI, GetStatusPOptions.newBuilder()
-        .setCommonOptions(optionNoSync())
-        .build()));
+    assertNotNull(mFileSystem.getStatus(TEST_FILE_URI,
+        GetStatusPOptions.newBuilder().setCommonOptions(optionNoSync()).build()));
 
     try (FileInStream fis = mFileSystem.openFile(TEST_FILE_URI,
         OpenFilePOptions.newBuilder().setCommonOptions(optionNoSync()).build())) {
@@ -193,8 +177,8 @@ private void writeThenUpdateFromUfs(boolean clientWriteToUFS)
     }
 
     // This will update/sync metadata from UFS
-    mFileSystem.getStatus(TEST_FILE_URI, GetStatusPOptions.newBuilder()
-        .setCommonOptions(optionSync()).build());
+    mFileSystem.getStatus(TEST_FILE_URI,
+        GetStatusPOptions.newBuilder().setCommonOptions(optionSync()).build());
 
     // metadata is already updated. Even though we are not going to sync metadata in Read(),
     // it should get the latest content.
@@ -208,13 +192,11 @@ private void writeThenUpdateFromUfs(boolean clientWriteToUFS)
   }
 
   private FileSystemMasterCommonPOptions optionNoSync() {
-    return FileSystemMasterCommonPOptions.newBuilder().setSyncIntervalMs(-1)
-        .build();
+    return FileSystemMasterCommonPOptions.newBuilder().setSyncIntervalMs(-1).build();
   }
 
   private FileSystemMasterCommonPOptions optionSync() {
-    return FileSystemMasterCommonPOptions.newBuilder().setSyncIntervalMs(0)
-        .build();
+    return FileSystemMasterCommonPOptions.newBuilder().setSyncIntervalMs(0).build();
   }
 
   /**

From 97702ef458cfa101af45e35b457fb1a2984f5b58 Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Tue, 7 Nov 2023 11:43:01 +0800
Subject: [PATCH 06/14] update

---
 .../java/alluxio/client/file/dora/DoraCacheClient.java     | 2 ++
 .../src/main/java/alluxio/master/LocalAlluxioCluster.java  | 2 ++
 .../alluxio/client/fs/DoraFileSystemIntegrationTest.java   | 7 +++++++
 3 files changed, 11 insertions(+)

diff --git a/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java b/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java
index 1774e14e1a20..2ea2a3c5a744 100644
--- a/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java
+++ b/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java
@@ -252,6 +252,8 @@ protected URIStatus getStatusByGrpc(String path, GetStatusPOptions options)
    */
   public Pair createFile(String path, CreateFilePOptions options)
       throws PermissionDeniedException {
+    System.out.println("---");
+    System.out.println(getWorkerNetAddress(path));
     try (CloseableResource client =
              mContext.acquireBlockWorkerClient(getWorkerNetAddress(path))) {
       CreateFilePRequest request = CreateFilePRequest.newBuilder()
diff --git a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
index ffe53ad4f987..02eaf63f82ab 100644
--- a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
+++ b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
@@ -191,11 +191,13 @@ protected void waitForWorkersServing() throws TimeoutException, InterruptedExcep
     CommonUtils.waitFor("worker starts serving RPCs", () -> {
       try (FileSystemContext fsContext = FileSystemContext.create()) {
         List workerInfoList = fsContext.getCachedWorkers();
+        System.out.println(workerInfoList.size());
         if (mNumWorkers != workerInfoList.size()) {
           return false;
         }
         LOG.info("Observed {} workers in the cluster", workerInfoList.size());
         for (BlockWorkerInfo workerInfo : workerInfoList) {
+          System.out.println(workerInfo.getNetAddress());
           try (CloseableResource blockWorkerClient =
                    fsContext.acquireBlockWorkerClient(workerInfo.getNetAddress())) {
             AlluxioURI rootUri = new AlluxioURI("/");
diff --git a/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java
index 292e689cf00b..11c3ca2c0386 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/fs/DoraFileSystemIntegrationTest.java
@@ -11,6 +11,7 @@
 
 package alluxio.client.fs;
 
+import static java.lang.Thread.sleep;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThrows;
@@ -126,6 +127,7 @@ private void writeThenDeleteFromUfs(boolean clientWriteToUFS)
     LocalAlluxioClusterResource clusterResource = mLocalAlluxioClusterResourceBuilder.build();
     startCluster(clusterResource);
 
+//    sleep(1000);
     FileOutStream fos = mFileSystem.createFile(TEST_FILE_URI,
         CreateFilePOptions.newBuilder().setOverwrite(true).build());
     fos.write(TEST_CONTENT.getBytes());
@@ -161,6 +163,7 @@ private void writeThenUpdateFromUfs(boolean clientWriteToUFS)
     LocalAlluxioClusterResource clusterResource = mLocalAlluxioClusterResourceBuilder.build();
     startCluster(clusterResource);
 
+    sleep(1000);
     FileOutStream fos = mFileSystem.createFile(TEST_FILE_URI,
         CreateFilePOptions.newBuilder().setOverwrite(true).build());
     fos.write(TEST_CONTENT.getBytes());
@@ -227,6 +230,10 @@ public void testWriteThenDeleteFromUfsNotThrough() throws Exception {
   @Test
   public void testWriteThenUpdateFromUfs() throws Exception {
     writeThenUpdateFromUfs(true);
+  }
+
+  @Test
+  public void testWriteThenUpdateFromUfsNotThrough() throws Exception {
     writeThenUpdateFromUfs(false);
   }
 

From 9e4d454ffb9458f807d46bfba18381c0cd19e1a8 Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Thu, 30 Nov 2023 11:27:02 +0800
Subject: [PATCH 07/14] fix some bugs

---
 .../src/main/java/alluxio/client/file/dora/DoraCacheClient.java | 2 --
 .../src/main/java/alluxio/master/LocalAlluxioCluster.java       | 2 --
 2 files changed, 4 deletions(-)

diff --git a/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java b/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java
index 9ed82fecd315..5ae4273e4c3f 100644
--- a/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java
+++ b/dora/core/client/fs/src/main/java/alluxio/client/file/dora/DoraCacheClient.java
@@ -247,8 +247,6 @@ protected URIStatus getStatusByGrpc(String path, GetStatusPOptions options)
    */
   public Pair createFile(String path, CreateFilePOptions options)
       throws PermissionDeniedException {
-    System.out.println("---");
-    System.out.println(getWorkerNetAddress(path));
     try (CloseableResource client =
              mContext.acquireBlockWorkerClient(getWorkerNetAddress(path))) {
       CreateFilePRequest request = CreateFilePRequest.newBuilder()
diff --git a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
index 02eaf63f82ab..ffe53ad4f987 100644
--- a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
+++ b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
@@ -191,13 +191,11 @@ protected void waitForWorkersServing() throws TimeoutException, InterruptedExcep
     CommonUtils.waitFor("worker starts serving RPCs", () -> {
       try (FileSystemContext fsContext = FileSystemContext.create()) {
         List workerInfoList = fsContext.getCachedWorkers();
-        System.out.println(workerInfoList.size());
         if (mNumWorkers != workerInfoList.size()) {
           return false;
         }
         LOG.info("Observed {} workers in the cluster", workerInfoList.size());
         for (BlockWorkerInfo workerInfo : workerInfoList) {
-          System.out.println(workerInfo.getNetAddress());
           try (CloseableResource blockWorkerClient =
                    fsContext.acquireBlockWorkerClient(workerInfo.getNetAddress())) {
             AlluxioURI rootUri = new AlluxioURI("/");

From 57759d487272b3f26adb26a10aad08fcd1d9fcfa Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Thu, 30 Nov 2023 11:35:29 +0800
Subject: [PATCH 08/14] Update DoraLsCommandIntegrationTest.java

---
 .../client/cli/fs/command/DoraLsCommandIntegrationTest.java    | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
index b11089108629..5b2fd4683cfe 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
@@ -21,7 +21,6 @@
 import alluxio.grpc.WritePType;
 import alluxio.util.io.BufferUtils;
 
-import org.junit.Ignore;
 import org.junit.Test;
 
 import java.io.IOException;
@@ -135,7 +134,6 @@ public void testLsR() throws Exception {
     );
   }
 
-  @Ignore("Ignore broken test for now")
   @Test
   public void testLsWithSortByAccessTime() throws IOException, AlluxioException {
     String oldFile = "/testRoot/oldFile";
@@ -181,7 +179,6 @@ public void testLsWithSortBySizeAndReverse() throws IOException, AlluxioExceptio
     );
   }
 
-  @Ignore("Ignore broken test for now")
   @Test
   public void testLsWithSortByCreationTime() throws IOException, AlluxioException {
     String oldFile = "/testRoot/oldFile";

From 667728692020ccdd18b23aef61c4a2648209beff Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Thu, 30 Nov 2023 17:00:45 +0800
Subject: [PATCH 09/14] fix the integrationTest bug

---
 cli/src/alluxio.org/cli/cmd/fs/ls.go          | 202 +++++++++---------
 .../command/DoraLsCommandIntegrationTest.java |   6 +-
 2 files changed, 105 insertions(+), 103 deletions(-)

diff --git a/cli/src/alluxio.org/cli/cmd/fs/ls.go b/cli/src/alluxio.org/cli/cmd/fs/ls.go
index 562ce2873ad3..2d05f7136746 100644
--- a/cli/src/alluxio.org/cli/cmd/fs/ls.go
+++ b/cli/src/alluxio.org/cli/cmd/fs/ls.go
@@ -12,139 +12,139 @@
 package fs
 
 import (
-	"fmt"
-	"strings"
+    "fmt"
+    "strings"
 
-	"github.com/palantir/stacktrace"
-	"github.com/spf13/cobra"
+    "github.com/palantir/stacktrace"
+    "github.com/spf13/cobra"
 
-	"alluxio.org/cli/env"
+    "alluxio.org/cli/env"
 )
 
 func Ls(className string) env.Command {
-	return &LsCommand{
-		BaseJavaCommand: &env.BaseJavaCommand{
-			CommandName:   "ls",
-			JavaClassName: className,
-			Parameters:    []string{"ls"},
-		},
-	}
+    return &LsCommand{
+        BaseJavaCommand: &env.BaseJavaCommand{
+            CommandName:   "ls",
+            JavaClassName: className,
+            Parameters:    []string{"ls"},
+        },
+    }
 }
 
 type LsCommand struct {
-	*env.BaseJavaCommand
+    *env.BaseJavaCommand
 
-	listDirAsFile     bool
-	forceLoadMetadata bool
-	isHumanReadable   bool
-	omitMountInfo     bool
-	pinnedFileOnly    bool
-	isRecursive       bool
-	isReverse         bool
-	sortBy            string
-	timestamp         string
+    listDirAsFile     bool
+    forceLoadMetadata bool
+    isHumanReadable   bool
+    omitMountInfo     bool
+    pinnedFileOnly    bool
+    isRecursive       bool
+    isReverse         bool
+    sortBy            string
+    timestamp         string
 }
 
 func (c *LsCommand) Base() *env.BaseJavaCommand {
-	return c.BaseJavaCommand
+    return c.BaseJavaCommand
 }
 
 var (
-	sortOptions = []string{
-		"creationTime",
-		"inMemoryPercentage",
-		"lastAccessTime",
-		"lastModificationTime",
-		"name",
-		"path",
-		"size",
-	}
-	timestampOptions = []string{
-		"createdTime",
-		"lastAccessTime",
-		"lastModifiedTime",
-	}
+    sortOptions = []string{
+        "creationTime",
+        "inMemoryPercentage",
+        "lastAccessTime",
+        "lastModificationTime",
+        "name",
+        "path",
+        "size",
+    }
+    timestampOptions = []string{
+        "creationTime",
+        "lastAccessTime",
+        "lastModifiedTime",
+    }
 )
 
 func (c *LsCommand) ToCommand() *cobra.Command {
-	cmd := c.Base().InitRunJavaClassCmd(&cobra.Command{
-		Use:   "ls [path]",
-		Short: "Prints information for files and directories at the given path",
-		Long: `The ls command lists all the immediate children in a directory and displays the file size, last modification time, and in memory status of the files.
+    cmd := c.Base().InitRunJavaClassCmd(&cobra.Command{
+        Use:   "ls [path]",
+        Short: "Prints information for files and directories at the given path",
+        Long: `The ls command lists all the immediate children in a directory and displays the file size, last modification time, and in memory status of the files.
 Using ls on a file will only display the information for that specific file.
 
 The ls command will also load the metadata for any file or immediate children of a directory from the under storage system to Alluxio namespace if it does not exist in Alluxio.
 It queries the under storage system for any file or directory matching the given path and creates a mirror of the file in Alluxio backed by that file.
 Only the metadata, such as the file name and size, are loaded this way and no data transfer occurs.`,
-		Example: `# List and load metadata for all immediate children of /s3/data
+        Example: `# List and load metadata for all immediate children of /s3/data
 $ ./bin/alluxio fs ls /s3/data
 
 # Force loading metadata of /s3/data
 $ ./bin/alluxio fs ls -f /s3/data`,
-		Args: cobra.ExactArgs(1),
-		RunE: func(cmd *cobra.Command, args []string) error {
-			return c.Run(args)
-		},
-	})
-	// special case to overwrite the -h shorthand for --help flag for --human-readable
-	cmd.PersistentFlags().BoolP("help", "", false, "help for this command")
+        Args: cobra.ExactArgs(1),
+        RunE: func(cmd *cobra.Command, args []string) error {
+            return c.Run(args)
+        },
+    })
+    // special case to overwrite the -h shorthand for --help flag for --human-readable
+    cmd.PersistentFlags().BoolP("help", "", false, "help for this command")
 
-	cmd.Flags().BoolVarP(&c.listDirAsFile, "list-dir-as-file", "d", false, "List directories as files")
-	cmd.Flags().BoolVarP(&c.forceLoadMetadata, "load-metadata", "f", false, "Force load metadata for immediate children in a directory")
-	cmd.Flags().BoolVarP(&c.isHumanReadable, "human-readable", "h", false, "Print sizes in human readable format")
-	cmd.Flags().BoolVarP(&c.omitMountInfo, "omit-mount-info", "m", false, "Omit mount point related information such as the UFS path")
-	cmd.Flags().BoolVarP(&c.pinnedFileOnly, "pinned-files", "p", false, "Only show pinned files")
-	cmd.Flags().BoolVarP(&c.isRecursive, "recursive", "R", false, "List subdirectories recursively")
-	cmd.Flags().BoolVarP(&c.isReverse, "reverse", "r", false, "Reverse sorted order")
-	cmd.Flags().StringVar(&c.sortBy, "sort", "", fmt.Sprintf("Sort entries by column, one of {%v}", strings.Join(sortOptions, "|")))
-	cmd.Flags().StringVar(&c.timestamp, "timestamp", "", fmt.Sprintf("Display specified timestamp of entry, one of {%v}", strings.Join(timestampOptions, "|")))
-	return cmd
+    cmd.Flags().BoolVarP(&c.listDirAsFile, "list-dir-as-file", "d", false, "List directories as files")
+    cmd.Flags().BoolVarP(&c.forceLoadMetadata, "load-metadata", "f", false, "Force load metadata for immediate children in a directory")
+    cmd.Flags().BoolVarP(&c.isHumanReadable, "human-readable", "h", false, "Print sizes in human readable format")
+    cmd.Flags().BoolVarP(&c.omitMountInfo, "omit-mount-info", "m", false, "Omit mount point related information such as the UFS path")
+    cmd.Flags().BoolVarP(&c.pinnedFileOnly, "pinned-files", "p", false, "Only show pinned files")
+    cmd.Flags().BoolVarP(&c.isRecursive, "recursive", "R", false, "List subdirectories recursively")
+    cmd.Flags().BoolVarP(&c.isReverse, "reverse", "r", false, "Reverse sorted order")
+    cmd.Flags().StringVar(&c.sortBy, "sort", "", fmt.Sprintf("Sort entries by column, one of {%v}", strings.Join(sortOptions, "|")))
+    cmd.Flags().StringVar(&c.timestamp, "timestamp", "", fmt.Sprintf("Display specified timestamp of entry, one of {%v}", strings.Join(timestampOptions, "|")))
+    return cmd
 }
 
 func (c *LsCommand) Run(args []string) error {
-	var javaArgs []string
-	if c.listDirAsFile {
-		javaArgs = append(javaArgs, "-d")
-	}
-	if c.forceLoadMetadata {
-		javaArgs = append(javaArgs, "-f")
-	}
-	if c.isHumanReadable {
-		javaArgs = append(javaArgs, "-h")
-	}
-	if c.omitMountInfo {
-		javaArgs = append(javaArgs, "-m")
-	}
-	if c.pinnedFileOnly {
-		javaArgs = append(javaArgs, "-p")
-	}
-	if c.isRecursive {
-		javaArgs = append(javaArgs, "-R")
-	}
-	if c.isReverse {
-		javaArgs = append(javaArgs, "-r")
-	}
-	if c.sortBy != "" {
-		if err := checkAllowed(c.sortBy, sortOptions...); err != nil {
-			return stacktrace.Propagate(err, "error validating sort options")
-		}
-		javaArgs = append(javaArgs, "--sort", c.sortBy)
-	}
-	if c.timestamp != "" {
-		if err := checkAllowed(c.timestamp, timestampOptions...); err != nil {
-			return stacktrace.Propagate(err, "error validating timestamp options")
-		}
-		javaArgs = append(javaArgs, "--timestamp", c.timestamp)
-	}
-	javaArgs = append(javaArgs, args...)
-	return c.Base().Run(javaArgs)
+    var javaArgs []string
+    if c.listDirAsFile {
+        javaArgs = append(javaArgs, "-d")
+    }
+    if c.forceLoadMetadata {
+        javaArgs = append(javaArgs, "-f")
+    }
+    if c.isHumanReadable {
+        javaArgs = append(javaArgs, "-h")
+    }
+    if c.omitMountInfo {
+        javaArgs = append(javaArgs, "-m")
+    }
+    if c.pinnedFileOnly {
+        javaArgs = append(javaArgs, "-p")
+    }
+    if c.isRecursive {
+        javaArgs = append(javaArgs, "-R")
+    }
+    if c.isReverse {
+        javaArgs = append(javaArgs, "-r")
+    }
+    if c.sortBy != "" {
+        if err := checkAllowed(c.sortBy, sortOptions...); err != nil {
+            return stacktrace.Propagate(err, "error validating sort options")
+        }
+        javaArgs = append(javaArgs, "--sort", c.sortBy)
+    }
+    if c.timestamp != "" {
+        if err := checkAllowed(c.timestamp, timestampOptions...); err != nil {
+            return stacktrace.Propagate(err, "error validating timestamp options")
+        }
+        javaArgs = append(javaArgs, "--timestamp", c.timestamp)
+    }
+    javaArgs = append(javaArgs, args...)
+    return c.Base().Run(javaArgs)
 }
 
 func checkAllowed(val string, allowed ...string) error {
-	for _, i := range allowed {
-		if val == i {
-			return nil
-		}
-	}
-	return stacktrace.NewError("value %v must be one of %v", val, strings.Join(allowed, ","))
+    for _, i := range allowed {
+        if val == i {
+            return nil
+        }
+    }
+    return stacktrace.NewError("value %v must be one of %v", val, strings.Join(allowed, ","))
 }
diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
index 5b2fd4683cfe..e378ce009677 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
@@ -142,7 +142,8 @@ public void testLsWithSortByAccessTime() throws IOException, AlluxioException {
         WritePType.CACHE_THROUGH);
     createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB),
         WritePType.CACHE_THROUGH);
-    assertEquals(0, mFsShell.run("ls", "--sort", "lastAccessTime", "/testRoot"));
+    assertEquals(0, mFsShell.run("ls", "--sort", "lastAccessTime", "--timestamp", "lastAccessTime",
+        "/testRoot"));
     checkOutput(
         ".*FILE " + oldFile,
         ".*FILE " + newFile
@@ -187,7 +188,8 @@ public void testLsWithSortByCreationTime() throws IOException, AlluxioException
         WritePType.CACHE_THROUGH);
     createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB),
         WritePType.CACHE_THROUGH);
-    assertEquals(0, mFsShell.run("ls", "--sort", "creationTime", "/testRoot"));
+    assertEquals(0,
+        mFsShell.run("ls", "--sort", "creationTime", "--timestamp", "creationTime", "/testRoot"));
     checkOutput(
         ".*FILE " + oldFile,
         ".*FILE " + newFile

From d09a7d2df5517b8e1eba9ecfaae1e99eca0993fd Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Tue, 5 Dec 2023 16:48:44 +0800
Subject: [PATCH 10/14] Update DoraLsCommandIntegrationTest.java

---
 .../command/DoraLsCommandIntegrationTest.java | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
index e378ce009677..0a1b22882077 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
@@ -21,6 +21,7 @@
 import alluxio.grpc.WritePType;
 import alluxio.util.io.BufferUtils;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.io.IOException;
@@ -134,6 +135,7 @@ public void testLsR() throws Exception {
     );
   }
 
+  @Ignore("UfsStatus doesn't support lastAccessTime")
   @Test
   public void testLsWithSortByAccessTime() throws IOException, AlluxioException {
     String oldFile = "/testRoot/oldFile";
@@ -180,6 +182,7 @@ public void testLsWithSortBySizeAndReverse() throws IOException, AlluxioExceptio
     );
   }
 
+  @Ignore("UfsStatus doesn't support creationTime")
   @Test
   public void testLsWithSortByCreationTime() throws IOException, AlluxioException {
     String oldFile = "/testRoot/oldFile";
@@ -209,6 +212,22 @@ public void testLsWithInvalidSortOption() throws IOException, AlluxioException {
     assertEquals(expected, mOutput.toString());
   }
 
+  @Test
+  public void testLsWithSortByLastModificationTime() throws IOException, AlluxioException {
+    String oldFile = "/testRoot/oldFile";
+    String newFile = "/testRoot/newFile";
+    createByteFileInAlluxio(oldFile, BufferUtils.getIncreasingByteArray(Constants.MB),
+        WritePType.CACHE_THROUGH);
+    createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB),
+        WritePType.CACHE_THROUGH);
+    assertEquals(0, mFsShell.run("ls", "--sort", "lastModificationTime", "--timestamp",
+        "lastModificationTime", "/testRoot"));
+    checkOutput(
+        ".*FILE " + oldFile,
+        ".*FILE " + newFile
+    );
+  }
+
   private void checkOutput(String... linePatterns) {
     String[] actualLines = mOutput.toString().split("\n");
     assertEquals("Output: ", linePatterns.length, actualLines.length);

From 271b70589bc16e2a26d6328c50e8030c5dd6cf50 Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Tue, 12 Dec 2023 16:07:14 +0800
Subject: [PATCH 11/14] Revert "fix the integrationTest bug"

This reverts commit 667728692020ccdd18b23aef61c4a2648209beff.
---
 cli/src/alluxio.org/cli/cmd/fs/ls.go          | 202 +++++++++---------
 .../command/DoraLsCommandIntegrationTest.java |   6 +-
 2 files changed, 103 insertions(+), 105 deletions(-)

diff --git a/cli/src/alluxio.org/cli/cmd/fs/ls.go b/cli/src/alluxio.org/cli/cmd/fs/ls.go
index 2d05f7136746..562ce2873ad3 100644
--- a/cli/src/alluxio.org/cli/cmd/fs/ls.go
+++ b/cli/src/alluxio.org/cli/cmd/fs/ls.go
@@ -12,139 +12,139 @@
 package fs
 
 import (
-    "fmt"
-    "strings"
+	"fmt"
+	"strings"
 
-    "github.com/palantir/stacktrace"
-    "github.com/spf13/cobra"
+	"github.com/palantir/stacktrace"
+	"github.com/spf13/cobra"
 
-    "alluxio.org/cli/env"
+	"alluxio.org/cli/env"
 )
 
 func Ls(className string) env.Command {
-    return &LsCommand{
-        BaseJavaCommand: &env.BaseJavaCommand{
-            CommandName:   "ls",
-            JavaClassName: className,
-            Parameters:    []string{"ls"},
-        },
-    }
+	return &LsCommand{
+		BaseJavaCommand: &env.BaseJavaCommand{
+			CommandName:   "ls",
+			JavaClassName: className,
+			Parameters:    []string{"ls"},
+		},
+	}
 }
 
 type LsCommand struct {
-    *env.BaseJavaCommand
+	*env.BaseJavaCommand
 
-    listDirAsFile     bool
-    forceLoadMetadata bool
-    isHumanReadable   bool
-    omitMountInfo     bool
-    pinnedFileOnly    bool
-    isRecursive       bool
-    isReverse         bool
-    sortBy            string
-    timestamp         string
+	listDirAsFile     bool
+	forceLoadMetadata bool
+	isHumanReadable   bool
+	omitMountInfo     bool
+	pinnedFileOnly    bool
+	isRecursive       bool
+	isReverse         bool
+	sortBy            string
+	timestamp         string
 }
 
 func (c *LsCommand) Base() *env.BaseJavaCommand {
-    return c.BaseJavaCommand
+	return c.BaseJavaCommand
 }
 
 var (
-    sortOptions = []string{
-        "creationTime",
-        "inMemoryPercentage",
-        "lastAccessTime",
-        "lastModificationTime",
-        "name",
-        "path",
-        "size",
-    }
-    timestampOptions = []string{
-        "creationTime",
-        "lastAccessTime",
-        "lastModifiedTime",
-    }
+	sortOptions = []string{
+		"creationTime",
+		"inMemoryPercentage",
+		"lastAccessTime",
+		"lastModificationTime",
+		"name",
+		"path",
+		"size",
+	}
+	timestampOptions = []string{
+		"createdTime",
+		"lastAccessTime",
+		"lastModifiedTime",
+	}
 )
 
 func (c *LsCommand) ToCommand() *cobra.Command {
-    cmd := c.Base().InitRunJavaClassCmd(&cobra.Command{
-        Use:   "ls [path]",
-        Short: "Prints information for files and directories at the given path",
-        Long: `The ls command lists all the immediate children in a directory and displays the file size, last modification time, and in memory status of the files.
+	cmd := c.Base().InitRunJavaClassCmd(&cobra.Command{
+		Use:   "ls [path]",
+		Short: "Prints information for files and directories at the given path",
+		Long: `The ls command lists all the immediate children in a directory and displays the file size, last modification time, and in memory status of the files.
 Using ls on a file will only display the information for that specific file.
 
 The ls command will also load the metadata for any file or immediate children of a directory from the under storage system to Alluxio namespace if it does not exist in Alluxio.
 It queries the under storage system for any file or directory matching the given path and creates a mirror of the file in Alluxio backed by that file.
 Only the metadata, such as the file name and size, are loaded this way and no data transfer occurs.`,
-        Example: `# List and load metadata for all immediate children of /s3/data
+		Example: `# List and load metadata for all immediate children of /s3/data
 $ ./bin/alluxio fs ls /s3/data
 
 # Force loading metadata of /s3/data
 $ ./bin/alluxio fs ls -f /s3/data`,
-        Args: cobra.ExactArgs(1),
-        RunE: func(cmd *cobra.Command, args []string) error {
-            return c.Run(args)
-        },
-    })
-    // special case to overwrite the -h shorthand for --help flag for --human-readable
-    cmd.PersistentFlags().BoolP("help", "", false, "help for this command")
+		Args: cobra.ExactArgs(1),
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return c.Run(args)
+		},
+	})
+	// special case to overwrite the -h shorthand for --help flag for --human-readable
+	cmd.PersistentFlags().BoolP("help", "", false, "help for this command")
 
-    cmd.Flags().BoolVarP(&c.listDirAsFile, "list-dir-as-file", "d", false, "List directories as files")
-    cmd.Flags().BoolVarP(&c.forceLoadMetadata, "load-metadata", "f", false, "Force load metadata for immediate children in a directory")
-    cmd.Flags().BoolVarP(&c.isHumanReadable, "human-readable", "h", false, "Print sizes in human readable format")
-    cmd.Flags().BoolVarP(&c.omitMountInfo, "omit-mount-info", "m", false, "Omit mount point related information such as the UFS path")
-    cmd.Flags().BoolVarP(&c.pinnedFileOnly, "pinned-files", "p", false, "Only show pinned files")
-    cmd.Flags().BoolVarP(&c.isRecursive, "recursive", "R", false, "List subdirectories recursively")
-    cmd.Flags().BoolVarP(&c.isReverse, "reverse", "r", false, "Reverse sorted order")
-    cmd.Flags().StringVar(&c.sortBy, "sort", "", fmt.Sprintf("Sort entries by column, one of {%v}", strings.Join(sortOptions, "|")))
-    cmd.Flags().StringVar(&c.timestamp, "timestamp", "", fmt.Sprintf("Display specified timestamp of entry, one of {%v}", strings.Join(timestampOptions, "|")))
-    return cmd
+	cmd.Flags().BoolVarP(&c.listDirAsFile, "list-dir-as-file", "d", false, "List directories as files")
+	cmd.Flags().BoolVarP(&c.forceLoadMetadata, "load-metadata", "f", false, "Force load metadata for immediate children in a directory")
+	cmd.Flags().BoolVarP(&c.isHumanReadable, "human-readable", "h", false, "Print sizes in human readable format")
+	cmd.Flags().BoolVarP(&c.omitMountInfo, "omit-mount-info", "m", false, "Omit mount point related information such as the UFS path")
+	cmd.Flags().BoolVarP(&c.pinnedFileOnly, "pinned-files", "p", false, "Only show pinned files")
+	cmd.Flags().BoolVarP(&c.isRecursive, "recursive", "R", false, "List subdirectories recursively")
+	cmd.Flags().BoolVarP(&c.isReverse, "reverse", "r", false, "Reverse sorted order")
+	cmd.Flags().StringVar(&c.sortBy, "sort", "", fmt.Sprintf("Sort entries by column, one of {%v}", strings.Join(sortOptions, "|")))
+	cmd.Flags().StringVar(&c.timestamp, "timestamp", "", fmt.Sprintf("Display specified timestamp of entry, one of {%v}", strings.Join(timestampOptions, "|")))
+	return cmd
 }
 
 func (c *LsCommand) Run(args []string) error {
-    var javaArgs []string
-    if c.listDirAsFile {
-        javaArgs = append(javaArgs, "-d")
-    }
-    if c.forceLoadMetadata {
-        javaArgs = append(javaArgs, "-f")
-    }
-    if c.isHumanReadable {
-        javaArgs = append(javaArgs, "-h")
-    }
-    if c.omitMountInfo {
-        javaArgs = append(javaArgs, "-m")
-    }
-    if c.pinnedFileOnly {
-        javaArgs = append(javaArgs, "-p")
-    }
-    if c.isRecursive {
-        javaArgs = append(javaArgs, "-R")
-    }
-    if c.isReverse {
-        javaArgs = append(javaArgs, "-r")
-    }
-    if c.sortBy != "" {
-        if err := checkAllowed(c.sortBy, sortOptions...); err != nil {
-            return stacktrace.Propagate(err, "error validating sort options")
-        }
-        javaArgs = append(javaArgs, "--sort", c.sortBy)
-    }
-    if c.timestamp != "" {
-        if err := checkAllowed(c.timestamp, timestampOptions...); err != nil {
-            return stacktrace.Propagate(err, "error validating timestamp options")
-        }
-        javaArgs = append(javaArgs, "--timestamp", c.timestamp)
-    }
-    javaArgs = append(javaArgs, args...)
-    return c.Base().Run(javaArgs)
+	var javaArgs []string
+	if c.listDirAsFile {
+		javaArgs = append(javaArgs, "-d")
+	}
+	if c.forceLoadMetadata {
+		javaArgs = append(javaArgs, "-f")
+	}
+	if c.isHumanReadable {
+		javaArgs = append(javaArgs, "-h")
+	}
+	if c.omitMountInfo {
+		javaArgs = append(javaArgs, "-m")
+	}
+	if c.pinnedFileOnly {
+		javaArgs = append(javaArgs, "-p")
+	}
+	if c.isRecursive {
+		javaArgs = append(javaArgs, "-R")
+	}
+	if c.isReverse {
+		javaArgs = append(javaArgs, "-r")
+	}
+	if c.sortBy != "" {
+		if err := checkAllowed(c.sortBy, sortOptions...); err != nil {
+			return stacktrace.Propagate(err, "error validating sort options")
+		}
+		javaArgs = append(javaArgs, "--sort", c.sortBy)
+	}
+	if c.timestamp != "" {
+		if err := checkAllowed(c.timestamp, timestampOptions...); err != nil {
+			return stacktrace.Propagate(err, "error validating timestamp options")
+		}
+		javaArgs = append(javaArgs, "--timestamp", c.timestamp)
+	}
+	javaArgs = append(javaArgs, args...)
+	return c.Base().Run(javaArgs)
 }
 
 func checkAllowed(val string, allowed ...string) error {
-    for _, i := range allowed {
-        if val == i {
-            return nil
-        }
-    }
-    return stacktrace.NewError("value %v must be one of %v", val, strings.Join(allowed, ","))
+	for _, i := range allowed {
+		if val == i {
+			return nil
+		}
+	}
+	return stacktrace.NewError("value %v must be one of %v", val, strings.Join(allowed, ","))
 }
diff --git a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
index 0a1b22882077..9fef0146b9d9 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/cli/fs/command/DoraLsCommandIntegrationTest.java
@@ -144,8 +144,7 @@ public void testLsWithSortByAccessTime() throws IOException, AlluxioException {
         WritePType.CACHE_THROUGH);
     createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB),
         WritePType.CACHE_THROUGH);
-    assertEquals(0, mFsShell.run("ls", "--sort", "lastAccessTime", "--timestamp", "lastAccessTime",
-        "/testRoot"));
+    assertEquals(0, mFsShell.run("ls", "--sort", "lastAccessTime", "/testRoot"));
     checkOutput(
         ".*FILE " + oldFile,
         ".*FILE " + newFile
@@ -191,8 +190,7 @@ public void testLsWithSortByCreationTime() throws IOException, AlluxioException
         WritePType.CACHE_THROUGH);
     createByteFileInAlluxio(newFile, BufferUtils.getIncreasingByteArray(Constants.MB),
         WritePType.CACHE_THROUGH);
-    assertEquals(0,
-        mFsShell.run("ls", "--sort", "creationTime", "--timestamp", "creationTime", "/testRoot"));
+    assertEquals(0, mFsShell.run("ls", "--sort", "creationTime", "/testRoot"));
     checkOutput(
         ".*FILE " + oldFile,
         ".*FILE " + newFile

From 035a61cbd1185757afe3ba7ca8fb238487f71206 Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Thu, 28 Dec 2023 14:37:03 +0800
Subject: [PATCH 12/14] Update LocalAlluxioCluster.java

---
 .../java/alluxio/master/LocalAlluxioCluster.java    | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
index 7fb430619a98..43b854fb98c9 100644
--- a/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
+++ b/dora/minicluster/src/main/java/alluxio/master/LocalAlluxioCluster.java
@@ -15,11 +15,16 @@
 import alluxio.ClientContext;
 import alluxio.ConfigurationTestUtils;
 import alluxio.client.block.BlockMasterClient;
+import alluxio.client.block.stream.BlockWorkerClient;
+import alluxio.client.file.DoraCacheFileSystem;
 import alluxio.client.file.FileSystem;
 import alluxio.client.file.FileSystemContext;
 import alluxio.conf.Configuration;
 import alluxio.conf.PropertyKey;
+import alluxio.grpc.GetStatusPRequest;
+import alluxio.grpc.GetStatusPResponse;
 import alluxio.membership.WorkerClusterView;
+import alluxio.resource.CloseableResource;
 import alluxio.util.CommonUtils;
 import alluxio.util.WaitForOptions;
 import alluxio.wire.WorkerInfo;
@@ -185,14 +190,14 @@ protected void waitForMasterServing() throws TimeoutException, InterruptedExcept
   protected void waitForWorkersServing() throws TimeoutException, InterruptedException {
     CommonUtils.waitFor("worker starts serving RPCs", () -> {
       try (FileSystemContext fsContext = FileSystemContext.create()) {
-        List workerInfoList = fsContext.getCachedWorkers();
+        WorkerClusterView workerInfoList = fsContext.getCachedWorkers();
         if (mNumWorkers != workerInfoList.size()) {
           return false;
         }
         LOG.info("Observed {} workers in the cluster", workerInfoList.size());
-        for (BlockWorkerInfo workerInfo : workerInfoList) {
+        for (WorkerInfo workerInfo : workerInfoList) {
           try (CloseableResource blockWorkerClient =
-                   fsContext.acquireBlockWorkerClient(workerInfo.getNetAddress())) {
+                   fsContext.acquireBlockWorkerClient(workerInfo.getAddress())) {
             AlluxioURI rootUri = new AlluxioURI("/");
             FileSystem masterFs = mMaster.getClient();
             DoraCacheFileSystem doraCacheFs = masterFs.getDoraCacheFileSystem();
@@ -204,7 +209,7 @@ protected void waitForWorkersServing() throws TimeoutException, InterruptedExcep
               return false;
             }
           } catch (IOException ioe) {
-            LOG.error("Failed to connect to worker {}: {}", workerInfo.getNetAddress(), ioe);
+            LOG.error("Failed to connect to worker {}: {}", workerInfo.getAddress(), ioe);
             return false;
           }
         }

From 22d0ef573aeacae4fae4a1b6b10adb5dbf30a4f9 Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Thu, 28 Dec 2023 15:27:20 +0800
Subject: [PATCH 13/14] Update CreateBucketTest.java

---
 .../src/test/java/alluxio/client/rest/CreateBucketTest.java | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/dora/tests/integration/src/test/java/alluxio/client/rest/CreateBucketTest.java b/dora/tests/integration/src/test/java/alluxio/client/rest/CreateBucketTest.java
index 3dbaf6bfbab3..ce194e9a2b01 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/rest/CreateBucketTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/rest/CreateBucketTest.java
@@ -53,11 +53,13 @@ public class CreateBucketTest extends RestApiTest {
           .setProperty(PropertyKey.UNDERFS_S3_ENDPOINT, "localhost:" + UFS_PORT)
           .setProperty(PropertyKey.UNDERFS_S3_ENDPOINT_REGION, "us-west-2")
           .setProperty(PropertyKey.UNDERFS_S3_DISABLE_DNS_BUCKETS, true)
-          .setProperty(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS, "s3://" + TEST_BUCKET)
-          .setProperty(PropertyKey.DORA_CLIENT_UFS_ROOT, "s3://" + TEST_BUCKET)
+          .setProperty(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS, "s3://" + TEST_BUCKET + "/")
+          .setProperty(PropertyKey.DORA_CLIENT_UFS_ROOT, "s3://" + TEST_BUCKET + "/")
           .setProperty(PropertyKey.WORKER_HTTP_SERVER_ENABLED, false)
           .setProperty(PropertyKey.S3A_ACCESS_KEY, mS3Proxy.getAccessKey())
           .setProperty(PropertyKey.S3A_SECRET_KEY, mS3Proxy.getSecretKey())
+          .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false)
+          .setProperty(PropertyKey.DORA_CLIENT_UFS_FALLBACK_ENABLED, false)
           .setNumWorkers(1)
           .build();
 

From 43b6d74e601b6c7f572c4abf2baa34a584ae7856 Mon Sep 17 00:00:00 2001
From: thu-david 
Date: Thu, 28 Dec 2023 15:46:21 +0800
Subject: [PATCH 14/14] Update S3ObjectTest.java

---
 .../src/test/java/alluxio/client/rest/S3ObjectTest.java  | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/dora/tests/integration/src/test/java/alluxio/client/rest/S3ObjectTest.java b/dora/tests/integration/src/test/java/alluxio/client/rest/S3ObjectTest.java
index 76e6c7692177..3dd5820d98b3 100644
--- a/dora/tests/integration/src/test/java/alluxio/client/rest/S3ObjectTest.java
+++ b/dora/tests/integration/src/test/java/alluxio/client/rest/S3ObjectTest.java
@@ -64,12 +64,13 @@ public class S3ObjectTest extends RestApiTest {
           .setProperty(PropertyKey.UNDERFS_S3_ENDPOINT, "localhost:" + UFS_PORT)
           .setProperty(PropertyKey.UNDERFS_S3_ENDPOINT_REGION, "us-west-2")
           .setProperty(PropertyKey.UNDERFS_S3_DISABLE_DNS_BUCKETS, true)
-          .setProperty(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS, "s3://" + TEST_BUCKET)
-          .setProperty(PropertyKey.DORA_CLIENT_UFS_ROOT, "s3://" + TEST_BUCKET)
+          .setProperty(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS, "s3://" + TEST_BUCKET + "/")
+          .setProperty(PropertyKey.DORA_CLIENT_UFS_ROOT, "s3://" + TEST_BUCKET + "/")
+          .setProperty(PropertyKey.DORA_CLIENT_UFS_FALLBACK_ENABLED, false)
           .setProperty(PropertyKey.WORKER_HTTP_SERVER_ENABLED, false)
           .setProperty(PropertyKey.S3A_ACCESS_KEY, mS3Proxy.getAccessKey())
-          .setProperty(PropertyKey.S3A_SECRET_KEY, mS3Proxy.getSecretKey())
-          .setNumWorkers(1)
+          .setProperty(PropertyKey.UNDERFS_XATTR_CHANGE_ENABLED, false)
+          .setNumWorkers(2)
           .build();
 
   @Before