github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/storage/repair/options.go (about)

     1  // Copyright (c) 2016 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 repair
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"time"
    27  
    28  	"github.com/m3db/m3/src/dbnode/client"
    29  	"github.com/m3db/m3/src/dbnode/storage/bootstrap/result"
    30  	"github.com/m3db/m3/src/dbnode/topology"
    31  )
    32  
    33  const (
    34  	defaultRepairType     = DefaultRepair
    35  	defaultRepairStrategy = DefaultStrategy
    36  	// Allow repairs to progress when a single peer is down (I.E during single node failure
    37  	// or deployments).
    38  	defaultRepairConsistencyLevel           = topology.ReadConsistencyLevelUnstrictMajority
    39  	defaultRepairCheckInterval              = time.Minute
    40  	defaultRepairThrottle                   = 90 * time.Second
    41  	defaultRepairShardConcurrency           = 1
    42  	defaultDebugShadowComparisonsEnabled    = false
    43  	defaultDebugShadowComparisonsPercentage = 1.0
    44  )
    45  
    46  var (
    47  	errNoAdminClient                           = errors.New("no admin client in repair options")
    48  	errInvalidRepairCheckInterval              = errors.New("invalid repair check interval in repair options")
    49  	errInvalidRepairThrottle                   = errors.New("invalid repair throttle in repair options")
    50  	errNoReplicaMetadataSlicePool              = errors.New("no replica metadata pool in repair options")
    51  	errNoResultOptions                         = errors.New("no result options in repair options")
    52  	errInvalidDebugShadowComparisonsPercentage = errors.New("debug shadow comparisons percentage must be between 0 and 1")
    53  )
    54  
    55  type options struct {
    56  	repairType                       Type
    57  	strategy                         Strategy
    58  	force                            bool
    59  	adminClients                     []client.AdminClient
    60  	repairConsistencyLevel           topology.ReadConsistencyLevel
    61  	repairShardConcurrency           int
    62  	repairCheckInterval              time.Duration
    63  	repairThrottle                   time.Duration
    64  	replicaMetadataSlicePool         ReplicaMetadataSlicePool
    65  	resultOptions                    result.Options
    66  	debugShadowComparisonsEnabled    bool
    67  	debugShadowComparisonsPercentage float64
    68  }
    69  
    70  // NewOptions creates new bootstrap options
    71  func NewOptions() Options {
    72  	return &options{
    73  		repairType:                       defaultRepairType,
    74  		strategy:                         defaultRepairStrategy,
    75  		repairConsistencyLevel:           defaultRepairConsistencyLevel,
    76  		repairShardConcurrency:           defaultRepairShardConcurrency,
    77  		repairCheckInterval:              defaultRepairCheckInterval,
    78  		repairThrottle:                   defaultRepairThrottle,
    79  		replicaMetadataSlicePool:         NewReplicaMetadataSlicePool(nil, 0),
    80  		resultOptions:                    result.NewOptions(),
    81  		debugShadowComparisonsEnabled:    defaultDebugShadowComparisonsEnabled,
    82  		debugShadowComparisonsPercentage: defaultDebugShadowComparisonsPercentage,
    83  	}
    84  }
    85  
    86  func (o *options) SetType(value Type) Options {
    87  	opts := *o
    88  	opts.repairType = value
    89  	return &opts
    90  }
    91  
    92  func (o *options) Type() Type {
    93  	return o.repairType
    94  }
    95  
    96  func (o *options) SetStrategy(value Strategy) Options {
    97  	opts := *o
    98  	opts.strategy = value
    99  	return &opts
   100  }
   101  
   102  func (o *options) Strategy() Strategy {
   103  	return o.strategy
   104  }
   105  
   106  func (o *options) SetForce(value bool) Options {
   107  	opts := *o
   108  	opts.force = value
   109  	return &opts
   110  }
   111  
   112  func (o *options) Force() bool {
   113  	return o.force
   114  }
   115  
   116  func (o *options) SetAdminClients(value []client.AdminClient) Options {
   117  	opts := *o
   118  	opts.adminClients = value
   119  	return &opts
   120  }
   121  
   122  func (o *options) AdminClients() []client.AdminClient {
   123  	return o.adminClients
   124  }
   125  
   126  func (o *options) SetRepairConsistencyLevel(value topology.ReadConsistencyLevel) Options {
   127  	opts := *o
   128  	opts.repairConsistencyLevel = value
   129  	return &opts
   130  }
   131  
   132  func (o *options) RepairConsistencyLevel() topology.ReadConsistencyLevel {
   133  	return o.repairConsistencyLevel
   134  }
   135  
   136  func (o *options) SetRepairShardConcurrency(value int) Options {
   137  	opts := *o
   138  	opts.repairShardConcurrency = value
   139  	return &opts
   140  }
   141  
   142  func (o *options) RepairShardConcurrency() int {
   143  	return o.repairShardConcurrency
   144  }
   145  
   146  func (o *options) SetRepairCheckInterval(value time.Duration) Options {
   147  	opts := *o
   148  	opts.repairCheckInterval = value
   149  	return &opts
   150  }
   151  
   152  func (o *options) RepairCheckInterval() time.Duration {
   153  	return o.repairCheckInterval
   154  }
   155  
   156  func (o *options) SetRepairThrottle(value time.Duration) Options {
   157  	opts := *o
   158  	opts.repairThrottle = value
   159  	return &opts
   160  }
   161  
   162  func (o *options) RepairThrottle() time.Duration {
   163  	return o.repairThrottle
   164  }
   165  
   166  func (o *options) SetReplicaMetadataSlicePool(value ReplicaMetadataSlicePool) Options {
   167  	opts := *o
   168  	opts.replicaMetadataSlicePool = value
   169  	return &opts
   170  }
   171  
   172  func (o *options) ReplicaMetadataSlicePool() ReplicaMetadataSlicePool {
   173  	return o.replicaMetadataSlicePool
   174  }
   175  
   176  func (o *options) SetResultOptions(value result.Options) Options {
   177  	opts := *o
   178  	opts.resultOptions = value
   179  	return &opts
   180  }
   181  
   182  func (o *options) ResultOptions() result.Options {
   183  	return o.resultOptions
   184  }
   185  
   186  func (o *options) SetDebugShadowComparisonsEnabled(value bool) Options {
   187  	opts := *o
   188  	opts.debugShadowComparisonsEnabled = value
   189  	return &opts
   190  }
   191  
   192  func (o *options) DebugShadowComparisonsEnabled() bool {
   193  	return o.debugShadowComparisonsEnabled
   194  }
   195  
   196  func (o *options) SetDebugShadowComparisonsPercentage(value float64) Options {
   197  	opts := *o
   198  	opts.debugShadowComparisonsPercentage = value
   199  	return &opts
   200  }
   201  
   202  func (o *options) DebugShadowComparisonsPercentage() float64 {
   203  	return o.debugShadowComparisonsPercentage
   204  }
   205  
   206  func (o *options) Validate() error {
   207  	if len(o.adminClients) == 0 {
   208  		return errNoAdminClient
   209  	}
   210  
   211  	var prevOrigin string
   212  	for _, c := range o.adminClients {
   213  		currOrigin := c.Options().(client.AdminOptions).Origin().ID()
   214  		if prevOrigin == "" {
   215  			prevOrigin = currOrigin
   216  			continue
   217  		}
   218  
   219  		if currOrigin != prevOrigin {
   220  			return fmt.Errorf(
   221  				"all repair clients should have the same origin, prev: %s, curr: %s",
   222  				prevOrigin, currOrigin)
   223  		}
   224  	}
   225  
   226  	if o.repairCheckInterval < 0 {
   227  		return errInvalidRepairCheckInterval
   228  	}
   229  	if o.repairThrottle < 0 {
   230  		return errInvalidRepairThrottle
   231  	}
   232  	if o.replicaMetadataSlicePool == nil {
   233  		return errNoReplicaMetadataSlicePool
   234  	}
   235  	if o.resultOptions == nil {
   236  		return errNoResultOptions
   237  	}
   238  	if o.debugShadowComparisonsPercentage > 1.0 ||
   239  		o.debugShadowComparisonsPercentage < 0 {
   240  		return errInvalidDebugShadowComparisonsPercentage
   241  	}
   242  	return nil
   243  }