github.com/m3db/m3@v1.5.0/src/dbnode/storage/block/retriever_manager.go (about) 1 // Copyright (c) 2016 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 block 22 23 import ( 24 "sync" 25 26 "github.com/m3db/m3/src/dbnode/namespace" 27 "github.com/m3db/m3/src/dbnode/sharding" 28 "github.com/m3db/m3/src/dbnode/x/xio" 29 "github.com/m3db/m3/src/x/context" 30 "github.com/m3db/m3/src/x/ident" 31 xtime "github.com/m3db/m3/src/x/time" 32 ) 33 34 // NewDatabaseBlockRetrieverFn is a method for constructing 35 // new database block retrievers 36 type NewDatabaseBlockRetrieverFn func( 37 md namespace.Metadata, 38 shardSet sharding.ShardSet, 39 ) (DatabaseBlockRetriever, error) 40 41 // NewDatabaseBlockRetrieverManager creates a new manager 42 // for constructing and providing existing database block retrievers 43 func NewDatabaseBlockRetrieverManager( 44 newDatabaseBlockRetrieverFn NewDatabaseBlockRetrieverFn, 45 ) DatabaseBlockRetrieverManager { 46 return &blockRetrieverManager{ 47 newRetrieverFn: newDatabaseBlockRetrieverFn, 48 retrievers: newRetrieverMap(retrieverMapOptions{}), 49 } 50 } 51 52 type blockRetrieverManager struct { 53 sync.RWMutex 54 newRetrieverFn NewDatabaseBlockRetrieverFn 55 retrievers *retrieverMap 56 } 57 58 func (m *blockRetrieverManager) Retriever( 59 md namespace.Metadata, 60 shardSet sharding.ShardSet, 61 ) (DatabaseBlockRetriever, error) { 62 m.RLock() 63 retriever, ok := m.retrievers.Get(md.ID()) 64 m.RUnlock() 65 if ok { 66 return retriever, nil 67 } 68 69 m.Lock() 70 defer m.Unlock() 71 72 retriever, ok = m.retrievers.Get(md.ID()) 73 if ok { 74 return retriever, nil 75 } 76 77 var err error 78 retriever, err = m.newRetrieverFn(md, shardSet) 79 if err != nil { 80 return nil, err 81 } 82 83 m.retrievers.Set(md.ID(), retriever) 84 return retriever, nil 85 } 86 87 type shardBlockRetriever struct { 88 DatabaseBlockRetriever 89 shard uint32 90 } 91 92 // NewDatabaseShardBlockRetriever creates a new shard database 93 // block retriever given an existing database block retriever 94 func NewDatabaseShardBlockRetriever( 95 shard uint32, 96 r DatabaseBlockRetriever, 97 ) DatabaseShardBlockRetriever { 98 return &shardBlockRetriever{ 99 DatabaseBlockRetriever: r, 100 shard: shard, 101 } 102 } 103 104 func (r *shardBlockRetriever) Stream( 105 ctx context.Context, 106 id ident.ID, 107 blockStart xtime.UnixNano, 108 onRetrieve OnRetrieveBlock, 109 nsCtx namespace.Context, 110 ) (xio.BlockReader, error) { 111 return r.DatabaseBlockRetriever.Stream(ctx, r.shard, id, 112 blockStart, onRetrieve, nsCtx) 113 } 114 115 type shardBlockRetrieverManager struct { 116 sync.RWMutex 117 retriever DatabaseBlockRetriever 118 shardRetrievers map[uint32]DatabaseShardBlockRetriever 119 } 120 121 // NewDatabaseShardBlockRetrieverManager creates and holds shard block 122 // retrievers binding shards to an existing retriever. 123 func NewDatabaseShardBlockRetrieverManager( 124 r DatabaseBlockRetriever, 125 ) DatabaseShardBlockRetrieverManager { 126 return &shardBlockRetrieverManager{ 127 retriever: r, 128 shardRetrievers: make(map[uint32]DatabaseShardBlockRetriever), 129 } 130 } 131 132 func (m *shardBlockRetrieverManager) ShardRetriever( 133 shard uint32, 134 ) DatabaseShardBlockRetriever { 135 m.RLock() 136 retriever, ok := m.shardRetrievers[shard] 137 m.RUnlock() 138 139 if ok { 140 return retriever 141 } 142 143 m.Lock() 144 defer m.Unlock() 145 146 retriever, ok = m.shardRetrievers[shard] 147 if ok { 148 return retriever 149 } 150 151 retriever = NewDatabaseShardBlockRetriever(shard, m.retriever) 152 m.shardRetrievers[shard] = retriever 153 return retriever 154 }