github.com/mre-fog/trillianxx@v1.1.2-0.20180615153820-ae375a99d36a/util/election/stub/election.go (about)

     1  // Copyright 2018 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package stub contains a MasterElection implementation for testing.
    16  package stub
    17  
    18  import (
    19  	"context"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/google/trillian/util"
    24  	"github.com/google/trillian/util/election"
    25  )
    26  
    27  // Errors contains errors to be returned by each of MasterElection methods.
    28  type Errors struct {
    29  	Start     error
    30  	Wait      error // WaitForMastership error.
    31  	IsMaster  error
    32  	Resign    error // ResignAndRestart error.
    33  	Close     error
    34  	GetMaster error // GetCurrentMaster error.
    35  }
    36  
    37  // ErrAll creates Errors containing the same err associated with each method.
    38  func ErrAll(err error) *Errors {
    39  	return &Errors{err, err, err, err, err, err}
    40  }
    41  
    42  // MasterElection implements election.MasterElection interface for testing.
    43  type MasterElection struct {
    44  	isMaster bool
    45  	errs     Errors
    46  	mu       sync.RWMutex
    47  }
    48  
    49  // NewMasterElection returns a new initialized MasterElection for testing.
    50  func NewMasterElection(isMaster bool, errs *Errors) *MasterElection {
    51  	me := &MasterElection{isMaster: isMaster}
    52  	if errs != nil {
    53  		me.errs = *errs
    54  	}
    55  	return me
    56  }
    57  
    58  // Update changes mastership status and errors returned by interface calls.
    59  func (e *MasterElection) Update(isMaster bool, errs *Errors) {
    60  	e.mu.Lock()
    61  	defer e.mu.Unlock()
    62  	if errs == nil {
    63  		errs = &Errors{}
    64  	}
    65  	e.isMaster, e.errs = isMaster, *errs
    66  }
    67  
    68  // Start returns the stored error for this call.
    69  func (e *MasterElection) Start(context.Context) error {
    70  	e.mu.RLock()
    71  	defer e.mu.RUnlock()
    72  	return e.errs.Start
    73  }
    74  
    75  // WaitForMastership blocks until this instance is master, or an error is
    76  // supplied, or context is done.
    77  func (e *MasterElection) WaitForMastership(ctx context.Context) error {
    78  	for {
    79  		is, err := func() (bool, error) {
    80  			e.mu.Lock()
    81  			defer e.mu.Unlock()
    82  			if ctx.Err() != nil {
    83  				return false, ctx.Err()
    84  			}
    85  			if e.errs.Wait != nil {
    86  				return false, e.errs.Wait
    87  			}
    88  			return e.isMaster, nil
    89  		}()
    90  		if is || err != nil {
    91  			return err
    92  		}
    93  		if err := util.SleepContext(ctx, 5*time.Millisecond); err != nil {
    94  			return err
    95  		}
    96  	}
    97  }
    98  
    99  // IsMaster returns the stored mastership status and error.
   100  func (e *MasterElection) IsMaster(context.Context) (bool, error) {
   101  	e.mu.RLock()
   102  	defer e.mu.RUnlock()
   103  	return e.isMaster, e.errs.IsMaster
   104  }
   105  
   106  // Resign returns the stored error and resets mastership status if the error is
   107  // nil.
   108  func (e *MasterElection) Resign(context.Context) error {
   109  	e.mu.Lock()
   110  	defer e.mu.Unlock()
   111  	if e.errs.Resign == nil {
   112  		e.isMaster = false
   113  	}
   114  	return e.errs.Resign
   115  }
   116  
   117  // Close returns the stored error.
   118  func (e *MasterElection) Close(context.Context) error {
   119  	e.mu.RLock()
   120  	defer e.mu.RUnlock()
   121  	return e.errs.Close
   122  }
   123  
   124  // GetCurrentMaster returns the current master which is *this* instance, or
   125  // error if not currently the master.
   126  func (e *MasterElection) GetCurrentMaster(context.Context) (string, error) {
   127  	e.mu.RLock()
   128  	defer e.mu.RUnlock()
   129  	if e.errs.GetMaster != nil {
   130  		return "", e.errs.GetMaster
   131  	}
   132  	if e.isMaster {
   133  		return "self", nil
   134  	}
   135  	return "", election.ErrNoMaster
   136  }