|
@@ -165,6 +165,8 @@ public class ClientCnxn {
|
|
|
|
|
|
private int readTimeout;
|
|
|
|
|
|
+ private int expirationTimeout;
|
|
|
+
|
|
|
private final int sessionTimeout;
|
|
|
|
|
|
private final ZKWatchManager watchManager;
|
|
@@ -411,6 +413,7 @@ public class ClientCnxn {
|
|
|
|
|
|
this.connectTimeout = sessionTimeout / hostProvider.size();
|
|
|
this.readTimeout = sessionTimeout * 2 / 3;
|
|
|
+ this.expirationTimeout = sessionTimeout * 4 / 3;
|
|
|
|
|
|
this.sendThread = new SendThread(clientCnxnSocket);
|
|
|
this.eventThread = new EventThread();
|
|
@@ -803,6 +806,12 @@ public class ClientCnxn {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ private static class ConnectionTimeoutException extends IOException {
|
|
|
+ public ConnectionTimeoutException(String message) {
|
|
|
+ super(message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static class SessionTimeoutException extends IOException {
|
|
|
|
|
|
private static final long serialVersionUID = 824482094072071178L;
|
|
@@ -1143,7 +1152,7 @@ public class ClientCnxn {
|
|
|
startConnect(serverAddress);
|
|
|
// Update now to start the connection timer right after we make a connection attempt
|
|
|
clientCnxnSocket.updateNow();
|
|
|
- clientCnxnSocket.updateLastSendAndHeard();
|
|
|
+ clientCnxnSocket.updateLastSend();
|
|
|
}
|
|
|
|
|
|
if (state.isConnected()) {
|
|
@@ -1181,16 +1190,24 @@ public class ClientCnxn {
|
|
|
}
|
|
|
to = readTimeout - clientCnxnSocket.getIdleRecv();
|
|
|
} else {
|
|
|
- to = connectTimeout - clientCnxnSocket.getIdleRecv();
|
|
|
+ to = connectTimeout - clientCnxnSocket.getIdleSend();
|
|
|
}
|
|
|
|
|
|
- if (to <= 0) {
|
|
|
+ int expiration = expirationTimeout - clientCnxnSocket.getIdleRecv();
|
|
|
+ if (expiration <= 0) {
|
|
|
String warnInfo = String.format(
|
|
|
"Client session timed out, have not heard from server in %dms for session id 0x%s",
|
|
|
clientCnxnSocket.getIdleRecv(),
|
|
|
Long.toHexString(sessionId));
|
|
|
LOG.warn(warnInfo);
|
|
|
+ changeZkState(States.CLOSED);
|
|
|
throw new SessionTimeoutException(warnInfo);
|
|
|
+ } else if (to <= 0) {
|
|
|
+ String warnInfo = String.format(
|
|
|
+ "Client connection timed out, have not heard from server in %dms for session id 0x%s",
|
|
|
+ clientCnxnSocket.getIdleRecv(),
|
|
|
+ Long.toHexString(sessionId));
|
|
|
+ throw new ConnectionTimeoutException(warnInfo);
|
|
|
}
|
|
|
if (state.isConnected()) {
|
|
|
//1000(1 second) is to prevent race condition missing to send the second ping
|
|
@@ -1235,7 +1252,7 @@ public class ClientCnxn {
|
|
|
} else {
|
|
|
LOG.warn(
|
|
|
"Session 0x{} for server {}, Closing socket connection. "
|
|
|
- + "Attempting reconnect except it is a SessionExpiredException.",
|
|
|
+ + "Attempting reconnect except it is a SessionExpiredException or SessionTimeoutException.",
|
|
|
Long.toHexString(getSessionId()),
|
|
|
serverAddress,
|
|
|
e);
|
|
@@ -1256,7 +1273,12 @@ public class ClientCnxn {
|
|
|
if (state.isAlive()) {
|
|
|
eventThread.queueEvent(new WatchedEvent(Event.EventType.None, Event.KeeperState.Disconnected, null));
|
|
|
}
|
|
|
- eventThread.queueEvent(new WatchedEvent(Event.EventType.None, Event.KeeperState.Closed, null));
|
|
|
+ if (closing) {
|
|
|
+ eventThread.queueEvent(new WatchedEvent(Event.EventType.None, KeeperState.Closed, null));
|
|
|
+ } else if (state == States.CLOSED) {
|
|
|
+ eventThread.queueEvent(new WatchedEvent(Event.EventType.None, KeeperState.Expired, null));
|
|
|
+ }
|
|
|
+ eventThread.queueEventOfDeath();
|
|
|
|
|
|
Login l = loginRef.getAndSet(null);
|
|
|
if (l != null) {
|
|
@@ -1274,7 +1296,6 @@ public class ClientCnxn {
|
|
|
eventThread.queueEvent(new WatchedEvent(Event.EventType.None, Event.KeeperState.Disconnected, null));
|
|
|
}
|
|
|
clientCnxnSocket.updateNow();
|
|
|
- clientCnxnSocket.updateLastSendAndHeard();
|
|
|
}
|
|
|
|
|
|
private void pingRwServer() throws RWServerFoundException {
|
|
@@ -1374,6 +1395,7 @@ public class ClientCnxn {
|
|
|
}
|
|
|
|
|
|
readTimeout = negotiatedSessionTimeout * 2 / 3;
|
|
|
+ expirationTimeout = negotiatedSessionTimeout * 4 / 3;
|
|
|
connectTimeout = negotiatedSessionTimeout / hostProvider.size();
|
|
|
hostProvider.onConnected();
|
|
|
sessionId = _sessionId;
|