github.com/matrixorigin/matrixone@v1.2.0/pkg/fileservice/remote_cache.go (about) 1 // Copyright 2021 - 2023 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fileservice 16 17 import ( 18 "context" 19 "github.com/matrixorigin/matrixone/pkg/common/moerr" 20 "sync" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/pb/query" 24 "github.com/matrixorigin/matrixone/pkg/perfcounter" 25 "github.com/matrixorigin/matrixone/pkg/queryservice/client" 26 metric "github.com/matrixorigin/matrixone/pkg/util/metric/v2" 27 ) 28 29 type TargetCacheKeys map[string][]*query.RequestCacheKey 30 31 type KeyRouterFactory[T comparable] func() client.KeyRouter[T] 32 33 // RemoteCache is the cache for remote read. 34 type RemoteCache struct { 35 // client sends the cache request to query server. 36 client client.QueryClient 37 // keyRouterFactory is used to set the keyRouter async. 38 keyRouterFactory KeyRouterFactory[query.CacheKey] 39 // keyRouter is used to find out which node we should send 40 // cache request to. 41 keyRouter client.KeyRouter[query.CacheKey] 42 // We only init the key router for the first time. 43 init sync.Once 44 } 45 46 var _ IOVectorCache = new(RemoteCache) 47 48 func NewRemoteCache(client client.QueryClient, factory KeyRouterFactory[query.CacheKey]) *RemoteCache { 49 return &RemoteCache{ 50 client: client, 51 keyRouterFactory: factory, 52 } 53 } 54 55 func (r *RemoteCache) Read(ctx context.Context, vector *IOVector) error { 56 if r.keyRouterFactory == nil { 57 return nil 58 } 59 r.init.Do(func() { 60 r.keyRouter = r.keyRouterFactory() 61 }) 62 if r.keyRouter == nil { 63 return nil 64 } 65 66 path, err := ParsePath(vector.FilePath) 67 if err != nil { 68 return err 69 } 70 71 var numHit, numRead int64 72 defer func() { 73 metric.FSReadHitRemoteCounter.Add(float64(numHit)) 74 perfcounter.Update(ctx, func(c *perfcounter.CounterSet) { 75 c.FileService.Cache.Read.Add(numRead) 76 c.FileService.Cache.Hit.Add(numHit) 77 c.FileService.Cache.Remote.Read.Add(numRead) 78 c.FileService.Cache.Remote.Hit.Add(numHit) 79 }) 80 }() 81 82 targetCacheKeys := make(TargetCacheKeys, len(vector.Entries)) 83 for i, entry := range vector.Entries { 84 if entry.done { 85 continue 86 } 87 if entry.Size < 0 { 88 continue 89 } 90 91 cacheKey := CacheKey{ 92 Path: path.File, 93 Offset: entry.Offset, 94 Sz: entry.Size, 95 } 96 target := r.keyRouter.Target(cacheKey) 97 if len(target) == 0 { 98 continue 99 } 100 101 if _, ok := targetCacheKeys[target]; !ok { 102 targetCacheKeys[target] = make([]*query.RequestCacheKey, 0) 103 } 104 targetCacheKeys[target] = append(targetCacheKeys[target], &query.RequestCacheKey{ 105 Index: int32(i), 106 CacheKey: &cacheKey, 107 }) 108 } 109 110 for target, key := range targetCacheKeys { 111 req := r.client.NewRequest(query.CmdMethod_GetCacheData) 112 req.GetCacheDataRequest = &query.GetCacheDataRequest{ 113 RequestCacheKey: key, 114 } 115 116 func(ctx context.Context) { 117 ctx, cancel := context.WithTimeout(ctx, time.Second*2) 118 defer cancel() 119 resp, err := r.client.SendMessage(ctx, target, req) 120 if err != nil { 121 // Do not return error here to read data from local storage. 122 return 123 } 124 defer r.client.Release(resp) 125 if resp.GetCacheDataResponse != nil { 126 for _, cacheData := range resp.GetCacheDataResponse.ResponseCacheData { 127 numRead++ 128 idx := int(cacheData.Index) 129 if cacheData.Hit { 130 vector.Entries[idx].done = true 131 vector.Entries[idx].CachedData = Bytes(cacheData.Data) 132 vector.Entries[idx].fromCache = r 133 numHit++ 134 } 135 } 136 } 137 }(ctx) 138 } 139 return nil 140 } 141 142 func (r *RemoteCache) Update(ctx context.Context, vector *IOVector, async bool) error { 143 return nil 144 } 145 146 func (r *RemoteCache) Flush() {} 147 148 func (r *RemoteCache) DeletePaths(ctx context.Context, paths []string) error { 149 //TODO 150 return nil 151 } 152 153 func HandleRemoteRead( 154 ctx context.Context, fs FileService, req *query.Request, resp *query.WrappedResponse, 155 ) error { 156 if req.GetCacheDataRequest == nil { 157 return moerr.NewInternalError(ctx, "bad request") 158 } 159 first := req.GetCacheDataRequest.RequestCacheKey[0].CacheKey 160 if first == nil { // We cannot get the first one. 161 return nil 162 } 163 164 ioVec := &IOVector{ 165 FilePath: first.Path, 166 } 167 ioVec.Entries = make([]IOEntry, len(req.GetCacheDataRequest.RequestCacheKey)) 168 for i, k := range req.GetCacheDataRequest.RequestCacheKey { 169 ioVec.Entries[i].Offset = k.CacheKey.Offset 170 ioVec.Entries[i].Size = k.CacheKey.Sz 171 } 172 if err := fs.ReadCache(ctx, ioVec); err != nil { 173 return err 174 } 175 respData := make([]*query.ResponseCacheData, len(req.GetCacheDataRequest.RequestCacheKey)) 176 for i, k := range req.GetCacheDataRequest.RequestCacheKey { 177 var data []byte 178 if ioVec.Entries[i].CachedData != nil { 179 data = ioVec.Entries[i].CachedData.Bytes() 180 } 181 respData[i] = &query.ResponseCacheData{ 182 Index: k.Index, 183 Hit: ioVec.Entries[i].fromCache != nil, 184 Data: data, 185 } 186 } 187 188 resp.GetCacheDataResponse = &query.GetCacheDataResponse{ 189 ResponseCacheData: respData, 190 } 191 resp.ReleaseFunc = func() { ioVec.Release() } 192 return nil 193 }