gopkg.in/dedis/onet.v2@v2.0.0-20181115163211-c8f3724038a7/simul/manage/close_all.go (about)

     1  package manage
     2  
     3  import (
     4  	"time"
     5  
     6  	"gopkg.in/dedis/onet.v2"
     7  	"gopkg.in/dedis/onet.v2/log"
     8  	"gopkg.in/dedis/onet.v2/network"
     9  )
    10  
    11  /*
    12  Protocol used to close all connections, starting from the leaf-nodes.
    13  It first sends down a message `PrepareClose` through the tree, then
    14  from the leaf-nodes a `Close`-message up to the root. Every node receiving
    15  the `Close`-message will shut down all network communications.
    16  
    17  The protocol waits for the `Close`-message to arrive at the root.
    18  */
    19  
    20  func init() {
    21  	network.RegisterMessage(PrepareClose{})
    22  	network.RegisterMessage(Close{})
    23  	onet.GlobalProtocolRegister("CloseAll", NewCloseAll)
    24  }
    25  
    26  // ProtocolCloseAll is the structure used to hold the Done-channel
    27  type ProtocolCloseAll struct {
    28  	*onet.TreeNodeInstance
    29  	// Done receives a 'true' once the protocol is done.
    30  	Done chan bool
    31  }
    32  
    33  // PrepareClose is sent down the tree until the nodes
    34  type PrepareClose struct{}
    35  
    36  // PrepareCloseMsg is the wrapper for the PrepareClose message
    37  type PrepareCloseMsg struct {
    38  	*onet.TreeNode
    39  	PrepareClose
    40  }
    41  
    42  // Close is sent to the parent just before the node shuts down
    43  type Close struct{}
    44  
    45  // CloseMsg is the wrapper for the Close message
    46  type CloseMsg struct {
    47  	*onet.TreeNode
    48  	Close
    49  }
    50  
    51  // NewCloseAll will create a new protocol
    52  func NewCloseAll(n *onet.TreeNodeInstance) (onet.ProtocolInstance, error) {
    53  	p := &ProtocolCloseAll{TreeNodeInstance: n}
    54  	p.Done = make(chan bool, 1)
    55  	if err := p.RegisterHandler(p.FuncPrepareClose); err != nil {
    56  		return nil, err
    57  	}
    58  	if err := p.RegisterHandler(p.FuncClose); err != nil {
    59  		return nil, err
    60  	}
    61  	return p, nil
    62  }
    63  
    64  // Start the protocol and waits for the `Close`-message to arrive back at
    65  // the root-node.
    66  func (p *ProtocolCloseAll) Start() error {
    67  	// Send an empty message
    68  	p.FuncPrepareClose(PrepareCloseMsg{TreeNode: p.TreeNode()})
    69  	// Wait till the end
    70  	<-p.Done
    71  	return nil
    72  }
    73  
    74  // FuncPrepareClose sends a `PrepareClose`-message down the tree.
    75  func (p *ProtocolCloseAll) FuncPrepareClose(pc PrepareCloseMsg) error {
    76  	log.Lvl3(pc.ServerIdentity.Address, "sent PrepClose to", p.ServerIdentity().Address)
    77  	if !p.IsLeaf() {
    78  		for _, c := range p.Children() {
    79  			err := p.SendTo(c, &PrepareClose{})
    80  			log.Lvl3(p.ServerIdentity().Address, "sends to", c.ServerIdentity.Address, "(err=", err, ")")
    81  		}
    82  	} else {
    83  		p.FuncClose(nil)
    84  	}
    85  	return nil
    86  }
    87  
    88  // FuncClose is called from the leafs to the parents and up the tree. Everybody
    89  // receiving all `Close`-messages from all children will close down all
    90  // network communication.
    91  func (p *ProtocolCloseAll) FuncClose(c []CloseMsg) error {
    92  	if !p.IsRoot() {
    93  		log.Lvl3("Sending closeall from", p.ServerIdentity().Address,
    94  			"to", p.Parent().ServerIdentity.Address)
    95  		if err := p.SendTo(p.Parent(), &Close{}); err != nil {
    96  			log.Error(p.Info(), "couldn't send 'close' tp parent",
    97  				p.Parent(), err)
    98  		}
    99  	}
   100  	time.Sleep(time.Second)
   101  	log.Lvl3("Closing host", p.ServerIdentity().Address)
   102  	err := p.TreeNodeInstance.CloseHost()
   103  	if err != nil {
   104  		log.Error("Couldn't close:", err)
   105  	}
   106  	if p.IsRoot() {
   107  		log.Lvl2("Root received Close")
   108  		p.Done <- true
   109  	}
   110  	p.TreeNodeInstance.Done()
   111  	return nil
   112  }