diff --git a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfs/files/service/DhfsFileServiceImpl.java b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfs/files/service/DhfsFileServiceImpl.java index 96125217..48030b99 100644 --- a/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfs/files/service/DhfsFileServiceImpl.java +++ b/dhfs-parent/dhfs-fs/src/main/java/com/usatiuk/dhfs/files/service/DhfsFileServiceImpl.java @@ -367,16 +367,12 @@ public class DhfsFileServiceImpl implements DhfsFileService { + offset + " " + data.size()); } - if (size(fileUuid) < offset) { - truncate(fileUuid, offset); - file = remoteTx.getData(File.class, fileUuid).orElse(null); - } - NavigableMap removedChunks = new TreeMap<>(); long realOffset = targetChunkAlignment >= 0 ? alignDown(offset, targetChunkAlignment) : offset; long writeEnd = offset + data.size(); long start = realOffset; + long existingEnd = 0; ByteString pendingPrefix = ByteString.empty(); ByteString pendingSuffix = ByteString.empty(); @@ -385,8 +381,8 @@ public class DhfsFileServiceImpl implements DhfsFileService { var curEntry = it.next(); long curChunkStart = curEntry.getKey().key(); var curChunkId = curEntry.getValue().ref(); - long curChunkEnd = curChunkStart + getChunkSize(curChunkId); - + long curChunkEnd = it.hasNext() ? it.peekNextKey().key() : curChunkStart + getChunkSize(curChunkId); + existingEnd = curChunkEnd; if (curChunkEnd <= realOffset) break; removedChunks.put(curEntry.getKey().key(), curChunkId); @@ -408,12 +404,23 @@ public class DhfsFileServiceImpl implements DhfsFileService { } } + + NavigableMap newChunks = new TreeMap<>(); + + if (existingEnd < offset) { + if (!pendingPrefix.isEmpty()) { + int diff = Math.toIntExact(offset - existingEnd); + pendingPrefix = pendingPrefix.concat(ByteString.copyFrom(new byte[diff])); + } else { + fillZeros(existingEnd, offset, newChunks); + start = offset; + } + } + ByteString pendingWrites = pendingPrefix.concat(data).concat(pendingSuffix); int combinedSize = pendingWrites.size(); - NavigableMap newChunks = new TreeMap<>(); - { int targetChunkSize = 1 << targetChunkAlignment; int cur = 0; @@ -476,38 +483,7 @@ public class DhfsFileServiceImpl implements DhfsFileService { NavigableMap newChunks = new TreeMap<>(); if (curSize < length) { - long combinedSize = (length - curSize); - - long start = curSize; - - // Hack - HashMap zeroCache = new HashMap<>(); - - { - long cur = 0; - while (cur < combinedSize) { - long end; - - if (targetChunkSize <= 0) - end = combinedSize; - else { - if ((combinedSize - cur) > (targetChunkSize * 1.5)) { - end = cur + targetChunkSize; - } else { - end = combinedSize; - } - } - - if (!zeroCache.containsKey(end - cur)) - zeroCache.put(end - cur, createChunk(UnsafeByteOperations.unsafeWrap(new byte[Math.toIntExact(end - cur)]))); - - ChunkData newChunkData = zeroCache.get(end - cur); - newChunks.put(start, newChunkData.key()); - - start += newChunkData.data().size(); - cur = end; - } - } + fillZeros(curSize, length, newChunks); } else { // Pair> first; Pair> last; @@ -572,6 +548,41 @@ public class DhfsFileServiceImpl implements DhfsFileService { }); } + private void fillZeros(long fillStart, long length, NavigableMap newChunks) { + long combinedSize = (length - fillStart); + + long start = fillStart; + + // Hack + HashMap zeroCache = new HashMap<>(); + + { + long cur = 0; + while (cur < combinedSize) { + long end; + + if (targetChunkSize <= 0) + end = combinedSize; + else { + if ((combinedSize - cur) > (targetChunkSize * 1.5)) { + end = cur + targetChunkSize; + } else { + end = combinedSize; + } + } + + if (!zeroCache.containsKey(end - cur)) + zeroCache.put(end - cur, createChunk(UnsafeByteOperations.unsafeWrap(new byte[Math.toIntExact(end - cur)]))); + + ChunkData newChunkData = zeroCache.get(end - cur); + newChunks.put(start, newChunkData.key()); + + start += newChunkData.data().size(); + cur = end; + } + } + } + @Override public String readlink(JObjectKey uuid) { return jObjectTxManager.executeTx(() -> { diff --git a/dhfs-parent/dhfs-fs/src/test/java/com/usatiuk/dhfs/files/DhfsFileServiceSimpleTestImpl.java b/dhfs-parent/dhfs-fs/src/test/java/com/usatiuk/dhfs/files/DhfsFileServiceSimpleTestImpl.java index 7b6af361..db9668c2 100644 --- a/dhfs-parent/dhfs-fs/src/test/java/com/usatiuk/dhfs/files/DhfsFileServiceSimpleTestImpl.java +++ b/dhfs-parent/dhfs-fs/src/test/java/com/usatiuk/dhfs/files/DhfsFileServiceSimpleTestImpl.java @@ -169,6 +169,7 @@ public abstract class DhfsFileServiceSimpleTestImpl { Assertions.assertArrayEquals(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, fileService.read(uuid, 0, 10).get().toByteArray()); fileService.truncate(uuid, 20); + Assertions.assertArrayEquals(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fileService.read(uuid, 0, 20).get().toByteArray()); fileService.write(uuid, 10, new byte[]{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}); Assertions.assertArrayEquals(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, fileService.read(uuid, 0, 20).get().toByteArray()); } finally {