github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/storage/util.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 storage 22 23 import ( 24 "sync" 25 "time" 26 27 "github.com/m3db/m3/src/dbnode/persist/fs" 28 "github.com/m3db/m3/src/dbnode/runtime" 29 "github.com/m3db/m3/src/dbnode/storage/block" 30 "github.com/m3db/m3/src/dbnode/storage/index" 31 "github.com/m3db/m3/src/dbnode/storage/series" 32 "github.com/m3db/m3/src/x/pool" 33 xtime "github.com/m3db/m3/src/x/time" 34 ) 35 36 var ( 37 defaultTestOptionsOnce sync.Once 38 defaultTestOptions Options 39 ) 40 41 // DefaultTestOptions provides a single set of test storage options 42 // we save considerable memory by doing this avoiding creating 43 // default pools several times. 44 func DefaultTestOptions() Options { 45 defaultTestOptionsOnce.Do(func() { 46 opts := newOptions(pool.NewObjectPoolOptions(). 47 SetSize(16)) 48 49 // Use a no-op options manager to avoid spinning up a goroutine to listen 50 // for updates, which causes problems with leaktest in individual test 51 // executions 52 runtimeOptionsMgr := runtime.NewNoOpOptionsManager( 53 runtime.NewOptions()) 54 55 blockLeaseManager := &block.NoopLeaseManager{} 56 fsOpts := fs.NewOptions(). 57 SetRuntimeOptionsManager(runtimeOptionsMgr) 58 pm, err := fs.NewPersistManager(fsOpts) 59 if err != nil { 60 panic(err) 61 } 62 63 plCache, err := index.NewPostingsListCache(10, index.PostingsListCacheOptions{ 64 InstrumentOptions: opts.InstrumentOptions(), 65 }) 66 if err != nil { 67 panic(err) 68 } 69 plStop := plCache.Start() 70 defer plStop() 71 72 indexOpts := opts.IndexOptions(). 73 SetPostingsListCache(plCache) 74 75 defaultTestOptions = opts. 76 SetIndexOptions(indexOpts). 77 SetSeriesCachePolicy(series.CacheAll). 78 SetPersistManager(pm). 79 SetRepairEnabled(false). 80 SetCommitLogOptions( 81 opts.CommitLogOptions().SetFilesystemOptions(fsOpts)). 82 SetBlockLeaseManager(blockLeaseManager) 83 }) 84 85 // Needs a unique index claims manager each time as it tracks volume indices via in mem claims that 86 // should be different per test. 87 fs.ResetIndexClaimsManagersUnsafe() 88 fsOpts := defaultTestOptions.CommitLogOptions().FilesystemOptions() 89 icm, err := fs.NewIndexClaimsManager(fsOpts) 90 if err != nil { 91 panic(err) 92 } 93 94 return defaultTestOptions.SetIndexClaimsManager(icm) 95 } 96 97 // numIntervals returns the number of intervals between [start, end] for a given 98 // windowSize. 99 // NB: edge conditions: 100 // - returns 0 if window <= 0 ; 101 // - returns 0 if end is before start; 102 // - returns 1 if end == start 103 func numIntervals(startInclusive, endInclusive xtime.UnixNano, window time.Duration) int { 104 if window <= 0 || endInclusive.Before(startInclusive) { 105 return 0 106 } 107 108 return 1 + int((endInclusive.Sub(startInclusive))/window) 109 } 110 111 // timesInRange returns the points between [start, end] windowSize apart, starting at `end`, in 112 // reverse chronological order. 113 // NB: returns empty slice if window <= 0 or end is before start 114 func timesInRange(startInclusive, endInclusive xtime.UnixNano, windowSize time.Duration) []xtime.UnixNano { 115 ni := numIntervals(startInclusive, endInclusive, windowSize) 116 if ni == 0 { 117 return nil 118 } 119 times := make([]xtime.UnixNano, 0, ni) 120 for t := endInclusive; !t.Before(startInclusive); t = t.Add(-windowSize) { 121 times = append(times, t) 122 } 123 return times 124 } 125 126 // filterTimes returns the values in the slice `times` which satisfy 127 // the provided predicate. 128 func filterTimes(times []xtime.UnixNano, predicate func(t xtime.UnixNano) bool) []xtime.UnixNano { 129 filtered := make([]xtime.UnixNano, 0, len(times)) 130 for _, t := range times { 131 if predicate(t) { 132 filtered = append(filtered, t) 133 } 134 } 135 136 return filtered 137 }