Skip to content

Commit

Permalink
Merge tag v13.4.0 into v14.x.x
Browse files Browse the repository at this point in the history
  • Loading branch information
Gavin Norman committed May 2, 2018
2 parents 73436b5 + 89cfee0 commit 54336b9
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 63 deletions.
17 changes: 17 additions & 0 deletions relnotes/retryhandshake-logging.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### `RetryHandshake` now has built-in logging

`dhtproto.client.legacy.internal.helper.RetryHandshake`

The helper logs the following events:
* Each time it starts a handshake. (info)
* When the handshake succeeds for a node. (info)
* When the handshake succeeds for all nodes. (info)
* When the handshake finished but did not succeed for all nodes and will be
retried. (info)
* Whenever the handshake notifier is called. (trace)

Applications that already use this helper may have implemented their own logging
behaviour in the handshake callbacks. It is recommended that this logging is
removed. You should be able to rely on the standard logging output of
`RetryHandshake` now.

46 changes: 42 additions & 4 deletions src/dhtproto/client/legacy/internal/helper/Mirror.d
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)
import ocean.util.log.Logger;
import ocean.text.convert.Formatter;
import swarm.Const : NodeItem;
import dhtproto.util.Verify;

/// Core functionality shared by Listen and GetAll handlers.
private final class SingleNodeRequest
Expand All @@ -51,11 +52,12 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)
{
None,
Assigned,
Scheduled
Scheduled,
Running
}

/// State of the request.
public State state = State.None;
private State state = State.None;

/// Logger for this request.
private Logger log;
Expand Down Expand Up @@ -115,6 +117,39 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)
this.state = State.Scheduled;
}
}

/***********************************************************************
Resets the internal state. Should be called when the request
finishes.
***********************************************************************/

public void finished ( )
{
this.state = State.None;
}

/***********************************************************************
Handles the state change from Assigned / Schedulued -> Running.
Should be called when the request receives a record. (The API of the
GetAll and Mirror requests do not provide any other way of telling
when a request has been successfully established.)
***********************************************************************/

public void receivedRecord ( )
{
if ( this.state == State.Running )
return;

verify(this.state == State.Assigned ||
this.state == State.Scheduled);

this.state = State.Running;
log.info("Started receiving data.");
}
}

/// Single-node Listen request handler.
Expand Down Expand Up @@ -168,6 +203,7 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)
private void receiveRecord ( Dht.RequestContext, in char[] key,
in char[] value )
{
this.core.receivedRecord();
this.outer.receiveRecord(key, value, true);
}

Expand All @@ -189,7 +225,7 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)

if ( info.type == info.type.Finished )
{
this.core.state = this.core.state.None;
this.core.finished();

// No need to check `info.succeeded` -- a Listen request can
// never end cleanly.
Expand All @@ -202,6 +238,7 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)
}
}

/// Single-node GetAll request handler.
private class GetAll
{
/// Core single-node request functionality.
Expand Down Expand Up @@ -270,6 +307,7 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)
private void receiveRecord ( Dht.RequestContext, in char[] key,
in char[] value )
{
this.core.receivedRecord();
this.outer.receiveRecord(key, value, false);
}

Expand All @@ -291,7 +329,7 @@ abstract public class Mirror ( Dht : DhtClient ) : MirrorBase!(Dht)

