[prev in list] [next in list] [prev in thread] [next in thread] 

List:       monetdb-checkins
Subject:    monetdb-java: default - Refactor Handshake options
From:       Joeri_van_Ruth <commits+joeri.van.ruth=monetdbsolutions.com () mon
Date:       2022-10-28 14:31:32
Message-ID: hg.fade6c6960cc.1666967492.-1478053844545772160 () dev ! monetdb ! org
[Download RAW message or body]

Changeset: fade6c6960cc for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/fade6c6960cc
Added Files:
	src/main/java/org/monetdb/mcl/net/HandshakeOption.java
Removed Files:
	src/main/java/org/monetdb/mcl/net/HandshakeOptions.java
Modified Files:
	src/main/java/org/monetdb/jdbc/MonetConnection.java
	src/main/java/org/monetdb/mcl/net/MapiSocket.java
Branch: default
Log Message:

Refactor Handshake options

It was not clear and there were obscure bugs.


diffs (truncated from 430 to 300 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetConnection.java \
                b/src/main/java/org/monetdb/jdbc/MonetConnection.java
--- a/src/main/java/org/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/org/monetdb/jdbc/MonetConnection.java
@@ -36,8 +36,7 @@ import java.util.concurrent.Executor;
 import org.monetdb.mcl.io.BufferedMCLReader;
 import org.monetdb.mcl.io.BufferedMCLWriter;
 import org.monetdb.mcl.io.LineType;
-import org.monetdb.mcl.net.HandshakeOptions;
-import org.monetdb.mcl.net.HandshakeOptions.Setting;
+import org.monetdb.mcl.net.HandshakeOption;
 import org.monetdb.mcl.net.MapiSocket;
 import org.monetdb.mcl.parser.HeaderLineParser;
 import org.monetdb.mcl.parser.MCLParseException;
@@ -166,7 +165,12 @@ public class MonetConnection
 	MonetConnection(final Properties props)
 		throws SQLException, IllegalArgumentException
 	{
-	// for debug: System.out.println("New connection object. Received properties are: " \
+ props.toString()); +		HandshakeOption.AutoCommit autoCommitSetting = new \
HandshakeOption.AutoCommit(true); +		HandshakeOption.ReplySize replySizeSetting = new \
HandshakeOption.ReplySize(DEF_FETCHSIZE); +		HandshakeOption.SizeHeader \
sizeHeaderSetting = new HandshakeOption.SizeHeader(true); +		HandshakeOption.TimeZone \
timeZoneSetting = new HandshakeOption.TimeZone(0); +
+		// for debug: System.out.println("New connection object. Received properties are: \
" + props.toString());  // get supported property values from the props argument.
 		// When a value is found add it to the internal conn_props list for use by \
getClientInfo().  this.hostname = props.getProperty("host");
@@ -211,10 +215,10 @@ public class MonetConnection
 			conn_props.setProperty("hash", hash);
 
 		String autocommit_prop = props.getProperty("autocommit");
-		boolean initial_autocommit = true;
 		if (autocommit_prop != null) {
-			initial_autocommit = Boolean.parseBoolean(autocommit_prop);
-			conn_props.setProperty("autocommit", Boolean.toString(initial_autocommit));
+			boolean ac = Boolean.parseBoolean(autocommit_prop);
+			autoCommitSetting.set(ac);
+			conn_props.setProperty("autocommit", Boolean.toString(ac));
 		}
 
 		final String fetchsize_prop = props.getProperty("fetchsize");
@@ -222,7 +226,7 @@ public class MonetConnection
 			try {
 				int fetchsize = Integer.parseInt(fetchsize_prop);
 				if (fetchsize > 0 || fetchsize == -1) {
-					this.defaultFetchSize = fetchsize;
+					replySizeSetting.set(fetchsize);
 					conn_props.setProperty("fetchsize", fetchsize_prop);
 				} else {
 					addWarning("Fetch size must either be positive or -1. Value " + fetchsize + " \
ignored", "M1M05"); @@ -291,16 +295,18 @@ public class MonetConnection
 			server.setDatabase(database);
 		server.setLanguage(language);
 
+		// calculate our time zone offset
 		final Calendar cal = Calendar.getInstance();
 		int offsetMillis = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
 		int offsetSeconds = offsetMillis / 1000;
-		final HandshakeOptions handshakeOptions = new HandshakeOptions();
-		handshakeOptions.set(Setting.AutoCommit, initial_autocommit ? 1 : 0);
-		handshakeOptions.set(Setting.TimeZone, offsetSeconds);
-		handshakeOptions.set(Setting.ReplySize, defaultFetchSize);
-//		handshakeOptions.set(Setting.SizeHeader, 1);
-		server.setHandshakeOptions(handshakeOptions);
-		autoCommit = initial_autocommit;
+		timeZoneSetting.set(offsetSeconds);
+
+		server.setHandshakeOptions(new HandshakeOption[] {
+				autoCommitSetting,
+				replySizeSetting,
+				sizeHeaderSetting,
+				timeZoneSetting,
+		});
 
 		// we're debugging here... uhm, should be off in real life
 		if (debug) {
@@ -381,50 +387,21 @@ public class MonetConnection
 			lang = LANG_UNKNOWN;
 		}
 
-		// The reply size is checked before every query and adjusted if
-		// necessary. Update our current belief of what the server is set to.
-		if (handshakeOptions.wasSentInHandshake(HandshakeOptions.Setting.ReplySize)) {
-			this.curReplySize = handshakeOptions.get(HandshakeOptions.Setting.ReplySize);
+		// Now take care of any handshake options not handled during the handshake
+		if (replySizeSetting.isSent()) {
+			this.curReplySize = replySizeSetting.get();
 		}
-
-		for (Setting setting : new Setting[] { Setting.SizeHeader }) {
-			if (handshakeOptions.mustSend(setting)) {
-				Integer value = handshakeOptions.get(setting); // guaranteed by mustSend to be \
                non-null
-				String command = String.format("%s %d", setting.getXCommand(), value);
-				sendControlCommand(command);
-			}
-		}
-
-		// the following initialisers are only valid when the language is SQL...
+		this.defaultFetchSize = replySizeSetting.get();
 		if (lang == LANG_SQL) {
-			if (handshakeOptions.mustSend(Setting.AutoCommit)) {
-				setAutoCommit(handshakeOptions.get(Setting.AutoCommit) != 0);
+			if (autoCommitSetting.mustSend(autoCommit)) {
+				setAutoCommit(autoCommitSetting.get());
 			}
-
-			// set our time zone on the server, if we haven't already
-			if (handshakeOptions.mustSend(Setting.TimeZone)) {
-				final StringBuilder tz = new StringBuilder(64);
-				tz.append("SET TIME ZONE INTERVAL '");
-				int offsetMinutes = handshakeOptions.get(Setting.TimeZone) / 60;
-				if (offsetMinutes < 0) {
-					tz.append('-');
-					offsetMinutes = -offsetMinutes; // make it positive
-				} else {
-					tz.append('+');
-				}
-				int offsetHours = offsetMinutes / 60;
-				if (offsetHours < 10)
-					tz.append('0');
-				tz.append(offsetHours).append(':');
-				offsetMinutes -= offsetHours * 60;
-				if (offsetMinutes < 10)
-					tz.append('0');
-				tz.append(offsetMinutes).append("' HOUR TO MINUTE");
-				sendIndependentCommand(tz.toString());
+			if (sizeHeaderSetting.mustSend(false)) {
+				sendControlCommand("sizeheader 1");
 			}
-
-			// set sizeheader to 1 to enable sending "typesizes" info by the server (see \
                mapi_set_size_header() in mapi.c)
-			sendControlCommand("sizeheader 1");
+			if (timeZoneSetting.mustSend(0)) {
+				setTimezone(timeZoneSetting.get());
+			}
 		}
 
 		// we're absolutely not closed, since we're brand new
@@ -1739,6 +1716,27 @@ public class MonetConnection
 		return downloadHandler;
 	}
 
+	public void setTimezone(int offsetSeconds) throws SQLException {
+		final StringBuilder tz = new StringBuilder(64);
+		tz.append("SET TIME ZONE INTERVAL '");
+		int offsetMinutes = offsetSeconds / 60;
+		if (offsetMinutes < 0) {
+			tz.append('-');
+			offsetMinutes = -offsetMinutes; // make it positive
+		} else {
+			tz.append('+');
+		}
+		int offsetHours = offsetMinutes / 60;
+		if (offsetHours < 10)
+			tz.append('0');
+		tz.append(offsetHours).append(':');
+		offsetMinutes -= offsetHours * 60;
+		if (offsetMinutes < 10)
+			tz.append('0');
+		tz.append(offsetMinutes).append("' HOUR TO MINUTE");
+		sendIndependentCommand(tz.toString());
+	}
+
 	/**
 	 * Local helper method to test whether the Connection object is closed
 	 * When closed it throws an SQLException
diff --git a/src/main/java/org/monetdb/mcl/net/HandshakeOption.java \
b/src/main/java/org/monetdb/mcl/net/HandshakeOption.java new file mode 100644
--- /dev/null
+++ b/src/main/java/org/monetdb/mcl/net/HandshakeOption.java
@@ -0,0 +1,100 @@
+package org.monetdb.mcl.net;
+
+public abstract class HandshakeOption<T> {
+	protected final int level;
+	protected final String handshakeField;
+	boolean sent = false;
+	T desiredValue;
+
+	protected HandshakeOption(int level, String handshakeField, T desiredValue) {
+		if (desiredValue == null) {
+			throw new IllegalArgumentException("initial value must not be null");
+		}
+		this.level = level;
+		this.handshakeField = handshakeField;
+		this.desiredValue = desiredValue;
+	}
+
+	public void set(T newValue) {
+		if (newValue == null) {
+			throw new IllegalArgumentException("new value must not be null");
+		}
+		desiredValue = newValue;
+	}
+
+	public T get() {
+		return desiredValue;
+	}
+
+	public int getLevel() {
+		return level;
+	}
+
+	public String getFieldName() {
+		return handshakeField;
+	}
+
+	public boolean isSent() {
+		return sent;
+	}
+
+	public void setSent(boolean b) {
+		sent = b;
+	}
+
+	public boolean mustSend(T currentValue) {
+		if (sent)
+			return false;
+		if (currentValue.equals(desiredValue))
+			return false;
+		return true;
+	}
+
+	abstract long numericValue();
+
+	protected static class BooleanOption extends HandshakeOption<Boolean> {
+		protected BooleanOption(int level, String name, Boolean initialValue) {
+			super(level, name, initialValue);
+		}
+
+		@Override
+		long numericValue() {
+			return desiredValue ? 1 : 0;
+		}
+	}
+
+	public static class AutoCommit extends BooleanOption {
+		public AutoCommit(boolean autoCommit) {
+			super(1, "auto_commit",  autoCommit);
+		}
+	}
+
+	public static class ReplySize extends HandshakeOption<Integer> {
+		public ReplySize(int size) {
+			super(2, "reply_size", size);
+		}
+
+		@Override
+		long numericValue() {
+			return desiredValue;
+		}
+	}
+
+	public static class SizeHeader extends BooleanOption {
+		public SizeHeader(boolean sendHeader) {
+			super(3, "size_header", sendHeader);
+			set(sendHeader);
+		}
+	}
+
+	public static class TimeZone extends HandshakeOption<Integer> {
+		public TimeZone(int offset) {
+			super(5, "time_zone", offset);
+		}
+
+		@Override
+		long numericValue() {
+			return desiredValue;
+		}
+	}
+}
diff --git a/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java \
b/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java deleted file mode 100644
--- a/src/main/java/org/monetdb/mcl/net/HandshakeOptions.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0.  If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
- */
-
-package org.monetdb.mcl.net;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/** Keep track of MAPI handshake options.
- *
- * Recent server versions (from 2021) allow you to send configuration information \
                during
- * the authentication handshake so no additional round trips are necessary
- * when that has completed.
- *
- * This class keeps track of the values themselves, and also of whether or not they \
                should still be sent.
- */
-final public class HandshakeOptions {
-	HashMap<Setting,Integer> options = new HashMap<>();
-	int handshakeLevel = 0;
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-leave@monetdb.org


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic