From 0c3524851efe6b4ba4cca33b91ce92c39b2210d5 Mon Sep 17 00:00:00 2001 From: Stepan Usatiuk Date: Mon, 12 May 2025 12:49:10 +0200 Subject: [PATCH] Some javadocs + CI --- .github/workflows/server.yml | 7 +- dhfs-parent/.gitignore | 2 + .../com/usatiuk/dhfsfs/objects/ChunkData.java | 5 + .../objects/ChunkDataProtoSerializer.java | 26 --- .../java/com/usatiuk/dhfsfs/objects/File.java | 8 + .../com/usatiuk/dhfsfs/objects/FileDto.java | 5 + .../usatiuk/dhfsfs/objects/FileDtoMapper.java | 3 + .../usatiuk/dhfsfs/objects/FileHelper.java | 16 ++ .../dhfsfs/objects/FileProtoSerializer.java | 25 --- .../dhfsfs/objects/FileSyncHandler.java | 11 ++ .../JKleppmannTreeNodeMetaDirectory.java | 4 + .../objects/JKleppmannTreeNodeMetaFile.java | 5 + .../dhfsfs/service/DhfsFileService.java | 154 ++++++++++++++++-- .../service/DirectoryNotEmptyException.java | 5 + .../usatiuk/dhfsfs/service/GetattrRes.java | 9 +- dhfs-parent/pom.xml | 14 +- 16 files changed, 229 insertions(+), 70 deletions(-) delete mode 100644 dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkDataProtoSerializer.java delete mode 100644 dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileProtoSerializer.java diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index 30516826..3541bdd8 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -47,7 +47,7 @@ jobs: run: cd thirdparty/lazyfs/ && ./build.sh - name: Test with Maven - run: cd dhfs-parent && mvn -T $(nproc) --batch-mode --update-snapshots package verify + run: cd dhfs-parent && mvn -T $(nproc) --batch-mode --update-snapshots package verify javadoc:aggregate # - name: Build with Maven # run: cd dhfs-parent && mvn --batch-mode --update-snapshots package # -Dquarkus.log.category.\"com.usatiuk.dhfs\".min-level=DEBUG @@ -57,6 +57,11 @@ jobs: name: DHFS Server Package path: dhfs-parent/dhfs-fuse/target/quarkus-app + - uses: actions/upload-artifact@v4 + with: + name: DHFS Javadocs + path: dhfs-parent/target/reports/apidocs/ + - uses: actions/upload-artifact@v4 if: ${{ always() }} with: diff --git a/dhfs-parent/.gitignore b/dhfs-parent/.gitignore index 8c7863e7..8e2a9c71 100644 --- a/dhfs-parent/.gitignore +++ b/dhfs-parent/.gitignore @@ -41,3 +41,5 @@ nb-configuration.xml # Plugin directory /.quarkus/cli/plugins/ + +.jqwik-database \ No newline at end of file diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkData.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkData.java index ffe0fc31..72def208 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkData.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkData.java @@ -5,6 +5,11 @@ import com.usatiuk.dhfs.remoteobj.JDataRemote; import com.usatiuk.dhfs.remoteobj.JDataRemoteDto; import com.usatiuk.objects.JObjectKey; +/** + * ChunkData is a data structure that represents an immutable binary blob + * @param key unique key + * @param data binary data + */ public record ChunkData(JObjectKey key, ByteString data) implements JDataRemote, JDataRemoteDto { @Override public int estimateSize() { diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkDataProtoSerializer.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkDataProtoSerializer.java deleted file mode 100644 index 482d66d4..00000000 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/ChunkDataProtoSerializer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.usatiuk.dhfsfs.objects; - -import com.usatiuk.dhfs.ProtoSerializer; -import com.usatiuk.dhfs.persistence.ChunkDataP; -import com.usatiuk.dhfs.persistence.JObjectKeyP; -import com.usatiuk.objects.JObjectKey; -import jakarta.inject.Singleton; - -@Singleton -public class ChunkDataProtoSerializer implements ProtoSerializer { - @Override - public ChunkData deserialize(ChunkDataP message) { - return new ChunkData( - JObjectKey.of(message.getKey().getName()), - message.getData() - ); - } - - @Override - public ChunkDataP serialize(ChunkData object) { - return ChunkDataP.newBuilder() - .setKey(JObjectKeyP.newBuilder().setName(object.key().value()).build()) - .setData(object.data()) - .build(); - } -} diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/File.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/File.java index 26aab23d..68314f43 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/File.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/File.java @@ -9,6 +9,14 @@ import com.usatiuk.objects.JObjectKey; import java.util.Collection; import java.util.Set; +/** + * File is a data structure that represents a file in the file system + * @param key unique key + * @param mode file mode + * @param cTime creation time + * @param mTime modification time + * @param symlink true if the file is a symlink, false otherwise + */ public record File(JObjectKey key, long mode, long cTime, long mTime, boolean symlink ) implements JDataRemote, JMapHolder { diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDto.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDto.java index a657427b..3dbe06ff 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDto.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDto.java @@ -7,6 +7,11 @@ import org.apache.commons.lang3.tuple.Pair; import java.util.List; +/** + * FileDto is a data transfer object that contains a file and its chunks. + * @param file the file + * @param chunks the list of chunks, each represented as a pair of a long and a JObjectKey + */ public record FileDto(File file, List> chunks) implements JDataRemoteDto { @Override public Class objClass() { diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDtoMapper.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDtoMapper.java index 2a447248..656caa3b 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDtoMapper.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileDtoMapper.java @@ -5,6 +5,9 @@ import com.usatiuk.dhfs.syncmap.DtoMapper; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +/** + * Maps a {@link File} object to a {@link FileDto} object and vice versa. + */ @ApplicationScoped public class FileDtoMapper implements DtoMapper { @Inject diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileHelper.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileHelper.java index ac53169c..5813ae4d 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileHelper.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileHelper.java @@ -10,11 +10,20 @@ import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.List; +/** + * Helper class for working with files. + */ @ApplicationScoped public class FileHelper { @Inject JMapHelper jMapHelper; + /** + * Get the chunks of a file. + * Transaction is expected to be already started. + * @param file the file to get chunks from + * @return a list of pairs of chunk offset and chunk key + */ public List> getChunks(File file) { ArrayList> chunks = new ArrayList<>(); try (var it = jMapHelper.getIterator(file)) { @@ -26,6 +35,13 @@ public class FileHelper { return List.copyOf(chunks); } + /** + * Replace the chunks of a file. + * All previous chunks will be deleted. + * Transaction is expected to be already started. + * @param file the file to replace chunks in + * @param chunks the list of pairs of chunk offset and chunk key + */ public void replaceChunks(File file, List> chunks) { jMapHelper.deleteAll(file); diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileProtoSerializer.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileProtoSerializer.java deleted file mode 100644 index e9b86c40..00000000 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileProtoSerializer.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.usatiuk.dhfsfs.objects; - -import com.usatiuk.dhfs.ProtoSerializer; -import com.usatiuk.dhfs.persistence.FileDtoP; -import com.usatiuk.utils.SerializationHelper; -import jakarta.inject.Singleton; - -import java.io.IOException; - -@Singleton -public class FileProtoSerializer implements ProtoSerializer { - @Override - public FileDto deserialize(FileDtoP message) { - try (var is = message.getSerializedData().newInput()) { - return SerializationHelper.deserialize(is); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public FileDtoP serialize(FileDto object) { - return FileDtoP.newBuilder().setSerializedData(SerializationHelper.serialize(object)).build(); - } -} diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileSyncHandler.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileSyncHandler.java index 05ae92c4..a95cc2d8 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileSyncHandler.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/FileSyncHandler.java @@ -23,6 +23,9 @@ import javax.annotation.Nullable; import java.util.List; import java.util.Objects; +/** + * Handles synchronization of file objects. + */ @ApplicationScoped public class FileSyncHandler implements ObjSyncHandler { @Inject @@ -45,6 +48,14 @@ public class FileSyncHandler implements ObjSyncHandler { return jKleppmannTreeManager.getTree(JObjectKey.of("fs")).orElseThrow(); } + /** + * Resolve conflict between two file versions, update the file in storage and create a conflict file. + * + * @param from the peer that sent the update + * @param key the key of the file + * @param receivedChangelog the changelog of the received file + * @param receivedData the received file data + */ private void resolveConflict(PeerId from, JObjectKey key, PMap receivedChangelog, @Nullable FileDto receivedData) { var oursCurMeta = curTx.get(RemoteObjectMeta.class, key).orElse(null); diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaDirectory.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaDirectory.java index 50ca6199..50e5b149 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaDirectory.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaDirectory.java @@ -6,6 +6,10 @@ import com.usatiuk.objects.JObjectKey; import java.util.Collection; import java.util.List; +/** + * JKleppmannTreeNodeMetaDirectory is a record that represents a directory in the JKleppmann tree. + * @param name the name of the directory + */ public record JKleppmannTreeNodeMetaDirectory(String name) implements JKleppmannTreeNodeMeta { public JKleppmannTreeNodeMeta withName(String name) { return new JKleppmannTreeNodeMetaDirectory(name); diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaFile.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaFile.java index b4b0c1e0..404a4dc1 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaFile.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/objects/JKleppmannTreeNodeMetaFile.java @@ -6,6 +6,11 @@ import com.usatiuk.objects.JObjectKey; import java.util.Collection; import java.util.List; +/** + * JKleppmannTreeNodeMetaFile is a record that represents a file in the JKleppmann tree. + * @param name the name of the file + * @param fileIno a reference to the `File` object + */ public record JKleppmannTreeNodeMetaFile(String name, JObjectKey fileIno) implements JKleppmannTreeNodeMeta { @Override public JKleppmannTreeNodeMeta withName(String name) { diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DhfsFileService.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DhfsFileService.java index 6478013f..5832f794 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DhfsFileService.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DhfsFileService.java @@ -39,6 +39,9 @@ import java.nio.file.Path; import java.util.*; import java.util.stream.StreamSupport; +/** + * Actual filesystem implementation. + */ @ApplicationScoped public class DhfsFileService { @ConfigProperty(name = "dhfs.files.target_chunk_alignment") @@ -71,6 +74,12 @@ public class DhfsFileService { return jKleppmannTreeManager.getTree(JObjectKey.of("fs"), () -> new JKleppmannTreeNodeMetaDirectory("")); } + /** + * Create a new chunk with the given data and a new unique ID. + * + * @param bytes the data to store in the chunk + * @return the created chunk + */ private ChunkData createChunk(ByteString bytes) { var newChunk = new ChunkData(JObjectKey.of(UUID.randomUUID().toString()), bytes); remoteTx.putDataNew(newChunk); @@ -82,14 +91,7 @@ public class DhfsFileService { getTree(); } - private JKleppmannTreeNode getDirEntryW(String name) { - var res = getTree().traverse(StreamSupport.stream(Path.of(name).spliterator(), false).map(p -> p.toString()).toList()); - if (res == null) throw new StatusRuntimeExceptionNoStacktrace(Status.NOT_FOUND); - var ret = curTx.get(JKleppmannTreeNodeHolder.class, res).map(JKleppmannTreeNodeHolder::node).orElseThrow(() -> new StatusRuntimeException(Status.NOT_FOUND.withDescription("Tree node exists but not found as jObject: " + name))); - return ret; - } - - private JKleppmannTreeNode getDirEntryR(String name) { + private JKleppmannTreeNode getDirEntry(String name) { var res = getTree().traverse(StreamSupport.stream(Path.of(name).spliterator(), false).map(p -> p.toString()).toList()); if (res == null) throw new StatusRuntimeExceptionNoStacktrace(Status.NOT_FOUND); var ret = curTx.get(JKleppmannTreeNodeHolder.class, res).map(JKleppmannTreeNodeHolder::node).orElseThrow(() -> new StatusRuntimeException(Status.NOT_FOUND.withDescription("Tree node exists but not found as jObject: " + name))); @@ -103,6 +105,11 @@ public class DhfsFileService { return ret; } + /** + * Get the attributes of a file or directory. + * @param uuid the UUID of the file or directory + * @return the attributes of the file or directory + */ public Optional getattr(JObjectKey uuid) { return jObjectTxManager.executeTx(() -> { var ref = curTx.get(JData.class, uuid).orElse(null); @@ -124,10 +131,15 @@ public class DhfsFileService { }); } + /** + * Try to resolve a path to a file or directory. + * @param name the path to resolve + * @return the key of the file or directory, or an empty optional if it does not exist + */ public Optional open(String name) { return jObjectTxManager.executeTx(() -> { try { - var ret = getDirEntryR(name); + var ret = getDirEntry(name); return switch (ret.meta()) { case JKleppmannTreeNodeMetaFile f -> Optional.of(f.fileIno()); case JKleppmannTreeNodeMetaDirectory f -> Optional.of(ret.key()); @@ -147,10 +159,16 @@ public class DhfsFileService { throw new StatusRuntimeExceptionNoStacktrace(Status.INVALID_ARGUMENT.withDescription("Not a directory: " + entry.key())); } + /** + * Create a new file with the given name and mode. + * @param name the name of the file + * @param mode the mode of the file + * @return the key of the created file + */ public Optional create(String name, long mode) { return jObjectTxManager.executeTx(() -> { Path path = Path.of(name); - var parent = getDirEntryW(path.getParent().toString()); + var parent = getDirEntry(path.getParent().toString()); ensureDir(parent); @@ -171,9 +189,14 @@ public class DhfsFileService { }); } - //FIXME: Slow.. + /** + * Get the parent directory of a file or directory. + * @param ino the key of the file or directory + * @return the parent directory + */ public Pair inoToParent(JObjectKey ino) { return jObjectTxManager.executeTx(() -> { + // FIXME: Slow return getTree().findParent(w -> { if (w.meta() instanceof JKleppmannTreeNodeMetaFile f) return f.fileIno().equals(ino); @@ -182,20 +205,31 @@ public class DhfsFileService { }); } + /** + * Create a new directory with the given name and mode. + * @param name the name of the directory + * @param mode the mode of the directory + */ public void mkdir(String name, long mode) { jObjectTxManager.executeTx(() -> { Path path = Path.of(name); - var parent = getDirEntryW(path.getParent().toString()); + var parent = getDirEntry(path.getParent().toString()); ensureDir(parent); String dname = path.getFileName().toString(); Log.debug("Creating directory " + name); + // TODO: No modes for directories yet getTree().move(parent.key(), new JKleppmannTreeNodeMetaDirectory(dname), getTree().getNewNodeId()); }); } + /** + * Unlink a file or directory. + * @param name the name of the file or directory + * @throws DirectoryNotEmptyException if the directory is not empty and recursive delete is not allowed + */ public void unlink(String name) { jObjectTxManager.executeTx(() -> { var node = getDirEntryOpt(name).orElse(null); @@ -209,13 +243,19 @@ public class DhfsFileService { }); } + /** + * Rename a file or directory. + * @param from the old name + * @param to the new name + * @return true if the rename was successful, false otherwise + */ public Boolean rename(String from, String to) { return jObjectTxManager.executeTx(() -> { - var node = getDirEntryW(from); + var node = getDirEntry(from); JKleppmannTreeNodeMeta meta = node.meta(); var toPath = Path.of(to); - var toDentry = getDirEntryW(toPath.getParent().toString()); + var toDentry = getDirEntry(toPath.getParent().toString()); ensureDir(toDentry); getTree().move(toDentry.key(), meta.withName(toPath.getFileName().toString()), node.key()); @@ -223,6 +263,12 @@ public class DhfsFileService { }); } + /** + * Change the mode of a file or directory. + * @param uuid the ID of the file or directory + * @param mode the new mode + * @return true if the mode was changed successfully, false otherwise + */ public Boolean chmod(JObjectKey uuid, long mode) { return jObjectTxManager.executeTx(() -> { var dent = curTx.get(JData.class, uuid).orElseThrow(() -> new StatusRuntimeExceptionNoStacktrace(Status.NOT_FOUND)); @@ -243,9 +289,14 @@ public class DhfsFileService { }); } + /** + * Read the contents of a directory. + * @param name the path of the directory + * @return an iterable of the names of the files in the directory + */ public Iterable readDir(String name) { return jObjectTxManager.executeTx(() -> { - var found = getDirEntryW(name); + var found = getDirEntry(name); if (!(found.meta() instanceof JKleppmannTreeNodeMetaDirectory md)) throw new StatusRuntimeException(Status.INVALID_ARGUMENT); @@ -254,6 +305,13 @@ public class DhfsFileService { }); } + /** + * Read the contents of a file. + * @param fileUuid the ID of the file + * @param offset the offset to start reading from + * @param length the number of bytes to read + * @return the contents of the file as a ByteString + */ public ByteString read(JObjectKey fileUuid, long offset, int length) { return jObjectTxManager.executeTx(() -> { if (length < 0) @@ -315,6 +373,11 @@ public class DhfsFileService { }); } + /** + * Get the size of a file. + * @param uuid the ID of the file + * @return the size of the file + */ private ByteString readChunk(JObjectKey uuid) { var chunkRead = remoteTx.getData(ChunkData.class, uuid).orElse(null); @@ -326,6 +389,11 @@ public class DhfsFileService { return chunkRead.data(); } + /** + * Get the size of a chunk. + * @param uuid the ID of the chunk + * @return the size of the chunk + */ private int getChunkSize(JObjectKey uuid) { return readChunk(uuid).size(); } @@ -334,6 +402,13 @@ public class DhfsFileService { return num & -(1L << n); } + /** + * Write data to a file. + * @param fileUuid the ID of the file + * @param offset the offset to write to + * @param data the data to write + * @return the number of bytes written + */ public Long write(JObjectKey fileUuid, long offset, ByteString data) { return jObjectTxManager.executeTx(() -> { if (offset < 0) @@ -436,6 +511,12 @@ public class DhfsFileService { }); } + /** + * Truncate a file to the given length. + * @param fileUuid the ID of the file + * @param length the new length of the file + * @return true if the truncate was successful, false otherwise + */ public Boolean truncate(JObjectKey fileUuid, long length) { return jObjectTxManager.executeTx(() -> { if (length < 0) @@ -525,6 +606,12 @@ public class DhfsFileService { }); } + /** + * Fill the given range with zeroes. + * @param fillStart the start of the range + * @param length the end of the range + * @param newChunks the map to store the new chunks in + */ private void fillZeros(long fillStart, long length, Map newChunks) { long combinedSize = (length - fillStart); @@ -560,12 +647,22 @@ public class DhfsFileService { } } + /** + * Read the contents of a symlink. + * @param uuid the ID of the symlink + * @return the contents of the symlink as a string + */ public String readlink(JObjectKey uuid) { return jObjectTxManager.executeTx(() -> { return readlinkBS(uuid).toStringUtf8(); }); } + /** + * Read the contents of a symlink as a ByteString. + * @param uuid the ID of the symlink + * @return the contents of the symlink as a ByteString + */ public ByteString readlinkBS(JObjectKey uuid) { return jObjectTxManager.executeTx(() -> { var fileOpt = remoteTx.getData(File.class, uuid).orElseThrow(() -> new StatusRuntimeException(Status.NOT_FOUND.withDescription("File not found when trying to readlink: " + uuid))); @@ -573,10 +670,16 @@ public class DhfsFileService { }); } + /** + * Create a symlink. + * @param oldpath the target of the symlink + * @param newpath the path of the symlink + * @return the key of the created symlink + */ public JObjectKey symlink(String oldpath, String newpath) { return jObjectTxManager.executeTx(() -> { Path path = Path.of(newpath); - var parent = getDirEntryW(path.getParent().toString()); + var parent = getDirEntry(path.getParent().toString()); ensureDir(parent); @@ -595,6 +698,13 @@ public class DhfsFileService { }); } + /** + * Set the access and modification times of a file. + * @param fileUuid the ID of the file + * @param atimeMs the access time in milliseconds + * @param mtimeMs the modification time in milliseconds + * @return true if the times were set successfully, false otherwise + */ public Boolean setTimes(JObjectKey fileUuid, long atimeMs, long mtimeMs) { return jObjectTxManager.executeTx(() -> { var dent = curTx.get(JData.class, fileUuid).orElseThrow(() -> new StatusRuntimeExceptionNoStacktrace(Status.NOT_FOUND)); @@ -616,6 +726,11 @@ public class DhfsFileService { }); } + /** + * Get the size of a file. + * @param fileUuid the ID of the file + * @return the size of the file + */ public long size(JObjectKey fileUuid) { return jObjectTxManager.executeTx(() -> { long realSize = 0; @@ -635,6 +750,13 @@ public class DhfsFileService { }); } + /** + * Write data to a file. + * @param fileUuid the ID of the file + * @param offset the offset to write to + * @param data the data to write + * @return the number of bytes written + */ public Long write(JObjectKey fileUuid, long offset, byte[] data) { return write(fileUuid, offset, UnsafeByteOperations.unsafeWrap(data)); } diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DirectoryNotEmptyException.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DirectoryNotEmptyException.java index f0c47a9c..544c7d77 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DirectoryNotEmptyException.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/DirectoryNotEmptyException.java @@ -1,5 +1,10 @@ package com.usatiuk.dhfsfs.service; +/** + * DirectoryNotEmptyException is thrown when a directory is not empty. + * This exception is used to indicate that a directory cannot be deleted + * because it contains files or subdirectories. + */ public class DirectoryNotEmptyException extends RuntimeException { @Override public synchronized Throwable fillInStackTrace() { diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/GetattrRes.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/GetattrRes.java index 11b8e5fa..b97cfc4e 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/GetattrRes.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfsfs/service/GetattrRes.java @@ -1,4 +1,11 @@ package com.usatiuk.dhfsfs.service; -public record GetattrRes(long mtime, long ctime, long mode, GetattrType type) { +/** + * GetattrRes is a record that represents the result of a getattr operation. + * @param mtime File modification time + * @param ctime File creation time + * @param mode File mode + * @param type File type + */ + public record GetattrRes(long mtime, long ctime, long mode, GetattrType type) { } diff --git a/dhfs-parent/pom.xml b/dhfs-parent/pom.xml index 33942f16..95e9faa8 100644 --- a/dhfs-parent/pom.xml +++ b/dhfs-parent/pom.xml @@ -22,7 +22,6 @@ 3.12.1 - 21 21 UTF-8 @@ -87,6 +86,19 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.11.2 + + + --add-exports java.base/sun.nio.ch=ALL-UNNAMED + --add-exports java.base/jdk.internal.access=ALL-UNNAMED + --add-opens=java.base/java.nio=ALL-UNNAMED + --enable-preview + + + ${quarkus.platform.group-id} quarkus-maven-plugin