github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/watchdog/overseer.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package watchdog
     7  
     8  //func NewPassiveOverseer(name string) *Overseer {
     9  //	return &Overseer{name: name}
    10  //}
    11  //
    12  //func NewActiveOverseer(name string, heartbeatPeriod time.Duration, workersHint int) *Overseer {
    13  //
    14  //	if heartbeatPeriod <= 0 {
    15  //		panic("illegal value")
    16  //	}
    17  //
    18  //	if workersHint <= 0 {
    19  //		workersHint = 10
    20  //	}
    21  //
    22  //	chanLimit := uint64(1+time.Second/heartbeatPeriod) * uint64(workersHint)
    23  //	if chanLimit > 10000 {
    24  //		chanLimit = 10000 // keep it reasonable
    25  //	}
    26  //
    27  //	return &Overseer{name: name, heartbeatPeriod: heartbeatPeriod,
    28  //		beatChannel: make(chan Heartbeat, chanLimit)}
    29  //}
    30  //
    31  //type monitoringMap map[HeartbeatID]*monitoringEntry
    32  //
    33  //type Overseer struct {
    34  //	name            string
    35  //	beaters         monitoringMap
    36  //	atomicIDCounter uint32
    37  //	heartbeatPeriod time.Duration
    38  //	beatChannel     chan Heartbeat
    39  //}
    40  //
    41  //func (seer *Overseer) StartActive(ctx context.Context) {
    42  //	if seer.beatChannel == nil {
    43  //		panic("illegal state")
    44  //	}
    45  //
    46  //	m := activeMonitor{seer, &seer.beaters, seer.beatChannel}
    47  //	go m.worker(ctx)
    48  //}
    49  //
    50  //func (seer *Overseer) AttachContext(ctx context.Context) context.Context {
    51  //	ok, factory := FromContext(ctx)
    52  //	if ok {
    53  //		if factory == seer {
    54  //			return ctx
    55  //		}
    56  //		panic("context is under supervision")
    57  //	}
    58  //	seer.ensure()
    59  //	return WithFactory(ctx, "", seer)
    60  //}
    61  //
    62  //func (seer *Overseer) ensure() {
    63  //}
    64  //
    65  //func (seer *Overseer) GetNewID() uint32 {
    66  //	for {
    67  //		v := atomic.LoadUint32(&seer.atomicIDCounter)
    68  //		if atomic.CompareAndSwapUint32(&seer.atomicIDCounter, v, v+1) {
    69  //			return v + 1
    70  //		}
    71  //	}
    72  //}
    73  //
    74  //func (seer *Overseer) CreateGenerator(name string) *HeartbeatGenerator {
    75  //	id := seer.GetNewID()
    76  //
    77  //	period := seer.heartbeatPeriod
    78  //	if period == 0 && seer.beatChannel == nil {
    79  //		period = math.MaxInt64 //zero state should not cause excessive attempts
    80  //	}
    81  //
    82  //	entryI, loaded := seer.beaters.LoadOrStore(id, &monitoringEntry{name: name})
    83  //
    84  //	entry := entryI.(*monitoringEntry)
    85  //	if !loaded {
    86  //		newGen := NewHeartbeatGenerator(id, period, seer.beatChannel)
    87  //		entry.generator = &newGen
    88  //	}
    89  //	return entry.generator
    90  //}
    91  //
    92  //func (seer *Overseer) cleanup() *HeartbeatGenerator {
    93  //
    94  //}
    95  //
    96  //type monitoringEntry struct {
    97  //	name      string
    98  //	generator *HeartbeatGenerator
    99  //}
   100  //
   101  //type activeMonitor struct {
   102  //	seer    *Overseer
   103  //	beaters *sync.Map
   104  //
   105  //	beatChannel chan Heartbeat
   106  //}
   107  //
   108  //func (m *activeMonitor) worker(ctx context.Context) {
   109  //	defer close(m.beatChannel)
   110  //
   111  //	var prevRecent map[HeartbeatID]*monitoringEntry
   112  //
   113  //	// tick-tack model to detect stuck items
   114  //	for {
   115  //		recent := make(map[HeartbeatID]*monitoringEntry, len(prevRecent)+1)
   116  //		if !m.workOnMap(ctx, recent, nil) {
   117  //			return
   118  //		}
   119  //		prevRecent = recent
   120  //	}
   121  //}
   122  //
   123  //func (m *activeMonitor) workOnMap(ctx context.Context, recent map[HeartbeatID]*monitoringEntry, expire <-chan time.Time) bool {
   124  //	for {
   125  //		select {
   126  //		case <-ctx.Done():
   127  //			return false
   128  //		case <-expire:
   129  //			return true
   130  //		case beat := <-m.beatChannel:
   131  //			storedGen, ok := m.beaters.Load(beat.From)
   132  //			if !ok {
   133  //				m.missingEntryHeartbeat(beat)
   134  //			}
   135  //			me := storedGen.(*monitoringEntry)
   136  //			recent[beat.From] = me
   137  //			m.applyHeartbeat(beat, storedGen.(*monitoringEntry))
   138  //		}
   139  //	}
   140  //}
   141  //
   142  //func (m *activeMonitor) applyHeartbeat(heartbeat Heartbeat, entry *monitoringEntry) {
   143  //	if heartbeat.IsCancelled() {
   144  //		m.beaters.Delete(heartbeat.From)
   145  //	}
   146  //}
   147  //
   148  //func (m *activeMonitor) missingEntryHeartbeat(heartbeat Heartbeat) {
   149  //}