GP-6912 Added task monitor to Block Stream methods

This commit is contained in:
ghidra1
2026-06-02 12:41:55 -04:00
parent e59ffe5e5d
commit cc79293ccc
8 changed files with 74 additions and 40 deletions
@@ -22,6 +22,8 @@ import java.util.zip.Deflater;
import java.util.zip.InflaterInputStream;
import db.buffers.*;
import ghidra.util.MonitoredInputStream;
import ghidra.util.task.TaskMonitor;
/**
* <code>RemoteInputBlockStreamHandle</code> provides a serializable handle to a
@@ -56,11 +58,11 @@ public class RemoteInputBlockStreamHandle extends RemoteBlockStreamHandle<InputB
private class ClientInputBlockStream implements InputBlockStream {
private final Socket socket;
private final InputStream in;
private InputStream in;
private int blocksRemaining = getBlockCount();
ClientInputBlockStream(Socket socket) throws IOException {
ClientInputBlockStream(Socket socket, TaskMonitor monitor) throws IOException {
this.socket = socket;
if (compressed) {
// Uses default Inflater with nowrap=false
@@ -68,6 +70,7 @@ public class RemoteInputBlockStreamHandle extends RemoteBlockStreamHandle<InputB
} else {
in = socket.getInputStream();
}
in = new MonitoredInputStream(in, monitor);
}
@Override
@@ -121,12 +124,12 @@ public class RemoteInputBlockStreamHandle extends RemoteBlockStreamHandle<InputB
}
@Override
public InputBlockStream openBlockStream() throws IOException {
public InputBlockStream openBlockStream(TaskMonitor monitor) throws IOException {
Socket socket = connect();
socket.setReceiveBufferSize(getPreferredBufferSize());
return new ClientInputBlockStream(socket);
return new ClientInputBlockStream(socket, monitor);
}
@Override
@@ -150,6 +153,8 @@ public class RemoteInputBlockStreamHandle extends RemoteBlockStreamHandle<InputB
// Perform final handshake before close (uncompressed)
writeStreamEnd(socket);
// TODO: Investigate use of timeout if both sides are trying to do a read
readStreamEnd(socket, false);
}
catch (SocketException e) {
@@ -21,6 +21,8 @@ import java.net.SocketException;
import java.util.zip.*;
import db.buffers.*;
import ghidra.util.MonitoredOutputStream;
import ghidra.util.task.TaskMonitor;
/**
* <code>RemoteOutputBlockStreamHandle</code> provides a serializable handle to a
@@ -39,7 +41,7 @@ public class RemoteOutputBlockStreamHandle extends RemoteBlockStreamHandle<Outpu
* @param server block stream server instance
* @param blockCount number of blocks to be read by server and written by client
* @param blockSize buffer file block size
* @throws IOException
* @throws IOException if an IO error occurs
*/
public RemoteOutputBlockStreamHandle(BlockStreamServer server, int blockCount, int blockSize)
throws IOException {
@@ -54,16 +56,15 @@ public class RemoteOutputBlockStreamHandle extends RemoteBlockStreamHandle<Outpu
private class ClientOutputBlockStream implements OutputBlockStream {
private final Socket socket;
private final OutputStream out;
private OutputStream out;
private int blocksRemaining = getBlockCount();
ClientOutputBlockStream(Socket socket) throws IOException {
ClientOutputBlockStream(Socket socket, TaskMonitor monitor) throws IOException {
this.socket = socket;
out = new MonitoredOutputStream(socket.getOutputStream(), monitor);
if (compressed) {
out = new RemoteDeflaterOutputStream(socket.getOutputStream(), Deflater.BEST_SPEED);
} else {
out = socket.getOutputStream();
out = new RemoteDeflaterOutputStream(out, Deflater.BEST_SPEED);
}
}
@@ -106,12 +107,12 @@ public class RemoteOutputBlockStreamHandle extends RemoteBlockStreamHandle<Outpu
}
@Override
public OutputBlockStream openBlockStream() throws IOException {
public OutputBlockStream openBlockStream(TaskMonitor monitor) throws IOException {
Socket socket = connect();
socket.setSendBufferSize(getPreferredBufferSize());
return new ClientOutputBlockStream(socket);
return new ClientOutputBlockStream(socket, monitor);
}
@Override
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,14 +17,17 @@ package db.buffers;
import java.io.IOException;
import ghidra.util.task.TaskMonitor;
public interface BlockStreamHandle<T extends BlockStream> {
/**
* Invoked by client to establish the remote connection and return
* the opened block stream.
* @param monitor monitor which will allow cancellation of transfer
* @return connected/open block stream
* @throws IOException
* @throws IOException if an IO error occurs
*/
public T openBlockStream() throws IOException;
public T openBlockStream(TaskMonitor monitor) throws IOException;
}
@@ -20,6 +20,7 @@ import java.rmi.*;
import java.util.NoSuchElementException;
import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;
/**
* <code>BufferFileAdapter</code> provides a BufferFile implementation which
@@ -148,10 +149,11 @@ public class BufferFileAdapter implements BufferFile {
/**
* Obtain a direct stream to read all blocks of this buffer file
* @param monitor task monitor
* @return input block stream
* @throws IOException
* @throws IOException if an IO error occurs
*/
InputBlockStream getInputBlockStream() throws IOException {
InputBlockStream getInputBlockStream(TaskMonitor monitor) throws IOException {
// NOTE: This may need to change in the future if other
// non-RMI implementation require the use of InputBlockStreamHandle
if (isRemote()) {
@@ -159,7 +161,7 @@ public class BufferFileAdapter implements BufferFile {
// obtain InputBlockStream via InputBlockStreamHandle
BlockStreamHandle<InputBlockStream> inputBlockStreamHandle =
bufferFileHandle.getInputBlockStreamHandle();
return inputBlockStreamHandle.openBlockStream();
return inputBlockStreamHandle.openBlockStream(monitor);
}
return bufferFileHandle.getInputBlockStream();
}
@@ -167,10 +169,11 @@ public class BufferFileAdapter implements BufferFile {
/**
* Obtain a direct stream to write blocks to this buffer file
* @param blockCount number of blocks to be written
* @param monitor task monitor
* @return output block stream
* @throws IOException
* @throws IOException if an IO error occurs
*/
OutputBlockStream getOutputBlockStream(int blockCount) throws IOException {
OutputBlockStream getOutputBlockStream(int blockCount, TaskMonitor monitor) throws IOException {
// NOTE: This may need to change in the future if other
// non-RMI implementation require the use of InputBlockStreamHandle
if (isRemote()) {
@@ -178,7 +181,7 @@ public class BufferFileAdapter implements BufferFile {
// obtain OutputBlockStream via OutputBlockStreamHandle
BlockStreamHandle<OutputBlockStream> outputBlockStreamHandle =
bufferFileHandle.getOutputBlockStreamHandle(blockCount);
return outputBlockStreamHandle.openBlockStream();
return outputBlockStreamHandle.openBlockStream(monitor);
}
return bufferFileHandle.getOutputBlockStream(blockCount);
}
@@ -737,7 +737,8 @@ public class BufferMgr {
Msg.trace(BufferMgr.this, "Pre-cache started...");
int cacheCount = 0;
BufferFileAdapter sourceAdapter = (BufferFileAdapter) sourceFile;
try (InputBlockStream inputBlockStream = sourceAdapter.getInputBlockStream()) {
try (InputBlockStream inputBlockStream =
sourceAdapter.getInputBlockStream(TaskMonitor.DUMMY)) {
BufferFileBlock block;
while (!Thread.interrupted() && (block = inputBlockStream.readBlock()) != null) {
DataBuffer buf = LocalBufferFile.getDataBuffer(block);
@@ -2000,7 +2001,8 @@ public class BufferMgr {
monitor.initialize(indexCnt);
// write/update all non-empty buffers
try (OutputBlockStream out = LocalBufferFile.getOutputBlockStream(outFile, bufCount)) {
try (OutputBlockStream out =
LocalBufferFile.getOutputBlockStream(outFile, bufCount, monitor)) {
for (int id = 0; id < indexCnt; id++) {
monitor.checkCancelled();
monitor.setProgress(id);
@@ -939,14 +939,16 @@ public class LocalBufferFile implements BufferFile {
* for the specified read-only bufferFile. Input stream may not supply header block in which case
* free list and file parameters may need to be set separately.
* @param bufferFile buffer file opened read-only
* @param monitor task monitor
* @return input block stream object
* @throws IOException if an I/O error occurs
*/
private static InputBlockStream getInputBlockStream(BufferFile bufferFile) throws IOException {
private static InputBlockStream getInputBlockStream(BufferFile bufferFile, TaskMonitor monitor)
throws IOException {
// This method is used so we can utilize a package method and avoid putting
// it on the BufferFile interface
if (bufferFile instanceof BufferFileAdapter) {
return ((BufferFileAdapter) bufferFile).getInputBlockStream();
return ((BufferFileAdapter) bufferFile).getInputBlockStream(monitor);
}
if (bufferFile instanceof LocalBufferFile) {
return ((LocalBufferFile) bufferFile).getInputBlockStream();
@@ -961,18 +963,21 @@ public class LocalBufferFile implements BufferFile {
* to select which buffer should be transferred. Input stream may not supply header block
* in which case free list and file parameters may need to be set separately.
* @param bufferFile buffer file opened read-only
* @param monitor task monitor
* @return input block stream object
* @throws IOException if an I/O error occurs
*/
private static InputBlockStream getInputBlockStream(BufferFile bufferFile, ChangeMap changeMap)
private static InputBlockStream getInputBlockStream(BufferFile bufferFile, ChangeMap changeMap,
TaskMonitor monitor)
throws IOException {
if (changeMap == null) {
return getInputBlockStream(bufferFile);
return getInputBlockStream(bufferFile, monitor);
}
// This method is used so we can utilize a package method and avoid putting
// it on the BufferFile interface
if (bufferFile instanceof ManagedBufferFileAdapter) {
return ((ManagedBufferFileAdapter) bufferFile).getInputBlockStream(changeMap.getData());
return ((ManagedBufferFileAdapter) bufferFile).getInputBlockStream(changeMap.getData(),
monitor);
}
if (bufferFile instanceof LocalManagedBufferFile) {
return ((LocalManagedBufferFile) bufferFile).getInputBlockStream(changeMap.getData());
@@ -987,15 +992,17 @@ public class LocalBufferFile implements BufferFile {
* @param bufferFile write-able buffer file
* @param blockCount number of blocks to be written. This should be available from
* the corresponding {@link InputBlockStream}.
* @param monitor task monitor
* @return output block stream object
* @throws IOException if an I/O error occurs
*/
static OutputBlockStream getOutputBlockStream(BufferFile bufferFile, int blockCount)
static OutputBlockStream getOutputBlockStream(BufferFile bufferFile, int blockCount,
TaskMonitor monitor)
throws IOException {
// This method is used so we can utilize a package method and avoid putting
// it on the BufferFile interface
if (bufferFile instanceof BufferFileAdapter) {
return ((BufferFileAdapter) bufferFile).getOutputBlockStream(blockCount);
return ((BufferFileAdapter) bufferFile).getOutputBlockStream(blockCount, monitor);
}
if (bufferFile instanceof LocalBufferFile) {
return ((LocalBufferFile) bufferFile).getOutputBlockStream(blockCount);
@@ -1030,11 +1037,12 @@ public class LocalBufferFile implements BufferFile {
int srcBlockCnt;
boolean headerTransferRequired;
try (InputBlockStream in = getInputBlockStream(srcFile, changeMap)) {
try (InputBlockStream in = getInputBlockStream(srcFile, changeMap, monitor)) {
headerTransferRequired = !in.includesHeaderBlock();
srcBlockCnt = in.getBlockCount();
monitor.initialize(srcBlockCnt + 2);
try (OutputBlockStream out = getOutputBlockStream(destFile, in.getBlockCount())) {
try (OutputBlockStream out =
getOutputBlockStream(destFile, in.getBlockCount(), monitor)) {
completeBlockStreamTransfer(in, out, monitor);
}
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,6 +18,8 @@ package db.buffers;
import java.io.IOException;
import java.rmi.Remote;
import ghidra.util.task.TaskMonitor;
/**
* <code>ManagedBufferFileAdapter</code> provides a ManagedBufferFile implementation which
* wraps a ManagedBufferFileHandle.
@@ -86,7 +88,8 @@ public class ManagedBufferFileAdapter extends BufferFileAdapter implements Manag
* @return input block stream
* @throws IOException
*/
InputBlockStream getInputBlockStream(byte[] changeMapData) throws IOException {
InputBlockStream getInputBlockStream(byte[] changeMapData, TaskMonitor monitor)
throws IOException {
// NOTE: This may need to change in the future if other
// non-RMI implementation require the use of InputBlockStreamHandle
if (managedBufferFileHandle instanceof Remote) {
@@ -94,7 +97,7 @@ public class ManagedBufferFileAdapter extends BufferFileAdapter implements Manag
// obtain InputBlockStream via InputBlockStreamHandle
BlockStreamHandle<InputBlockStream> inputBlockStreamHandle =
managedBufferFileHandle.getInputBlockStreamHandle(changeMapData);
return inputBlockStreamHandle.openBlockStream();
return inputBlockStreamHandle.openBlockStream(monitor);
}
return managedBufferFileHandle.getInputBlockStream(changeMapData);
}
@@ -385,12 +385,21 @@ public abstract class LocalFileSystem implements FileSystem {
}
ItemPropertyFile propertyFile = itemStorage.getPropertyFile();
if (propertyFile.exists()) {
return LocalFolderItem.getFolderItem(this, propertyFile);
LocalFolderItem item = LocalFolderItem.getFolderItem(this, propertyFile);
if (item != null) {
return item;
}
Msg.warn(this, "Attempting item cleanup due to invalid state: " +
new File(propertyFile.getParentStorageDirectory(),
propertyFile.getStorageName()));
}
else {
Msg.warn(this, "Attempting item cleanup due to missing property file: " +
new File(propertyFile.getParentStorageDirectory(),
propertyFile.getStorageName()));
}
// force cleanup of bad storage allocation
Msg.warn(this, "Attempting item cleanup due to missing property file: " +
new File(propertyFile.getParentStorageDirectory(), propertyFile.getStorageName()));
itemDeleted(folderPath, name);
}
catch (InvalidObjectException e) {