github.com/m3db/m3@v1.5.0/src/query/remote/codecs_search.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 remote 22 23 import ( 24 "github.com/m3db/m3/src/dbnode/encoding" 25 "github.com/m3db/m3/src/query/block" 26 "github.com/m3db/m3/src/query/errors" 27 rpc "github.com/m3db/m3/src/query/generated/proto/rpcpb" 28 "github.com/m3db/m3/src/query/models" 29 "github.com/m3db/m3/src/query/storage" 30 "github.com/m3db/m3/src/query/storage/m3/consolidators" 31 "github.com/m3db/m3/src/x/serialize" 32 ) 33 34 func multiTagResultsToM3TagProperties( 35 results []consolidators.MultiTagResult, 36 encoderPool serialize.TagEncoderPool, 37 ) (*rpc.M3TagProperties, error) { 38 props := make([]rpc.M3TagProperty, len(results)) 39 for i, result := range results { 40 tags, err := compressedTagsFromTagIterator(result.Iter, encoderPool) 41 if err != nil { 42 return nil, err 43 } 44 45 props[i] = rpc.M3TagProperty{ 46 Id: result.ID.Bytes(), 47 CompressedTags: tags, 48 } 49 } 50 51 pprops := make([]*rpc.M3TagProperty, len(props)) 52 for i := range props { 53 pprops[i] = &props[i] 54 } 55 56 return &rpc.M3TagProperties{ 57 Properties: pprops, 58 }, nil 59 } 60 61 // encodeToCompressedSearchResult encodes SearchResults to a compressed 62 // search result. 63 func encodeToCompressedSearchResult( 64 results []consolidators.MultiTagResult, 65 metadata block.ResultMetadata, 66 pools encoding.IteratorPools, 67 ) (*rpc.SearchResponse, error) { 68 if pools == nil { 69 return nil, errors.ErrCannotEncodeCompressedTags 70 } 71 72 encoderPool := pools.TagEncoder() 73 if encoderPool == nil { 74 return nil, errors.ErrCannotEncodeCompressedTags 75 } 76 77 compressedTags, err := multiTagResultsToM3TagProperties(results, encoderPool) 78 if err != nil { 79 return nil, err 80 } 81 82 return &rpc.SearchResponse{ 83 Value: &rpc.SearchResponse_Compressed{ 84 Compressed: compressedTags, 85 }, 86 87 Meta: encodeResultMetadata(metadata), 88 }, nil 89 } 90 91 func decodeDecompressedSearchResponse( 92 response *rpc.TagProperties, 93 pools encoding.IteratorPools, 94 ) (models.Metrics, error) { 95 return nil, errors.ErrNotImplemented 96 } 97 98 func decodeCompressedSearchResponse( 99 response *rpc.M3TagProperties, 100 pools encoding.IteratorPools, 101 ) ([]consolidators.MultiTagResult, error) { 102 if pools == nil || pools.CheckedBytesWrapper() == nil || pools.TagDecoder() == nil { 103 return nil, errors.ErrCannotDecodeCompressedTags 104 } 105 106 cbwPool := pools.CheckedBytesWrapper() 107 decoderPool := pools.TagDecoder() 108 idPool := pools.ID() 109 110 props := response.GetProperties() 111 decoded := make([]consolidators.MultiTagResult, len(props)) 112 for i, prop := range props { 113 checkedBytes := cbwPool.Get(prop.GetCompressedTags()) 114 decoder := decoderPool.Get() 115 decoder.Reset(checkedBytes) 116 if err := decoder.Err(); err != nil { 117 return nil, err 118 } 119 120 id := idPool.BinaryID(cbwPool.Get(prop.GetId())) 121 decoded[i] = consolidators.MultiTagResult{ 122 ID: id, 123 // Copy underlying TagIterator bytes before closing the decoder and returning it to the pool 124 Iter: decoder.Duplicate(), 125 } 126 127 decoder.Close() 128 } 129 130 return decoded, nil 131 } 132 133 func decodeSearchResponse( 134 response *rpc.SearchResponse, 135 pools encoding.IteratorPools, 136 tagOptions models.TagOptions, 137 ) (models.Metrics, error) { 138 if compressed := response.GetCompressed(); compressed != nil { 139 results, err := decodeCompressedSearchResponse(compressed, pools) 140 if err != nil { 141 return nil, err 142 } 143 144 metrics := make(models.Metrics, len(results)) 145 for i, r := range results { 146 m, err := storage.FromM3IdentToMetric(r.ID, r.Iter, tagOptions) 147 if err != nil { 148 return nil, err 149 } 150 151 metrics[i] = m 152 } 153 154 return metrics, nil 155 } 156 157 if decompressed := response.GetDecompressed(); decompressed != nil { 158 return decodeDecompressedSearchResponse(decompressed, pools) 159 } 160 161 return nil, errors.ErrUnexpectedGRPCResponseType 162 } 163 164 // encodeSearchRequest encodes search request into rpc SearchRequest 165 func encodeSearchRequest( 166 query *storage.FetchQuery, 167 options *storage.FetchOptions, 168 ) (*rpc.SearchRequest, error) { 169 matchers, err := encodeTagMatchers(query.TagMatchers) 170 if err != nil { 171 return nil, err 172 } 173 174 opts, err := encodeFetchOptions(options) 175 if err != nil { 176 return nil, err 177 } 178 179 return &rpc.SearchRequest{ 180 Matchers: &rpc.SearchRequest_TagMatchers{ 181 TagMatchers: matchers, 182 }, 183 184 Start: fromTime(query.Start), 185 End: fromTime(query.End), 186 Options: opts, 187 }, nil 188 } 189 190 // decodeSearchRequest decodes rpc search request to read query and read options 191 func decodeSearchRequest( 192 req *rpc.SearchRequest, 193 ) (*storage.FetchQuery, error) { 194 matchers, err := decodeTagMatchers(req.GetTagMatchers()) 195 if err != nil { 196 return nil, err 197 } 198 199 return &storage.FetchQuery{ 200 TagMatchers: matchers, 201 Start: toTime(req.GetStart()), 202 End: toTime(req.GetEnd()), 203 }, nil 204 }