github.com/m3db/m3@v1.5.0/src/m3em/node/listener.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package node
    22  
    23  import (
    24  	"sync"
    25  	"time"
    26  )
    27  
    28  // NewListener creates a new listener
    29  func NewListener(
    30  	onProcessTerminate func(ServiceNode, string),
    31  	onHeartbeatTimeout func(ServiceNode, time.Time),
    32  	onOverwrite func(ServiceNode, string),
    33  ) Listener {
    34  	return &listener{
    35  		onProcessTerminate: onProcessTerminate,
    36  		onHeartbeatTimeout: onHeartbeatTimeout,
    37  		onOverwrite:        onOverwrite,
    38  	}
    39  }
    40  
    41  type listener struct {
    42  	onProcessTerminate func(ServiceNode, string)
    43  	onHeartbeatTimeout func(ServiceNode, time.Time)
    44  	onOverwrite        func(ServiceNode, string)
    45  }
    46  
    47  func (l *listener) OnProcessTerminate(node ServiceNode, desc string) {
    48  	if l.onProcessTerminate != nil {
    49  		l.onProcessTerminate(node, desc)
    50  	}
    51  }
    52  
    53  func (l *listener) OnHeartbeatTimeout(node ServiceNode, lastHeartbeatTs time.Time) {
    54  	if l.onHeartbeatTimeout != nil {
    55  		l.onHeartbeatTimeout(node, lastHeartbeatTs)
    56  	}
    57  }
    58  
    59  func (l *listener) OnOverwrite(node ServiceNode, desc string) {
    60  	if l.onOverwrite != nil {
    61  		l.onOverwrite(node, desc)
    62  	}
    63  }
    64  
    65  type listenerGroup struct {
    66  	sync.Mutex
    67  	node  ServiceNode
    68  	elems map[int]Listener
    69  	token int
    70  }
    71  
    72  func newListenerGroup(node ServiceNode) *listenerGroup {
    73  	return &listenerGroup{
    74  		node:  node,
    75  		elems: make(map[int]Listener),
    76  	}
    77  }
    78  
    79  func (lg *listenerGroup) add(l Listener) int {
    80  	lg.Lock()
    81  	defer lg.Unlock()
    82  	lg.token++
    83  	lg.elems[lg.token] = l
    84  	return lg.token
    85  }
    86  
    87  func (lg *listenerGroup) clear() {
    88  	lg.Lock()
    89  	defer lg.Unlock()
    90  	for i := range lg.elems {
    91  		delete(lg.elems, i)
    92  	}
    93  }
    94  
    95  func (lg *listenerGroup) remove(t int) {
    96  	lg.Lock()
    97  	defer lg.Unlock()
    98  	delete(lg.elems, t)
    99  }
   100  
   101  func (lg *listenerGroup) notifyTimeout(lastTs time.Time) {
   102  	lg.Lock()
   103  	defer lg.Unlock()
   104  	for _, l := range lg.elems {
   105  		go l.OnHeartbeatTimeout(lg.node, lastTs)
   106  	}
   107  }
   108  
   109  func (lg *listenerGroup) notifyTermination(desc string) {
   110  	lg.Lock()
   111  	defer lg.Unlock()
   112  	for _, l := range lg.elems {
   113  		go l.OnProcessTerminate(lg.node, desc)
   114  	}
   115  }
   116  
   117  func (lg *listenerGroup) notifyOverwrite(desc string) {
   118  	lg.Lock()
   119  	defer lg.Unlock()
   120  	for _, l := range lg.elems {
   121  		go l.OnOverwrite(lg.node, desc)
   122  	}
   123  }