github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/m3ninx/persist/reader.go (about) 1 // Copyright (c) 2018 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 persist 22 23 import ( 24 "fmt" 25 "io" 26 27 "github.com/m3db/m3/src/m3ninx/index/segment/fst" 28 "github.com/m3db/m3/src/m3ninx/x" 29 ) 30 31 // NewSegment returns a new fst.Segment backed by the provided fileset. 32 // NB: this method takes ownership of the provided fileset files, in case of both errors, 33 // and success. i.e. users are not expected to call Close on any of the provided fileset.Files() 34 // after invoking this function. 35 func NewSegment(fileset IndexSegmentFileSet, opts fst.Options) (fst.Segment, error) { 36 success := false 37 safeCloser := newSafeIndexSegmentFileSetCloser(fileset) 38 defer func() { 39 if !success { 40 safeCloser.Close() 41 } 42 }() 43 44 if t := fileset.SegmentType(); t != FSTIndexSegmentType { 45 return nil, fmt.Errorf("unknown segment type: %s", t) 46 } 47 48 sd, err := filesetToSegmentData(fileset) 49 if err != nil { 50 return nil, err 51 } 52 sd.Closer = safeCloser 53 54 segment, err := fst.NewSegment(sd, opts) 55 if err != nil { 56 return nil, err 57 } 58 59 // indicate we don't need to close files in the defer above. 60 success = true 61 62 // segment assumes ownership of the safeCloser at this point. 63 return segment, nil 64 } 65 66 func filesetToSegmentData(fileset IndexSegmentFileSet) (fst.SegmentData, error) { 67 var ( 68 sd = fst.SegmentData{ 69 Version: fst.Version{ 70 Major: fileset.MajorVersion(), 71 Minor: fileset.MinorVersion(), 72 }, 73 Metadata: fileset.SegmentMetadata(), 74 } 75 err error 76 ) 77 78 for _, f := range fileset.Files() { 79 fileType := f.SegmentFileType() 80 switch fileType { 81 case DocumentDataIndexSegmentFileType: 82 sd.DocsData, err = f.Mmap() 83 if err != nil { 84 return sd, err 85 } 86 case DocumentIndexIndexSegmentFileType: 87 sd.DocsIdxData, err = f.Mmap() 88 if err != nil { 89 return sd, err 90 } 91 case PostingsIndexSegmentFileType: 92 sd.PostingsData, err = f.Mmap() 93 if err != nil { 94 return sd, err 95 } 96 case FSTFieldsIndexSegmentFileType: 97 sd.FSTFieldsData, err = f.Mmap() 98 if err != nil { 99 return sd, err 100 } 101 case FSTTermsIndexSegmentFileType: 102 sd.FSTTermsData, err = f.Mmap() 103 if err != nil { 104 return sd, err 105 } 106 default: 107 return sd, fmt.Errorf("unknown fileType: %s provided", fileType) 108 } 109 } 110 111 return sd, nil 112 } 113 114 func newSafeIndexSegmentFileSetCloser(fileset IndexSegmentFileSet) io.Closer { 115 closers := make([]io.Closer, 0, len(fileset.Files())) 116 for _, f := range fileset.Files() { 117 closers = append(closers, f) 118 } 119 return x.NewSafeMultiCloser(closers...) 120 }