testdiskdrive now uses input stream which enables I/O on files larger than 2GB

This commit is contained in:
minjaesong
2025-10-07 19:54:43 +09:00
parent e36d4041ce
commit abce002cdd

View File

@@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.IOException import java.io.IOException
import java.io.InputStream
import java.util.* import java.util.*
/** /**
@@ -88,6 +89,11 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
field = value field = value
}*/ }*/
// Streaming read mode fields
private var readInputStream: InputStream? = null
private var readStreamActive = false
private var readFileSize = -1L
init { init {
statusCode.set(STATE_CODE_STANDBY) statusCode.set(STATE_CODE_STANDBY)
@@ -101,12 +107,24 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
private fun resetBuf() { private fun resetBuf() {
blockSendCount = 0 blockSendCount = 0
messageComposeBuffer.reset() messageComposeBuffer.reset()
closeReadStream()
}
private fun closeReadStream() {
readInputStream?.close()
readInputStream = null
readStreamActive = false
readFileSize = -1L
} }
override fun hasNext(): Boolean { override fun hasNext(): Boolean {
// For streaming read mode, check if stream has more data
if (readStreamActive) {
return readInputStream?.available() ?: 0 > 0
}
// For buffered messages, check buffer position
return (blockSendCount * BLOCK_SIZE < blockSendBuffer.size) return (blockSendCount * BLOCK_SIZE < blockSendBuffer.size)
} }
@@ -115,6 +133,40 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
* Disk drive must send prepared message (or file transfer packet) to the computer. * Disk drive must send prepared message (or file transfer packet) to the computer.
*/ */
override fun startSendImpl(recipient: BlockTransferInterface): Int { override fun startSendImpl(recipient: BlockTransferInterface): Int {
// Handle streaming read mode
if (readStreamActive) {
val stream = readInputStream ?: return 0
try {
val buffer = ByteArray(BLOCK_SIZE)
val bytesRead = stream.read(buffer)
if (bytesRead <= 0) {
// End of file
closeReadStream()
return 0
}
// Send only the bytes that were actually read
val sendBuffer = if (bytesRead < BLOCK_SIZE) {
buffer.copyOf(bytesRead)
} else {
buffer
}
recipient.writeout(sendBuffer)
blockSendCount += 1
return bytesRead
}
catch (e: IOException) {
closeReadStream()
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
return 0
}
}
// Handle buffered message mode (for LIST, GETLEN, etc.)
if (blockSendCount == 0) { if (blockSendCount == 0) {
blockSendBuffer = messageComposeBuffer.toByteArray() blockSendBuffer = messageComposeBuffer.toByteArray()
} }
@@ -203,6 +255,7 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
if (inputString.startsWith("DEVRST\u0017")) { if (inputString.startsWith("DEVRST\u0017")) {
printdbg("Device Reset") printdbg("Device Reset")
//readModeLength = -1 //readModeLength = -1
closeReadStream()
fileOpen = false fileOpen = false
fileOpenMode = -1 fileOpenMode = -1
file = File(rootPath.toURI()) file = File(rootPath.toURI())
@@ -337,6 +390,7 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
statusCode.set(STATE_CODE_STANDBY) statusCode.set(STATE_CODE_STANDBY)
} }
else if (inputString.startsWith("CLOSE")) { else if (inputString.startsWith("CLOSE")) {
closeReadStream()
fileOpen = false fileOpen = false
fileOpenMode = -1 fileOpenMode = -1
statusCode.set(STATE_CODE_STANDBY) statusCode.set(STATE_CODE_STANDBY)
@@ -347,10 +401,15 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
resetBuf() resetBuf()
if (file.isFile) { if (file.isFile) {
try { try {
messageComposeBuffer.write(file.readBytes()) // Open file for streaming reads instead of loading entire file
readInputStream = FileInputStream(file)
readStreamActive = true
readFileSize = file.length()
blockSendCount = 0
statusCode.set(STATE_CODE_STANDBY) statusCode.set(STATE_CODE_STANDBY)
} }
catch (e: IOException) { catch (e: IOException) {
closeReadStream()
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR) statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
} }
} }