aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-01-24 08:45:53 -0800
committerGarrett D'Amore <garrett@damore.org>2017-01-24 08:45:53 -0800
commit4c496d8182b5f3a5db6ca8fd763bab444e39f48a (patch)
tree1ec220c70d08951ce0f37d58255bd49d485c7701
parent7df0822d3ed58ee73918cac576c0b07363e84425 (diff)
downloadnng-4c496d8182b5f3a5db6ca8fd763bab444e39f48a.tar.gz
nng-4c496d8182b5f3a5db6ca8fd763bab444e39f48a.tar.bz2
nng-4c496d8182b5f3a5db6ca8fd763bab444e39f48a.zip
Implement reconnect timer including backoff.
This allows us to enable the last test case for compat_reqrep.
-rw-r--r--src/core/endpt.c35
-rw-r--r--src/core/socket.c2
-rw-r--r--tests/compat_reqrep.c9
3 files changed, 29 insertions, 17 deletions
diff --git a/src/core/endpt.c b/src/core/endpt.c
index 5a642a2f..9aae89eb 100644
--- a/src/core/endpt.c
+++ b/src/core/endpt.c
@@ -161,11 +161,31 @@ nni_dialer(void *arg)
nni_ep *ep = arg;
int rv;
nni_time cooldown;
+ nni_duration maxrtime;
+ nni_duration defrtime;
+ nni_duration rtime;
nni_mtx *mx = &ep->ep_sock->s_mx;
+ nni_mtx_lock(mx);
+ defrtime = ep->ep_sock->s_reconn;
+ if ((maxrtime = ep->ep_sock->s_reconnmax) == 0) {
+ maxrtime = defrtime;
+ }
+ nni_mtx_unlock(mx);
+
for (;;) {
nni_mtx_lock(mx);
+ if ((defrtime != ep->ep_sock->s_reconn) ||
+ (maxrtime != ep->ep_sock->s_reconnmax)) {
+ // Times changed, so reset them.
+ defrtime = ep->ep_sock->s_reconn;
+ if ((maxrtime = ep->ep_sock->s_reconnmax) == 0) {
+ maxrtime = defrtime;
+ }
+ rtime = defrtime;
+ }
while ((!ep->ep_close) && (ep->ep_pipe != NULL)) {
+ rtime = defrtime;
nni_cv_wait(&ep->ep_cv);
}
if (ep->ep_close) {
@@ -179,22 +199,19 @@ nni_dialer(void *arg)
case 0:
// good connection
continue;
- case NNG_ENOMEM:
- cooldown = 1000000;
- break;
case NNG_ECLOSED:
return;
default:
- // XXX: THIS NEEDS TO BE A PROPER BACKOFF.
- cooldown = 1000000;
+ cooldown = nni_clock() + rtime;
+ rtime *= 2;
+ if ((maxrtime >= defrtime) && (rtime > maxrtime)) {
+ rtime = maxrtime;
+ }
break;
}
// we inject a delay so we don't just spin hard on
- // errors like connection refused. For NNG_ENOMEM, we
- // wait even longer, since the system needs time to
- // release resources.
- cooldown += nni_clock();
+ // errors like connection refused.
nni_mtx_lock(mx);
while (!ep->ep_close) {
// We need a different condvar...
diff --git a/src/core/socket.c b/src/core/socket.c
index 24078941..b0ce172f 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -274,7 +274,7 @@ nni_sock_open(nni_sock **sockp, uint16_t pnum)
sock->s_rcvtimeo = -1;
sock->s_closing = 0;
sock->s_reconn = NNI_SECOND;
- sock->s_reconnmax = NNI_SECOND;
+ sock->s_reconnmax = 0;
sock->s_reapexit = 0;
NNI_LIST_INIT(&sock->s_pipes, nni_pipe, p_node);
NNI_LIST_INIT(&sock->s_reaps, nni_pipe, p_node);
diff --git a/tests/compat_reqrep.c b/tests/compat_reqrep.c
index a418b8d9..51ff4fb8 100644
--- a/tests/compat_reqrep.c
+++ b/tests/compat_reqrep.c
@@ -121,29 +121,24 @@ int main ()
test_close (rep1);
-#if 0 // The default reconnect interval is waaay to large for this to pass.
/* Check sending a request when the peer is not available. (It should
be sent immediatelly when the peer comes online rather than relying
on the resend algorithm. */
req1 = test_socket (AF_SP, NN_REQ);
timeo = 10;
- rc = nn_setsockopt (req1, NN_SOL_SOCKET, NN_RECONNECT_IVL,
- &timeo, sizeof (timeo));
+ test_setsockopt (req1, NN_SOL_SOCKET, NN_RECONNECT_IVL, &timeo, sizeof (timeo));
test_send (req1, "ABC");
test_connect (req1, SOCKET_ADDRESS);
rep1 = test_socket (AF_SP, NN_REP);
test_bind (rep1, SOCKET_ADDRESS);
timeo = 500;
- rc = nn_setsockopt (rep1, NN_SOL_SOCKET, NN_RCVTIMEO,
- &timeo, sizeof (timeo));
- printf("RC = %d errno %d (%s)\n", rc, errno, strerror(errno));
+ test_setsockopt (rep1, NN_SOL_SOCKET, NN_RCVTIMEO, &timeo, sizeof (timeo));
errno_assert (rc == 0);
test_recv (rep1, "ABC");
test_close (req1);
test_close (rep1);
-#endif
/* Check removing socket request sent to (It should
be sent immediatelly to other peer rather than relying