@@ -176,9 +176,8 @@ type FileStore struct {
176176 currentGeneration int
177177 dir string
178178
179- files []TSMFile
180- tsmMMAPWillNeed bool // If true then the kernel will be advised MMAP_WILLNEED for TSM files.
181- openLimiter limiter.Fixed // limit the number of concurrent opening TSM files.
179+ files []TSMFile
180+ openLimiter limiter.Fixed // limit the number of concurrent opening TSM files.
182181
183182 logger * zap.Logger // Logger to be used for important messages
184183 traceLogger * zap.Logger // Logger to be used when trace-logging is on.
@@ -198,6 +197,8 @@ type FileStore struct {
198197 // newReaderBlockCount keeps track of the current new reader block requests.
199198 // If non-zero, no new TSMReader objects may be created.
200199 newReaderBlockCount int
200+
201+ readerOptions []tsmReaderOption
201202}
202203
203204// FileStat holds information about a TSM file on disk.
@@ -234,7 +235,7 @@ func (f FileStat) ContainsKey(key []byte) bool {
234235}
235236
236237// NewFileStore returns a new instance of FileStore based on the given directory.
237- func NewFileStore (dir string , tags tsdb.EngineTags ) * FileStore {
238+ func NewFileStore (dir string , tags tsdb.EngineTags , options ... tsmReaderOption ) * FileStore {
238239 logger := zap .NewNop ()
239240 fs := & FileStore {
240241 dir : dir ,
@@ -250,6 +251,7 @@ func NewFileStore(dir string, tags tsdb.EngineTags) *FileStore {
250251 obs : noFileStoreObserver {},
251252 parseFileName : DefaultParseFileName ,
252253 copyFiles : runtime .GOOS == "windows" ,
254+ readerOptions : options ,
253255 }
254256 fs .purger .fileStore = fs
255257 return fs
@@ -616,28 +618,37 @@ func (f *FileStore) Open(ctx context.Context) error {
616618 defer f .openLimiter .Release ()
617619
618620 start := time .Now ()
619- df , err := NewTSMReader (file , WithMadviseWillNeed ( f . tsmMMAPWillNeed ) )
621+ df , err := NewTSMReader (file , f . readerOptions ... )
620622 f .logger .Info ("Opened file" ,
621623 zap .String ("path" , file .Name ()),
622624 zap .Int ("id" , idx ),
623625 zap .Duration ("duration" , time .Since (start )))
624626
625- // If we are unable to read a TSM file then log the error, rename
626- // the file, and continue loading the shard without it.
627+ // If we are unable to read a TSM file then log the error.
627628 if err != nil {
628629 if cerr := file .Close (); cerr != nil {
629630 f .logger .Error ("Error closing TSM file after error" , zap .String ("path" , file .Name ()), zap .Int ("id" , idx ), zap .Error (cerr ))
630631 }
631- // If the file is corrupt, rename it and
632- // continue loading the shard without it.
633- f .logger .Error ("Cannot read corrupt tsm file, renaming" , zap .String ("path" , file .Name ()), zap .Int ("id" , idx ), zap .Error (err ))
634- if e := os .Rename (file .Name (), file .Name ()+ "." + BadTSMFileExtension ); e != nil {
635- f .logger .Error ("Cannot rename corrupt tsm file" , zap .String ("path" , file .Name ()), zap .Int ("id" , idx ), zap .Error (e ))
636- readerC <- & res {r : df , err : fmt .Errorf ("cannot rename corrupt file %s: %w" , file .Name (), e )}
632+ if errors .Is (err , MmapError {}) {
633+ // An MmapError may indicate we have insufficient
634+ // handles for the mmap call, in which case the file should
635+ // be left untouched, and the vm.max_map_count be raised.
636+ f .logger .Error ("Cannot read TSM file, system limit for vm.max_map_count may be too low" ,
637+ zap .String ("path" , file .Name ()), zap .Int ("id" , idx ), zap .Error (err ))
638+ readerC <- & res {r : df , err : fmt .Errorf ("cannot read file %s, system limit for vm.max_map_count may be too low: %v" , file .Name (), err )}
639+ return
640+ } else {
641+ // If the file is corrupt, rename it and
642+ // continue loading the shard without it.
643+ f .logger .Error ("Cannot read corrupt tsm file, renaming" , zap .String ("path" , file .Name ()), zap .Int ("id" , idx ), zap .Error (err ))
644+ if e := os .Rename (file .Name (), file .Name ()+ "." + BadTSMFileExtension ); e != nil {
645+ f .logger .Error ("Cannot rename corrupt tsm file" , zap .String ("path" , file .Name ()), zap .Int ("id" , idx ), zap .Error (e ))
646+ readerC <- & res {r : df , err : fmt .Errorf ("cannot rename corrupt file %s: %v" , file .Name (), e )}
647+ return
648+ }
649+ readerC <- & res {r : df , err : fmt .Errorf ("cannot read corrupt file %s: %v" , file .Name (), err )}
637650 return
638651 }
639- readerC <- & res {r : df , err : fmt .Errorf ("cannot read corrupt file %s: %w" , file .Name (), err )}
640- return
641652 }
642653 df .WithObserver (f .obs )
643654 readerC <- & res {r : df }
@@ -920,7 +931,7 @@ func (f *FileStore) replace(oldFiles, newFiles []string, updatedFn func(r []TSMF
920931 }
921932 }
922933
923- tsm , err := NewTSMReader (fd , WithMadviseWillNeed ( f . tsmMMAPWillNeed ) )
934+ tsm , err := NewTSMReader (fd , f . readerOptions ... )
924935 if err != nil {
925936 if newName != oldName {
926937 if err1 := os .Rename (newName , oldName ); err1 != nil {
0 commit comments