Skip to content

Commit

Permalink
SI-5734 Allow setting of socket timeout for remote actors
Browse files Browse the repository at this point in the history
TcpService is locked while connections are being established, preventing
messages being sent to remote nodes. There was no way to specify a connect
timeout, so the service was waiting for a ConnectException to be thrown if
the remote node was unavailable (which can take several minutes).

Added a system property to allow setting a socket connect timeout to
prevent the TcpService from being locked for minutes at a time.

Default behaviour is unchanged, all tests pass and the patch has been
running in production without issue.
  • Loading branch information
martinmcnulty committed May 3, 2013
1 parent 33e3217 commit 8325729
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions src/actors/scala/actors/remote/TcpService.scala
Expand Up @@ -14,7 +14,7 @@ package remote

import java.io.{DataInputStream, DataOutputStream, IOException}
import java.lang.{Thread, SecurityException}
import java.net.{InetAddress, ServerSocket, Socket, UnknownHostException}
import java.net.{InetAddress, InetSocketAddress, ServerSocket, Socket, SocketTimeoutException, UnknownHostException}

import scala.collection.mutable
import scala.util.Random
Expand Down Expand Up @@ -59,6 +59,23 @@ object TcpService {
portnum
}

private val connectTimeoutMillis = {
val propName = "scala.actors.tcpSocket.connectTimeoutMillis"
val defaultTimeoutMillis = 0
sys.props get propName flatMap {
timeout =>
try {
val to = timeout.toInt
Debug.info("Using socket timeout $to")
Some(to)
} catch {
case e: NumberFormatException =>
Debug.warning(s"""Could not parse $propName = "$timeout" as an Int""")
None
}
} getOrElse defaultTimeoutMillis
}

var BufSize: Int = 65536
}

Expand Down Expand Up @@ -176,7 +193,15 @@ class TcpService(port: Int, cl: ClassLoader) extends Thread with Service {
}

def connect(n: Node): TcpServiceWorker = synchronized {
val socket = new Socket(n.address, n.port)
val socket = new Socket()
val start = System.nanoTime
try {
socket.connect(new InetSocketAddress(n.address, n.port), TcpService.connectTimeoutMillis)
} catch {
case e: SocketTimeoutException =>
Debug.warning(f"Timed out connecting to $n after ${(System.nanoTime - start) / math.pow(10, 9)}%.3f seconds")
throw e
}
val worker = new TcpServiceWorker(this, socket)
worker.sendNode(n)
worker.start()
Expand Down

0 comments on commit 8325729

Please sign in to comment.