github.com/matrixorigin/matrixone@v1.2.0/pkg/fileservice/cache.go (about) 1 // Copyright 2022 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 "errors" 20 "fmt" 21 "sync" 22 "time" 23 24 "github.com/matrixorigin/matrixone/pkg/common/morpc" 25 "github.com/matrixorigin/matrixone/pkg/fileservice/memorycache" 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 "github.com/matrixorigin/matrixone/pkg/pb/gossip" 28 pb "github.com/matrixorigin/matrixone/pkg/pb/query" 29 "github.com/matrixorigin/matrixone/pkg/queryservice/client" 30 "github.com/matrixorigin/matrixone/pkg/util/toml" 31 "go.uber.org/zap" 32 ) 33 34 type CacheConfig struct { 35 MemoryCapacity *toml.ByteSize `toml:"memory-capacity" user_setting:"advanced"` 36 DiskPath *string `toml:"disk-path"` 37 DiskCapacity *toml.ByteSize `toml:"disk-capacity"` 38 DiskMinEvictInterval *toml.Duration `toml:"disk-min-evict-interval"` 39 DiskEvictTarget *float64 `toml:"disk-evict-target"` 40 RemoteCacheEnabled bool `toml:"remote-cache-enabled"` 41 RPC morpc.Config `toml:"rpc"` 42 43 QueryClient client.QueryClient `json:"-"` 44 KeyRouterFactory KeyRouterFactory[pb.CacheKey] `json:"-"` 45 KeyRouter client.KeyRouter[pb.CacheKey] `json:"-"` 46 InitKeyRouter *sync.Once `json:"-"` 47 CacheCallbacks `json:"-"` 48 49 enableDiskCacheForLocalFS bool // for testing only 50 } 51 52 type CacheCallbacks struct { 53 PostGet []CacheCallbackFunc 54 PostSet []CacheCallbackFunc 55 PostEvict []CacheCallbackFunc 56 } 57 58 type CacheCallbackFunc = func(CacheKey, memorycache.CacheData) 59 60 func (c *CacheConfig) setDefaults() { 61 if c.MemoryCapacity == nil { 62 size := toml.ByteSize(512 << 20) 63 c.MemoryCapacity = &size 64 } 65 if c.DiskCapacity == nil { 66 size := toml.ByteSize(8 << 30) 67 c.DiskCapacity = &size 68 } 69 if c.DiskMinEvictInterval == nil { 70 c.DiskMinEvictInterval = &toml.Duration{ 71 Duration: time.Minute * 7, 72 } 73 } 74 if c.DiskEvictTarget == nil { 75 target := 0.8 76 c.DiskEvictTarget = &target 77 } 78 c.RPC.Adjust() 79 } 80 81 func (c *CacheConfig) SetRemoteCacheCallback() { 82 if !c.RemoteCacheEnabled || c.KeyRouterFactory == nil { 83 return 84 } 85 c.InitKeyRouter = &sync.Once{} 86 c.CacheCallbacks.PostSet = append(c.CacheCallbacks.PostSet, 87 func(key CacheKey, data memorycache.CacheData) { 88 c.InitKeyRouter.Do(func() { 89 c.KeyRouter = c.KeyRouterFactory() 90 }) 91 if c.KeyRouter == nil { 92 return 93 } 94 c.KeyRouter.AddItem(gossip.CommonItem{ 95 Operation: gossip.Operation_Set, 96 Key: &gossip.CommonItem_CacheKey{ 97 CacheKey: &key, 98 }, 99 }) 100 }, 101 ) 102 c.CacheCallbacks.PostEvict = append(c.CacheCallbacks.PostEvict, 103 func(key CacheKey, data memorycache.CacheData) { 104 c.InitKeyRouter.Do(func() { 105 c.KeyRouter = c.KeyRouterFactory() 106 }) 107 if c.KeyRouter == nil { 108 return 109 } 110 c.KeyRouter.AddItem(gossip.CommonItem{ 111 Operation: gossip.Operation_Delete, 112 Key: &gossip.CommonItem_CacheKey{ 113 CacheKey: &key, 114 }, 115 }) 116 }, 117 ) 118 } 119 120 var DisabledCacheConfig = CacheConfig{ 121 MemoryCapacity: ptrTo[toml.ByteSize](DisableCacheCapacity), 122 DiskCapacity: ptrTo[toml.ByteSize](DisableCacheCapacity), 123 } 124 125 const DisableCacheCapacity = 1 126 127 // var DefaultCacheDataAllocator = RCBytesPool 128 var DefaultCacheDataAllocator = new(bytesAllocator) 129 130 // VectorCache caches IOVector 131 type IOVectorCache interface { 132 Read( 133 ctx context.Context, 134 vector *IOVector, 135 ) error 136 Update( 137 ctx context.Context, 138 vector *IOVector, 139 async bool, 140 ) error 141 Flush() 142 //TODO file contents may change, so we still need this s. 143 DeletePaths( 144 ctx context.Context, 145 paths []string, 146 ) error 147 } 148 149 var slowCacheReadThreshold = time.Second * 0 150 151 func readCache(ctx context.Context, cache IOVectorCache, vector *IOVector) error { 152 if slowCacheReadThreshold > 0 { 153 var cancel context.CancelFunc 154 ctx, cancel = context.WithTimeout(ctx, slowCacheReadThreshold) 155 defer cancel() 156 } 157 err := cache.Read(ctx, vector) 158 if err != nil { 159 if errors.Is(err, context.DeadlineExceeded) { 160 logutil.Warn("cache read exceed deadline", 161 zap.Any("err", err), 162 zap.Any("cache type", fmt.Sprintf("%T", cache)), 163 zap.Any("path", vector.FilePath), 164 zap.Any("entries", vector.Entries), 165 ) 166 // safe to ignore 167 return nil 168 } 169 return err 170 } 171 return nil 172 } 173 174 type CacheKey = pb.CacheKey