Source:
<code>private void sendLargeFile(AbstractJournalStorageManager.JournalContent content, SimpleString pageStore, final long id, SequentialFile file, long maxBytesToSend) throws Exception { if (!enabled) return; if (!file.isOpen()) { file.open(); } final int size = 1024 * 1024; long fileSize = file.size(); int flowControlSize = 10; int packetsSent = 0; FlushAction action = new FlushAction(); long offset = 0; RandomAccessFile raf = null; FileChannel fileChannel = null; try { <START> raf = new RandomAccessFile(file.getJavaFile(), "r"); <END> fileChannel = raf.getChannel(); while (true) { long chunkSize = Math.min(size, fileSize - offset); int toSend = (int) chunkSize; if (chunkSize > 0) { if (chunkSize >= maxBytesToSend) { toSend = (int) maxBytesToSend; maxBytesToSend = 0; } else { maxBytesToSend = maxBytesToSend - chunkSize; } } logger.debug("sending " + toSend + " bytes on file " + file.getFileName()); sendSyncFileMessage(new ReplicationSyncFileMessage(content, pageStore, id, raf, fileChannel, offset, toSend), offset + toSend == fileSize); packetsSent++; offset += toSend; if (packetsSent % flowControlSize == 0) { flushReplicationStream(action); } if (toSend == 0 || maxBytesToSend == 0) break; } flushReplicationStream(action); } catch (Exception e) { if (raf != null) raf.close(); throw e; } finally { if (file.isOpen()) file.close(); } }</code><technical_language>If send a 0 size file, need close raf ReplicationSyncFileMessage::release called, correct</technical_language>

Target:
private CompletableFuture<?> sendLargeFile(AbstractJournalStorageManager.JournalContent content, SimpleString pageStore, final long id, SequentialFile file, long maxBytesToSend) throws Exception { if (!enabled) return CompletableFuture.completedFuture(null); if (!file.isOpen()) { file.open(); } final int size = 1024 * 1024; final long fileSize = file.size(); final File javaFile = file.getJavaFile(); if (fileSize == 0) { final String fileName = file.getFileName(); file.close(); final CompletableFuture<?> onFlushed = new CompletableFuture<>(); sendEmptyFile(content, pageStore, id, fileName, onFlushed); return onFlushed; } int flowControlSize = 10; int packetsSent = 0; FlushAction action = new FlushAction(); long offset = 0; RandomAccessFile raf = null; FileChannel fileChannel = null; CompletableFuture<?> onFlushed = null; try { raf = new RandomAccessFile(javaFile, "r"); fileChannel = raf.getChannel(); while (true) { long chunkSize = Math.min(size, fileSize - offset); int toSend = (int) chunkSize; if (chunkSize > 0) { if (chunkSize >= maxBytesToSend) { toSend = (int) maxBytesToSend; maxBytesToSend = 0; } else { maxBytesToSend = maxBytesToSend - chunkSize; } } logger.debugf("sending %d bytes on file %s", toSend, file.getFileName()); final boolean lastChunk = offset + toSend == fileSize; if (lastChunk && (toSend == 0 || maxBytesToSend == 0)) { onFlushed = new CompletableFuture<>(); } else { onFlushed = null; } sendSyncFileMessage(new ReplicationSyncFileMessage(content, pageStore, id, raf, fileChannel, offset, toSend), lastChunk, onFlushed); packetsSent++; offset += toSend; if (packetsSent % flowControlSize == 0) { flushReplicationStream(action); } if (toSend == 0 || maxBytesToSend == 0) break; } flushReplicationStream(action); assert onFlushed != null; return onFlushed; } catch (Exception e) { if (raf != null) raf.close(); onFlushed.completeExceptionally(e); throw e; } finally { if (file.isOpen()) file.close(); } }