github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/persist/fs/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 fs 22 23 import ( 24 "errors" 25 "fmt" 26 "os" 27 28 "github.com/m3db/m3/src/dbnode/persist/fs/msgpack" 29 "github.com/m3db/m3/src/dbnode/runtime" 30 "github.com/m3db/m3/src/m3ninx/index/segment/fst" 31 "github.com/m3db/m3/src/x/clock" 32 "github.com/m3db/m3/src/x/instrument" 33 "github.com/m3db/m3/src/x/mmap" 34 "github.com/m3db/m3/src/x/pool" 35 "github.com/m3db/m3/src/x/serialize" 36 ) 37 38 const ( 39 // defaultIndexSummariesPercent is the default percent of series for which an entry will be written into the metadata summary 40 defaultIndexSummariesPercent = 0.03 41 42 // defaultIndexBloomFilterFalsePositivePercent is the false positive percent to use to calculate size for when writing bloom filters 43 defaultIndexBloomFilterFalsePositivePercent = 0.02 44 45 // defaultWriterBufferSize is the default buffer size for writing TSDB files 46 defaultWriterBufferSize = 65536 47 48 // defaultDataReaderBufferSize is the default buffer size for reading TSDB data and index files 49 defaultDataReaderBufferSize = 65536 50 51 // defaultInfoReaderBufferSize is the default buffer size for reading TSDB info, checkpoint and digest files 52 defaultInfoReaderBufferSize = 64 53 54 // defaultSeekReaderBufferSize is the default buffer size for fs seeker's data buffer 55 defaultSeekReaderBufferSize = 4096 56 57 // defaultMmapEnableHugePages is the default setting whether to enable huge pages or not 58 defaultMmapEnableHugePages = false 59 60 // defaultMmapHugePagesThreshold is the default threshold for when to enable huge pages if enabled 61 defaultMmapHugePagesThreshold = 2 << 14 // 32kb (or when eclipsing 8 pages of default 4096 page size) 62 63 // defaultForceIndexSummariesMmapMemory is the default configuration for whether the bytes for the index 64 // summaries file should be mmap'd as an anonymous region (forced completely into memory) or mmap'd as a file. 65 defaultForceIndexSummariesMmapMemory = false 66 67 // defaultForceIndexBloomFilterMmapMemory is the default configuration for whether the bytes for the bloom filter 68 // should be mmap'd as an anonymous region (forced completely into memory) or mmap'd as a file. 69 defaultForceIndexBloomFilterMmapMemory = false 70 71 // defaultIndexReaderAutovalidateIndexSegments is the default configuration for 72 // whether or not the index reader should autovalidate the index segments when 73 // opening segments. This is an expensive operation and should be done post-open. 74 defaultIndexReaderAutovalidateIndexSegments = false 75 ) 76 77 var ( 78 defaultFilePathPrefix = os.TempDir() 79 defaultNewFileMode = os.FileMode(0o666) 80 defaultNewDirectoryMode = os.ModeDir | os.FileMode(0o755) 81 defaultFSTWriterOptions = fst.WriterOptions{} 82 83 errTagEncoderPoolNotSet = errors.New("tag encoder pool is not set") 84 errTagDecoderPoolNotSet = errors.New("tag decoder pool is not set") 85 ) 86 87 type options struct { 88 clockOpts clock.Options 89 instrumentOpts instrument.Options 90 runtimeOptsMgr runtime.OptionsManager 91 decodingOpts msgpack.DecodingOptions 92 filePathPrefix string 93 newFileMode os.FileMode 94 newDirectoryMode os.FileMode 95 indexSummariesPercent float64 96 indexBloomFilterFalsePositivePercent float64 97 writerBufferSize int 98 dataReaderBufferSize int 99 infoReaderBufferSize int 100 seekReaderBufferSize int 101 mmapHugePagesThreshold int64 102 tagEncoderPool serialize.TagEncoderPool 103 tagDecoderPool serialize.TagDecoderPool 104 fstOptions fst.Options 105 fstWriterOptions fst.WriterOptions 106 forceIndexSummariesMmapMemory bool 107 forceBloomFilterMmapMemory bool 108 mmapEnableHugePages bool 109 mmapReporter mmap.Reporter 110 indexReaderAutovalidateIndexSegments bool 111 encodingOptions msgpack.LegacyEncodingOptions 112 } 113 114 type optionsInput struct { 115 tagEncoderPool serialize.TagEncoderPool 116 tagDecoderPool serialize.TagDecoderPool 117 fstOptions fst.Options 118 119 // the bools allow explicitly setting the field to nil 120 tagEncoderPoolSet bool 121 tagDecoderPoolSet bool 122 fstOptionsSet bool 123 } 124 125 // OptionSetter is a function that modifies the behavior of NewOptions 126 type OptionSetter func(o *optionsInput) 127 128 // WithTagEncoderPool is an OptionSetter that provides custom serialize.TagEncoderPool 129 // Passing nil will be equivalent to calling Options.SetTagEncoderPool(nil) 130 // on the result of NewOptions 131 func WithTagEncoderPool(o serialize.TagEncoderPool) OptionSetter { 132 return func(input *optionsInput) { 133 input.tagEncoderPool = o 134 input.tagEncoderPoolSet = true 135 } 136 } 137 138 // WithTagDecodePool is an OptionSetter that provides custom serialize.TagDecoder 139 // Passing nil will be equivalent to calling Options.SetTagDecoderPool(nil) 140 // on the result of NewOptions 141 func WithTagDecodePool(o serialize.TagDecoderPool) OptionSetter { 142 return func(input *optionsInput) { 143 input.tagDecoderPool = o 144 input.tagDecoderPoolSet = true 145 } 146 } 147 148 // WithFstOptions is an OptionSetter that provides custom fst.Options 149 // Passing nil will be equivalent to calling Options.SetFSTOptions(nil) 150 // on the result of NewOptions 151 func WithFstOptions(o fst.Options) OptionSetter { 152 return func(input *optionsInput) { 153 input.fstOptions = o 154 input.fstOptionsSet = true 155 } 156 } 157 158 // NewOptions creates a new set of fs options 159 func NewOptions(setters ...OptionSetter) Options { 160 input := optionsInput{} 161 for _, setter := range setters { 162 setter(&input) 163 } 164 if !input.tagEncoderPoolSet && input.tagEncoderPool == nil { 165 input.tagEncoderPool = serialize.NewTagEncoderPool( 166 serialize.NewTagEncoderOptions(), pool.NewObjectPoolOptions()) 167 } 168 169 if !input.tagDecoderPoolSet && input.tagDecoderPool == nil { 170 input.tagDecoderPool = serialize.NewTagDecoderPool( 171 serialize.NewTagDecoderOptions(serialize.TagDecoderOptionsConfig{}), 172 pool.NewObjectPoolOptions()) 173 } 174 175 if !input.fstOptionsSet && input.fstOptions == nil { 176 input.fstOptions = fst.NewOptions() 177 } 178 179 if input.tagEncoderPool != nil { 180 input.tagEncoderPool.Init() 181 } 182 if input.tagDecoderPool != nil { 183 input.tagDecoderPool.Init() 184 } 185 186 return &options{ 187 clockOpts: clock.NewOptions(), 188 instrumentOpts: instrument.NewOptions(), 189 runtimeOptsMgr: runtime.NewOptionsManager(), 190 decodingOpts: msgpack.NewDecodingOptions(), 191 filePathPrefix: defaultFilePathPrefix, 192 newFileMode: defaultNewFileMode, 193 newDirectoryMode: defaultNewDirectoryMode, 194 indexSummariesPercent: defaultIndexSummariesPercent, 195 indexBloomFilterFalsePositivePercent: defaultIndexBloomFilterFalsePositivePercent, 196 forceIndexSummariesMmapMemory: defaultForceIndexSummariesMmapMemory, 197 forceBloomFilterMmapMemory: defaultForceIndexBloomFilterMmapMemory, 198 writerBufferSize: defaultWriterBufferSize, 199 dataReaderBufferSize: defaultDataReaderBufferSize, 200 infoReaderBufferSize: defaultInfoReaderBufferSize, 201 seekReaderBufferSize: defaultSeekReaderBufferSize, 202 mmapEnableHugePages: defaultMmapEnableHugePages, 203 mmapHugePagesThreshold: defaultMmapHugePagesThreshold, 204 tagEncoderPool: input.tagEncoderPool, 205 tagDecoderPool: input.tagDecoderPool, 206 fstOptions: input.fstOptions, 207 fstWriterOptions: defaultFSTWriterOptions, 208 indexReaderAutovalidateIndexSegments: defaultIndexReaderAutovalidateIndexSegments, 209 encodingOptions: msgpack.DefaultLegacyEncodingOptions, 210 } 211 } 212 213 func (o *options) Validate() error { 214 if o.indexSummariesPercent < 0 || o.indexSummariesPercent > 1.0 { 215 return fmt.Errorf( 216 "invalid index summaries percent, must be >= 0 and <= 1: instead %f", 217 o.indexSummariesPercent) 218 } 219 if o.indexBloomFilterFalsePositivePercent < 0 || o.indexBloomFilterFalsePositivePercent > 1.0 { 220 return fmt.Errorf( 221 "invalid index bloom filter false positive percent, must be >= 0 and <= 1: instead %f", 222 o.indexBloomFilterFalsePositivePercent) 223 } 224 if o.tagEncoderPool == nil { 225 return errTagEncoderPoolNotSet 226 } 227 if o.tagDecoderPool == nil { 228 return errTagDecoderPoolNotSet 229 } 230 return nil 231 } 232 233 func (o *options) SetClockOptions(value clock.Options) Options { 234 opts := *o 235 opts.clockOpts = value 236 return &opts 237 } 238 239 func (o *options) ClockOptions() clock.Options { 240 return o.clockOpts 241 } 242 243 func (o *options) SetInstrumentOptions(value instrument.Options) Options { 244 opts := *o 245 opts.instrumentOpts = value 246 return &opts 247 } 248 249 func (o *options) InstrumentOptions() instrument.Options { 250 return o.instrumentOpts 251 } 252 253 func (o *options) SetRuntimeOptionsManager(value runtime.OptionsManager) Options { 254 opts := *o 255 opts.runtimeOptsMgr = value 256 return &opts 257 } 258 259 func (o *options) RuntimeOptionsManager() runtime.OptionsManager { 260 return o.runtimeOptsMgr 261 } 262 263 func (o *options) SetDecodingOptions(value msgpack.DecodingOptions) Options { 264 opts := *o 265 opts.decodingOpts = value 266 return &opts 267 } 268 269 func (o *options) DecodingOptions() msgpack.DecodingOptions { 270 return o.decodingOpts 271 } 272 273 func (o *options) SetFilePathPrefix(value string) Options { 274 opts := *o 275 opts.filePathPrefix = value 276 return &opts 277 } 278 279 func (o *options) FilePathPrefix() string { 280 return o.filePathPrefix 281 } 282 283 func (o *options) SetNewFileMode(value os.FileMode) Options { 284 opts := *o 285 opts.newFileMode = value 286 return &opts 287 } 288 289 func (o *options) NewFileMode() os.FileMode { 290 return o.newFileMode 291 } 292 293 func (o *options) SetNewDirectoryMode(value os.FileMode) Options { 294 opts := *o 295 opts.newDirectoryMode = value 296 return &opts 297 } 298 299 func (o *options) NewDirectoryMode() os.FileMode { 300 return o.newDirectoryMode 301 } 302 303 func (o *options) SetIndexSummariesPercent(value float64) Options { 304 opts := *o 305 opts.indexSummariesPercent = value 306 return &opts 307 } 308 309 func (o *options) IndexSummariesPercent() float64 { 310 return o.indexSummariesPercent 311 } 312 313 func (o *options) SetIndexBloomFilterFalsePositivePercent(value float64) Options { 314 opts := *o 315 opts.indexBloomFilterFalsePositivePercent = value 316 return &opts 317 } 318 319 func (o *options) IndexBloomFilterFalsePositivePercent() float64 { 320 return o.indexBloomFilterFalsePositivePercent 321 } 322 323 func (o *options) SetForceIndexSummariesMmapMemory(value bool) Options { 324 opts := *o 325 opts.forceIndexSummariesMmapMemory = value 326 return &opts 327 } 328 329 func (o *options) ForceIndexSummariesMmapMemory() bool { 330 return o.forceIndexSummariesMmapMemory 331 } 332 333 func (o *options) SetForceBloomFilterMmapMemory(value bool) Options { 334 opts := *o 335 opts.forceBloomFilterMmapMemory = value 336 return &opts 337 } 338 339 func (o *options) ForceBloomFilterMmapMemory() bool { 340 return o.forceBloomFilterMmapMemory 341 } 342 343 func (o *options) SetWriterBufferSize(value int) Options { 344 opts := *o 345 opts.writerBufferSize = value 346 return &opts 347 } 348 349 func (o *options) WriterBufferSize() int { 350 return o.writerBufferSize 351 } 352 353 func (o *options) SetDataReaderBufferSize(value int) Options { 354 opts := *o 355 opts.dataReaderBufferSize = value 356 return &opts 357 } 358 359 func (o *options) DataReaderBufferSize() int { 360 return o.dataReaderBufferSize 361 } 362 363 func (o *options) SetInfoReaderBufferSize(value int) Options { 364 opts := *o 365 opts.infoReaderBufferSize = value 366 return &opts 367 } 368 369 func (o *options) InfoReaderBufferSize() int { 370 return o.infoReaderBufferSize 371 } 372 373 func (o *options) SetSeekReaderBufferSize(value int) Options { 374 opts := *o 375 opts.seekReaderBufferSize = value 376 return &opts 377 } 378 379 func (o *options) SeekReaderBufferSize() int { 380 return o.seekReaderBufferSize 381 } 382 383 func (o *options) SetMmapEnableHugeTLB(value bool) Options { 384 opts := *o 385 opts.mmapEnableHugePages = value 386 return &opts 387 } 388 389 func (o *options) MmapEnableHugeTLB() bool { 390 return o.mmapEnableHugePages 391 } 392 393 func (o *options) SetMmapHugeTLBThreshold(value int64) Options { 394 opts := *o 395 opts.mmapHugePagesThreshold = value 396 return &opts 397 } 398 399 func (o *options) MmapHugeTLBThreshold() int64 { 400 return o.mmapHugePagesThreshold 401 } 402 403 func (o *options) SetTagEncoderPool(value serialize.TagEncoderPool) Options { 404 opts := *o 405 opts.tagEncoderPool = value 406 return &opts 407 } 408 409 func (o *options) TagEncoderPool() serialize.TagEncoderPool { 410 return o.tagEncoderPool 411 } 412 413 func (o *options) SetTagDecoderPool(value serialize.TagDecoderPool) Options { 414 opts := *o 415 opts.tagDecoderPool = value 416 return &opts 417 } 418 419 func (o *options) TagDecoderPool() serialize.TagDecoderPool { 420 return o.tagDecoderPool 421 } 422 423 func (o *options) SetFSTOptions(value fst.Options) Options { 424 opts := *o 425 opts.fstOptions = value 426 return &opts 427 } 428 429 func (o *options) FSTOptions() fst.Options { 430 return o.fstOptions 431 } 432 433 func (o *options) SetFSTWriterOptions(value fst.WriterOptions) Options { 434 opts := *o 435 opts.fstWriterOptions = value 436 return &opts 437 } 438 439 func (o *options) FSTWriterOptions() fst.WriterOptions { 440 return o.fstWriterOptions 441 } 442 443 func (o *options) SetMmapReporter(mmapReporter mmap.Reporter) Options { 444 opts := *o 445 opts.mmapReporter = mmapReporter 446 return &opts 447 } 448 449 func (o *options) MmapReporter() mmap.Reporter { 450 return o.mmapReporter 451 } 452 453 func (o *options) SetIndexReaderAutovalidateIndexSegments(value bool) Options { 454 opts := *o 455 opts.indexReaderAutovalidateIndexSegments = value 456 return &opts 457 } 458 459 func (o *options) IndexReaderAutovalidateIndexSegments() bool { 460 return o.indexReaderAutovalidateIndexSegments 461 } 462 463 func (o *options) SetEncodingOptions(value msgpack.LegacyEncodingOptions) Options { 464 opts := *o 465 opts.encodingOptions = value 466 return &opts 467 } 468 469 func (o *options) EncodingOptions() msgpack.LegacyEncodingOptions { 470 return o.encodingOptions 471 }