From ee42588ebefe17996723e185ad55475a86986c5e Mon Sep 17 00:00:00 2001 From: Jake Smith Date: Tue, 10 Dec 2024 14:40:34 +0000 Subject: [PATCH] HPCC-33100 Fix data loss, streaming from dafilesrv and network failure. If there is a broken socket whilst streaming from dafilesrv, the underlying mechanism will dispose of the socket and reconnect and retry the command. If the server side remained running and did not receive notification of the closed socket, the client can reconnect to the same server and the retry will cause the next chunk of data in the stream to be retrieved, thereby losing the earlier one that hit the socket issues. Fix by avoiding the reconnect/retry mechanism at this level, instead, on failure during streaming, establish a new stream at the valid position using the serialized cursor. Signed-off-by: Jake Smith --- fs/dafsclient/rmtfile.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/dafsclient/rmtfile.cpp b/fs/dafsclient/rmtfile.cpp index 7b876e63883..fa8b494e6f7 100644 --- a/fs/dafsclient/rmtfile.cpp +++ b/fs/dafsclient/rmtfile.cpp @@ -2316,9 +2316,19 @@ class CRemoteFilteredFileIOBase : public CRemoteBase, implements IRemoteFileIO mrequest.append((RemoteFileCommandType)RFCStreamRead); VStringBuffer json("{ \"handle\" : %u, \"format\" : \"binary\" }", handle); mrequest.append(json.length(), json.str()); - sendRemoteCommand(mrequest, newReply); - unsigned newHandle; - newReply.read(newHandle); + unsigned newHandle = 0; + try + { + sendRemoteCommand(mrequest, newReply, false); + newReply.read(newHandle); + } + catch (IJSOCK_Exception *e) + { + // will trigger new request with cursor + EXCLOG(e, "CRemoteFilteredFileIOBase:: socket failure whilst streaming, will attempt to reconnect with cursor"); + newHandle = 0; + e->Release(); + } if (newHandle == handle) { reply.swapWith(newReply);