github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/storage/series_resolver.go (about) 1 // Copyright (c) 2021 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 "fmt" 25 "sync" 26 27 "github.com/m3db/m3/src/dbnode/storage/bootstrap" 28 "github.com/m3db/m3/src/x/ident" 29 ) 30 31 // retrieveWritableSeriesAndIncrementReaderWriterCountFn represents the function to retrieve series entry. 32 type retrieveWritableSeriesAndIncrementReaderWriterCountFn func(id ident.ID) (*Entry, error) 33 34 type seriesResolver struct { 35 sync.RWMutex 36 37 wg *sync.WaitGroup 38 createdEntry *Entry 39 retrieveWritableSeriesAndIncrementReaderWriterCountFn retrieveWritableSeriesAndIncrementReaderWriterCountFn 40 41 resolved bool 42 resolvedErr error 43 entry *Entry 44 } 45 46 // NewSeriesResolver creates new series ref resolver. 47 func NewSeriesResolver( 48 wg *sync.WaitGroup, 49 createdEntry *Entry, 50 retrieveWritableSeriesAndIncrementReaderWriterCountFn retrieveWritableSeriesAndIncrementReaderWriterCountFn, 51 ) bootstrap.SeriesRefResolver { 52 return &seriesResolver{ 53 wg: wg, 54 createdEntry: createdEntry, 55 retrieveWritableSeriesAndIncrementReaderWriterCountFn: retrieveWritableSeriesAndIncrementReaderWriterCountFn, 56 } 57 } 58 59 func (r *seriesResolver) resolve() error { 60 r.RLock() 61 if r.resolved { 62 resolvedResult := r.resolvedErr 63 r.RUnlock() 64 return resolvedResult 65 } 66 r.RUnlock() 67 68 r.Lock() 69 defer r.Unlock() 70 71 // Fast path: if we already resolved the result, just return it. 72 if r.resolved { 73 return r.resolvedErr 74 } 75 76 // Wait for the insertion. 77 r.wg.Wait() 78 79 // Retrieve the inserted entry. 80 entry, err := r.retrieveWritableSeriesAndIncrementReaderWriterCountFn(r.createdEntry.ID) 81 r.resolved = true 82 if err != nil { 83 r.resolvedErr = err 84 return r.resolvedErr 85 } 86 87 if entry == nil { 88 r.resolvedErr = fmt.Errorf("could not resolve: %s", r.createdEntry.ID) 89 return r.resolvedErr 90 } 91 92 r.entry = entry 93 return nil 94 } 95 96 func (r *seriesResolver) SeriesRef() (bootstrap.SeriesRef, error) { 97 if err := r.resolve(); err != nil { 98 return nil, err 99 } 100 return r.entry, nil 101 } 102 103 func (r *seriesResolver) ReleaseRef() { 104 if r.createdEntry != nil { 105 // We explicitly dec the originally created entry for the resolver since 106 // that it is the one that was incremented before we took ownership of it, 107 // this was done to make sure it was valid during insertion until we 108 // operated on it. 109 // If we got it back from the shard map and incremented the reader writer 110 // count as well during that retrieval, then we'll again decrement it below. 111 r.createdEntry.ReleaseRef() 112 r.createdEntry = nil 113 } 114 if r.entry != nil { 115 // To account for decrementing the increment that occurred when checking 116 // out the series from the shard itself (which was incremented 117 // the reader writer counter when we checked it out using by calling 118 // "retrieveWritableSeriesAndIncrementReaderWriterCount"). 119 r.entry.DecrementReaderWriterCount() 120 r.entry = nil 121 } 122 }