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 }