github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/cmd/services/m3dbnode/config/fs.go (about)

     1  // Copyright (c) 2017 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 config
    22  
    23  import (
    24  	"fmt"
    25  	"os"
    26  )
    27  
    28  const (
    29  	// DefaultNewFileMode is the default new file mode.
    30  	DefaultNewFileMode = os.FileMode(0666)
    31  	// DefaultNewDirectoryMode is the default new directory mode.
    32  	DefaultNewDirectoryMode = os.FileMode(0755)
    33  
    34  	defaultFilePathPrefix                  = "/var/lib/m3db"
    35  	defaultWriteBufferSize                 = 65536
    36  	defaultDataReadBufferSize              = 65536
    37  	defaultInfoReadBufferSize              = 128
    38  	defaultSeekReadBufferSize              = 4096
    39  	defaultThroughputLimitMbps             = 1000.0
    40  	defaultThroughputCheckEvery            = 128
    41  	defaultForceIndexSummariesMmapMemory   = false
    42  	defaultForceBloomFilterMmapMemory      = false
    43  	defaultBloomFilterFalsePositivePercent = 0.02
    44  )
    45  
    46  // DefaultMmapConfiguration is the default mmap configuration.
    47  func DefaultMmapConfiguration() MmapConfiguration {
    48  	return MmapConfiguration{
    49  		HugeTLB: MmapHugeTLBConfiguration{
    50  			Enabled:   true,    // Enable when on a platform that supports
    51  			Threshold: 2 << 14, // 32kb and above mappings use huge pages
    52  		},
    53  	}
    54  }
    55  
    56  // FilesystemConfiguration is the filesystem configuration.
    57  type FilesystemConfiguration struct {
    58  	// File path prefix for reading/writing TSDB files
    59  	FilePathPrefix *string `yaml:"filePathPrefix"`
    60  
    61  	// Write buffer size
    62  	WriteBufferSize *int `yaml:"writeBufferSize"`
    63  
    64  	// Data read buffer size
    65  	DataReadBufferSize *int `yaml:"dataReadBufferSize"`
    66  
    67  	// Info metadata file read buffer size
    68  	InfoReadBufferSize *int `yaml:"infoReadBufferSize"`
    69  
    70  	// Seek data read buffer size
    71  	SeekReadBufferSize *int `yaml:"seekReadBufferSize"`
    72  
    73  	// Disk flush throughput limit in Mb/s
    74  	ThroughputLimitMbps *float64 `yaml:"throughputLimitMbps"`
    75  
    76  	// Disk flush throughput check interval
    77  	ThroughputCheckEvery *int `yaml:"throughputCheckEvery"`
    78  
    79  	// NewFileMode is the new file permissions mode to use when
    80  	// creating files - specify as three digits, e.g. 666.
    81  	NewFileMode *string `yaml:"newFileMode"`
    82  
    83  	// NewDirectoryMode is the new file permissions mode to use when
    84  	// creating directories - specify as three digits, e.g. 755.
    85  	NewDirectoryMode *string `yaml:"newDirectoryMode"`
    86  
    87  	// Mmap is the mmap options which features are primarily platform dependent
    88  	Mmap *MmapConfiguration `yaml:"mmap"`
    89  
    90  	// ForceIndexSummariesMmapMemory forces the mmap that stores the index lookup bytes
    91  	// to be an anonymous region in memory as opposed to a file-based mmap.
    92  	ForceIndexSummariesMmapMemory *bool `yaml:"force_index_summaries_mmap_memory"`
    93  
    94  	// ForceBloomFilterMmapMemory forces the mmap that stores the index lookup bytes
    95  	// to be an anonymous region in memory as opposed to a file-based mmap.
    96  	ForceBloomFilterMmapMemory *bool `yaml:"force_bloom_filter_mmap_memory"`
    97  
    98  	// BloomFilterFalsePositivePercent controls the target false positive percentage
    99  	// for the bloom filters for the fileset files.
   100  	BloomFilterFalsePositivePercent *float64 `yaml:"bloomFilterFalsePositivePercent"`
   101  }
   102  
   103  // Validate validates the Filesystem configuration. We use this method to validate
   104  // fields where the validator package falls short.
   105  func (f FilesystemConfiguration) Validate() error {
   106  	if f.WriteBufferSize != nil && *f.WriteBufferSize < 1 {
   107  		return fmt.Errorf(
   108  			"fs writeBufferSize is set to: %d, but must be at least 1",
   109  			*f.WriteBufferSize)
   110  	}
   111  
   112  	if f.DataReadBufferSize != nil && *f.DataReadBufferSize < 1 {
   113  		return fmt.Errorf(
   114  			"fs dataReadBufferSize is set to: %d, but must be at least 1",
   115  			*f.DataReadBufferSize)
   116  	}
   117  
   118  	if f.InfoReadBufferSize != nil && *f.InfoReadBufferSize < 1 {
   119  		return fmt.Errorf(
   120  			"fs infoReadBufferSize is set to: %d, but must be at least 1",
   121  			*f.InfoReadBufferSize)
   122  	}
   123  
   124  	if f.SeekReadBufferSize != nil && *f.SeekReadBufferSize < 1 {
   125  		return fmt.Errorf(
   126  			"fs seekReadBufferSize is set to: %d, but must be at least 1",
   127  			*f.SeekReadBufferSize)
   128  	}
   129  
   130  	if f.ThroughputLimitMbps != nil && *f.ThroughputLimitMbps < 1 {
   131  		return fmt.Errorf(
   132  			"fs throughputLimitMbps is set to: %f, but must be at least 1",
   133  			*f.ThroughputLimitMbps)
   134  	}
   135  
   136  	if f.ThroughputCheckEvery != nil && *f.ThroughputCheckEvery < 1 {
   137  		return fmt.Errorf(
   138  			"fs throughputCheckEvery is set to: %d, but must be at least 1",
   139  			*f.ThroughputCheckEvery)
   140  	}
   141  	if f.BloomFilterFalsePositivePercent != nil &&
   142  		(*f.BloomFilterFalsePositivePercent < 0 || *f.BloomFilterFalsePositivePercent > 1) {
   143  		return fmt.Errorf(
   144  			"fs bloomFilterFalsePositivePercent is set to: %f, but must be between 0.0 and 1.0",
   145  			*f.BloomFilterFalsePositivePercent)
   146  	}
   147  
   148  	return nil
   149  }
   150  
   151  // FilePathPrefixOrDefault returns the configured file path prefix if configured, or a
   152  // default value otherwise.
   153  func (f FilesystemConfiguration) FilePathPrefixOrDefault() string {
   154  	if f.FilePathPrefix != nil {
   155  		return *f.FilePathPrefix
   156  	}
   157  
   158  	return defaultFilePathPrefix
   159  }
   160  
   161  // WriteBufferSizeOrDefault returns the configured write buffer size if configured, or a
   162  // default value otherwise.
   163  func (f FilesystemConfiguration) WriteBufferSizeOrDefault() int {
   164  	if f.WriteBufferSize != nil {
   165  		return *f.WriteBufferSize
   166  	}
   167  
   168  	return defaultWriteBufferSize
   169  }
   170  
   171  // DataReadBufferSizeOrDefault returns the configured data read buffer size if configured, or a
   172  // default value otherwise.
   173  func (f FilesystemConfiguration) DataReadBufferSizeOrDefault() int {
   174  	if f.DataReadBufferSize != nil {
   175  		return *f.DataReadBufferSize
   176  	}
   177  
   178  	return defaultDataReadBufferSize
   179  }
   180  
   181  // InfoReadBufferSizeOrDefault returns the configured info read buffer size if configured, or a
   182  // default value otherwise.
   183  func (f FilesystemConfiguration) InfoReadBufferSizeOrDefault() int {
   184  	if f.InfoReadBufferSize != nil {
   185  		return *f.InfoReadBufferSize
   186  	}
   187  
   188  	return defaultInfoReadBufferSize
   189  }
   190  
   191  // SeekReadBufferSizeOrDefault returns the configured seek read buffer size if configured, or a
   192  // default value otherwise.
   193  func (f FilesystemConfiguration) SeekReadBufferSizeOrDefault() int {
   194  	if f.SeekReadBufferSize != nil {
   195  		return *f.SeekReadBufferSize
   196  	}
   197  
   198  	return defaultSeekReadBufferSize
   199  }
   200  
   201  // ThroughputLimitMbpsOrDefault returns the configured throughput limit mbps if configured, or a
   202  // default value otherwise.
   203  func (f FilesystemConfiguration) ThroughputLimitMbpsOrDefault() float64 {
   204  	if f.ThroughputLimitMbps != nil {
   205  		return *f.ThroughputLimitMbps
   206  	}
   207  
   208  	return defaultThroughputLimitMbps
   209  }
   210  
   211  // ThroughputCheckEveryOrDefault returns the configured throughput check every value if configured, or a
   212  // default value otherwise.
   213  func (f FilesystemConfiguration) ThroughputCheckEveryOrDefault() int {
   214  	if f.ThroughputCheckEvery != nil {
   215  		return *f.ThroughputCheckEvery
   216  	}
   217  
   218  	return defaultThroughputCheckEvery
   219  }
   220  
   221  // MmapConfigurationOrDefault returns the configured mmap configuration if configured, or a
   222  // default value otherwise.
   223  func (f FilesystemConfiguration) MmapConfigurationOrDefault() MmapConfiguration {
   224  	if f.Mmap == nil {
   225  		return DefaultMmapConfiguration()
   226  	}
   227  	return *f.Mmap
   228  }
   229  
   230  // ForceIndexSummariesMmapMemoryOrDefault returns the configured value for forcing the summaries
   231  // mmaps into anonymous region in memory if configured, or a default value otherwise.
   232  func (f FilesystemConfiguration) ForceIndexSummariesMmapMemoryOrDefault() bool {
   233  	if f.ForceIndexSummariesMmapMemory != nil {
   234  		return *f.ForceIndexSummariesMmapMemory
   235  	}
   236  
   237  	return defaultForceIndexSummariesMmapMemory
   238  }
   239  
   240  // ForceBloomFilterMmapMemoryOrDefault returns the configured value for forcing the bloom
   241  // filter mmaps into anonymous region in memory if configured, or a default value otherwise.
   242  func (f FilesystemConfiguration) ForceBloomFilterMmapMemoryOrDefault() bool {
   243  	if f.ForceBloomFilterMmapMemory != nil {
   244  		return *f.ForceBloomFilterMmapMemory
   245  	}
   246  
   247  	return defaultForceBloomFilterMmapMemory
   248  }
   249  
   250  // BloomFilterFalsePositivePercentOrDefault returns the configured value for the target
   251  // false positive percent for the bloom filter for the fileset files if configured, or a default
   252  // value otherwise
   253  func (f FilesystemConfiguration) BloomFilterFalsePositivePercentOrDefault() float64 {
   254  	if f.BloomFilterFalsePositivePercent != nil {
   255  		return *f.BloomFilterFalsePositivePercent
   256  	}
   257  	return defaultBloomFilterFalsePositivePercent
   258  }
   259  
   260  // MmapConfiguration is the mmap configuration.
   261  type MmapConfiguration struct {
   262  	// HugeTLB is the huge pages configuration which will only take affect
   263  	// on platforms that support it, currently just linux
   264  	HugeTLB MmapHugeTLBConfiguration `yaml:"hugeTLB"`
   265  }
   266  
   267  // MmapHugeTLBConfiguration is the mmap huge TLB configuration.
   268  type MmapHugeTLBConfiguration struct {
   269  	// Enabled if true or disabled if false
   270  	Enabled bool `yaml:"enabled"`
   271  
   272  	// Threshold is the threshold on which to use the huge TLB flag if enabled
   273  	Threshold int64 `yaml:"threshold"`
   274  }
   275  
   276  // ParseNewFileMode parses the specified new file mode.
   277  func (f FilesystemConfiguration) ParseNewFileMode() (os.FileMode, error) {
   278  	if f.NewFileMode == nil {
   279  		return DefaultNewFileMode, nil
   280  	}
   281  
   282  	str := *f.NewFileMode
   283  	if len(str) != 3 {
   284  		return 0, fmt.Errorf("file mode must be 3 chars long")
   285  	}
   286  
   287  	str = "0" + str
   288  
   289  	var v uint32
   290  	n, err := fmt.Sscanf(str, "%o", &v)
   291  	if err != nil {
   292  		return 0, fmt.Errorf("unable to parse: %v", err)
   293  	}
   294  	if n != 1 {
   295  		return 0, fmt.Errorf("no value to parse")
   296  	}
   297  	return os.FileMode(v), nil
   298  }
   299  
   300  // ParseNewDirectoryMode parses the specified new directory mode.
   301  func (f FilesystemConfiguration) ParseNewDirectoryMode() (os.FileMode, error) {
   302  	if f.NewDirectoryMode == nil {
   303  		return DefaultNewDirectoryMode, nil
   304  	}
   305  
   306  	str := *f.NewDirectoryMode
   307  	if len(str) != 3 {
   308  		return 0, fmt.Errorf("file mode must be 3 chars long")
   309  	}
   310  
   311  	str = "0" + str
   312  
   313  	var v uint32
   314  	n, err := fmt.Sscanf(str, "%o", &v)
   315  	if err != nil {
   316  		return 0, fmt.Errorf("unable to parse: %v", err)
   317  	}
   318  	if n != 1 {
   319  		return 0, fmt.Errorf("no value to parse")
   320  	}
   321  	return os.ModeDir | os.FileMode(v), nil
   322  }