if ( info.type == info.type.Finished )
{
this.core.state = this.core.state.None;
this.core.finished();

if ( info.succeeded )
{
Expand Down
105 changes: 46 additions & 59 deletions src/dhtproto/client/legacy/internal/helper/RetryHandshake.d
Original file line number Diff line number Diff line change
Expand Up @@ -24,74 +24,51 @@ class RetryHandshake

import ocean.io.select.EpollSelectDispatcher;
import ocean.io.select.client.TimerEvent;
import ocean.util.log.Logger;

/***************************************************************************
Timer to retry the handshake
***************************************************************************/
/// Logger for instances of this class.
/// Note: in theory, an application may have multiple instances of this
/// class. Currently, these will all write to the same logger (which will
/// result in a confusing mess). This is a highly unusual case, though,
/// so is not specifically supported. We can add better support, if it's
/// ever needed.
private Logger log;

/// Timer to retry the handshake.
protected TimerEvent timer;

/***************************************************************************
DHT CLIENT. YES!
***************************************************************************/

/// DHT client to use to perform handshakes.
protected DhtClient dht;

/***************************************************************************
Epoll
***************************************************************************/

/// Epoll instance to register timer with.
protected EpollSelectDispatcher epoll;

/***************************************************************************
Time to wait before retrying
***************************************************************************/

/// Time to wait (in seconds) before retrying, after an incomplete
/// handshake.
protected size_t wait_time;

/***************************************************************************
Set of nodes which have already handshaken succesfully. (Nodes are only
added to this set, never removed.)
***************************************************************************/

/// Set of nodes which have already handshaken succesfully. (Nodes are only
/// added to this set, never removed.)
private bool[hash_t] established_nodes;

/***************************************************************************
Delegate that will be called on success of a complete handshake (i.e.
the handshake has succeeded for every node)
***************************************************************************/

/// Delegate that will be called on success of a complete handshake (i.e.
/// the handshake has succeeded for every node).
protected void delegate ( ) handshake_complete_dg;

/***************************************************************************
Delegate that will be called on the first successful handshake with each
individual node
***************************************************************************/

/// Delegate that will be called on the first successful handshake with each
/// individual node.
protected void delegate ( NodeItem ) one_node_handshake_dg;

/***************************************************************************
Constructor
Constructor. Initiates the handshake (and the retrying process, if the
handshake does not complete on the first attempt).
Params:
epoll = epoll instance
dht = dht client
wait_time = time to wait in seconds
dht = dht client
wait_time = time to wait (in seconds) before retrying, after an
incomplete handshake
handshake_complete_dg = delegate to call on success, optional
one_node_handshake_dg = delegate to call on connecting to one node,
optional
Expand All @@ -113,32 +90,33 @@ class RetryHandshake

this.timer = new TimerEvent(&this.tryHandshake);

this.log = Log.lookup("RetryHandshake");

this.tryHandshake();
}

/***************************************************************************
try doing the handshake
Try doing the handshake.
Returns:
false, so the timer doesn't stay registered
false, so the timer doesn't stay registered. (Re-registering the
timer is handled by the `result` method.)
***************************************************************************/

protected bool tryHandshake ( )
{
this.log.info("Attempting handshake.");
this.dht.nodeHandshake(&this.result, &this.handshake_notifier);

return false;
}

/***************************************************************************
handshake callback
Calls the user delegate on success, else retries the handshake after the
specified wait time
Handshake callback. Calls the user delegate on success, else retries the
handshake after the specified wait time.
Params:
success = whether the handshake was a success
Expand All @@ -151,12 +129,14 @@ class RetryHandshake
{
this.error();

this.log.info("Handshake did not succeed for all nodes. Retrying in {}s",
this.wait_time);
this.epoll.register(this.timer);

this.timer.set(this.wait_time, 0, 0, 0);
}
else
{
this.log.info("Handshake succeeded for all nodes.");
this.success();

if ( this.handshake_complete_dg !is null )
Expand All @@ -179,6 +159,8 @@ class RetryHandshake

private void handshake_notifier ( DhtClient.RequestNotification info )
{
this.log.trace("Callback: {}", info.message(this.dht.msg_buf));

this.nodeHandshakeCB(info);

if ( info.type != info.type.Finished )
Expand All @@ -203,6 +185,8 @@ class RetryHandshake
{
this.established_nodes[node_hash] = true;
this.one_node_handshake_dg(info.nodeitem);
this.log.info("Handshake succeeded on {}:{}.",
info.nodeitem.Address, info.nodeitem.Port);
}
}
}
Expand All @@ -212,23 +196,26 @@ class RetryHandshake
Optionally overrideable handshake notifier callback, called from
handshake_notifier().
Params:
info = DHT request notification for one of the requests involved in
the handshake
***************************************************************************/

protected void nodeHandshakeCB ( DhtClient.RequestNotification info ) { }


/***************************************************************************
Called when the handshake failed and it will be retried
Called when the handshake failed and it will be retried.
***************************************************************************/

protected void error ( ) { }


/***************************************************************************
Called when the handshake succeeded and the user delegate will be called
Called when the handshake succeeded and the user delegate will be
called.
***************************************************************************/

Expand Down
Loading

0 comments on commit 54336b9

Please sign in to comment.