Skip to content

Commit

Permalink
mysql: AFUNIXDatabaseSocketFactoryCJ: Respect timeouts
Browse files Browse the repository at this point in the history
AFUNIXDatabaseSocketFactoryCJ.connect takes a "loginTimeout" parameter,
and the system properties may specify a "connectTimeout".

While connecting to AF_UNIX sockets appears to not block in the regular
case, let's assume there's a corner case where respecting these values
makes sense.

Follow standard Mysql connector behavior and use these two timeouts to
determine the connect timeout for our unix domain sockets.

#154
  • Loading branch information
kohlschuetter committed Mar 7, 2024
1 parent 535b73a commit 9524e32
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.newsclub.net.unix.AFUNIXSocketAddress;

import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
import com.mysql.cj.conf.PropertyKey;
import com.mysql.cj.conf.PropertySet;
import com.mysql.cj.conf.RuntimeProperty;
import com.mysql.cj.protocol.ExportControlled;
Expand Down Expand Up @@ -61,8 +62,14 @@ public Socket connect(String hostname, int portNumber,
}
final File socketFile = new File(sock);

this.rawSocket = AFUNIXSocket.connectTo(AFUNIXSocketAddress.of(socketFile));
return rawSocket;
AFUNIXSocket socket = AFUNIXSocket.newInstance();

int connectTimeout = props.getIntegerProperty(PropertyKey.connectTimeout).getValue();
int timeout = MysqlHelper.shorterTimeout(connectTimeout, loginTimeout);

socket.connect(AFUNIXSocketAddress.of(socketFile), timeout);

return (this.rawSocket = socket);
}

@SuppressWarnings({"unchecked"})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* junixsocket
*
* Copyright 2009-2023 Christian Kohlschütter
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.newsclub.net.mysql;

/**
* Code sharable between code in junixsocket-mysql.
*
* @author Christian Kohlschütter
*/
final class MysqlHelper {
private MysqlHelper() {
}

/**
* Returns the shorter timeout of two given timeouts (assuming 0 means "unlimited").
*
* @param a The first timeout.
* @param b The second timeout.
* @return The shorter timeout.
*/
static int shorterTimeout(int a, int b) {
if (a == 0 || (b != 0 && b < a)) {
return b;
} else {
return a;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* junixsocket
*
* Copyright 2009-2023 Christian Kohlschütter
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.newsclub.net.mysql;

import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;

import java.time.Duration;

import org.junit.jupiter.api.Test;
import org.newsclub.net.unix.AFUNIXServerSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;

import com.mysql.cj.conf.DefaultPropertySet;
import com.mysql.cj.conf.StringPropertyDefinition;

public class AFUNIXDatabaseSocketFactoryCJTest {

@Test
public void testConnectTimeout() throws Exception {
AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile();
try (AFUNIXServerSocket serverSocket = AFUNIXServerSocket.newInstance()) {
serverSocket.bind(addr, 1);

AFUNIXDatabaseSocketFactoryCJ sf = new AFUNIXDatabaseSocketFactoryCJ();

DefaultPropertySet props = new DefaultPropertySet();
props.addProperty(new StringPropertyDefinition("junixsocket.file", "junixsocket.file", addr
.getFile().toString(), true, "description", "0", "category", 1).createRuntimeProperty());

assertTimeoutPreemptively(Duration.ofSeconds(5), () -> {
sf.connect("localhost", 0, props, 1);
});
}
}

}

0 comments on commit 9524e32

Please sign in to comment.