diff src/main/java/org/monetdb/mcl/net/MapiSocket.java @ 533:b75464874130 onclient

Keep better track of whether the server has cancelled the upload IOExceptions are suppressed by PrintStreams print/println methods. This means the client may not realize the server cancelled and we must suppress all further attempts to write. Also, the end of upload handshake is different if a cancellation occurred.
author Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com>
date Fri, 27 Aug 2021 13:45:38 +0200 (2021-08-27)
parents 72007c4f8f8a
children c9d88af06d35
line wrap: on
line diff
--- a/src/main/java/org/monetdb/mcl/net/MapiSocket.java
+++ b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
@@ -1194,6 +1194,7 @@ public class MapiSocket {	/* cannot (yet
 		public final static int DEFAULT_CHUNK_SIZE = 1024 * 1024;
 		private final int chunkSize;
 		private boolean closed = false;
+		private boolean serverCancelled = false;
 		private int chunkLeft;
 		private byte[] promptBuffer;
 
@@ -1215,6 +1216,12 @@ public class MapiSocket {	/* cannot (yet
 
 		@Override
 		public void write(int b) throws IOException {
+			if (serverCancelled) {
+				// We have already thrown an exception and apparently that has been ignored.
+				// Probably because they're calling print methods instead of write.
+				// Throw another one, maybe they'll catch this one.
+				throw new IOException("Server aborted the upload");
+			}
 			handleChunking();
 			super.write(b);
 			wrote(1);
@@ -1227,6 +1234,12 @@ public class MapiSocket {	/* cannot (yet
 
 		@Override
 		public void write(byte[] b, int off, int len) throws IOException {
+			if (serverCancelled) {
+				// We have already thrown an exception and apparently that has been ignored.
+				// Probably because they're calling print methods instead of write.
+				// Throw another one, maybe they'll catch this one.
+				throw new IOException("Server aborted the upload");
+			}
 			while (len > 0) {
 				handleChunking();
 				int toWrite = Integer.min(len, chunkLeft);
@@ -1247,6 +1260,15 @@ public class MapiSocket {	/* cannot (yet
 			if (closed) {
 				return;
 			}
+			closed = true;
+
+			if (serverCancelled)
+				closeAfterServerCancelled();
+			else
+				closeAfterSuccesfulUpload();
+		}
+
+		private void closeAfterSuccesfulUpload() throws IOException {
 			if (chunkLeft != chunkSize) {
 				// flush pending data
 				flushAndReadPrompt();
@@ -1259,6 +1281,10 @@ public class MapiSocket {	/* cannot (yet
 			}
 		}
 
+		private void closeAfterServerCancelled() throws IOException {
+			// nothing to do here, we have already read the error prompt.
+		}
+
 		private void wrote(int i) {
 			chunkLeft -= i;
 		}
@@ -1278,6 +1304,9 @@ public class MapiSocket {	/* cannot (yet
 				case MORE:
 					return;
 				case FILETRANSFER:
+					// Note, if the caller is calling print methods instead of write, the IO exception gets hidden.
+					// This is unfortunate but there's nothing we can do about it.
+					serverCancelled = true;
 					throw new IOException("Server aborted the upload");
 				default:
 					throw new IOException("Expected MORE/DONE from server, got " + lineType);