github.com/matrixorigin/matrixone@v1.2.0/pkg/gossip/base_item.go (about) 1 // Copyright 2021 - 2024 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 gossip 16 17 import ( 18 "sync" 19 20 "github.com/matrixorigin/matrixone/pkg/pb/gossip" 21 ) 22 23 const ( 24 defaultQueueSize = 100 25 maxItemCount = 8192 * 2000 26 ) 27 28 type BaseStore[K comparable] struct { 29 // cacheServerAddr is the service address of cache server. The items 30 // with it are added to the queue, and then the items are sent to other 31 // nodes. Then other nodes will try to send RPC request with this address 32 // to this node to get item info. 33 cacheServerAddr string 34 35 queueMu struct { 36 sync.Mutex 37 // When local service updates item, it pushes item to this queue. 38 // And gossip worker takes items from the queue and send to other nodes. 39 itemQueue []gossip.CommonItem 40 } 41 42 mu struct { 43 sync.Mutex 44 // keyTarget is the map that local service searches remote keys 45 // when the item does not exist in local service. 46 keyTarget map[K]string // key => cn address 47 } 48 } 49 50 func newBaseStore[K comparable](addr string) *BaseStore[K] { 51 s := &BaseStore[K]{ 52 cacheServerAddr: addr, 53 } 54 s.mu.keyTarget = make(map[K]string) 55 s.queueMu.itemQueue = make([]gossip.CommonItem, 0, defaultQueueSize) 56 return s 57 } 58 59 // Target implements the client.KeyRouter interface. 60 func (s *BaseStore[K]) Target(k K) string { 61 s.mu.Lock() 62 defer s.mu.Unlock() 63 if target, ok := s.mu.keyTarget[k]; ok && target != s.cacheServerAddr { 64 return target 65 } 66 return "" 67 } 68 69 // AddItem implements the client.KeyRouter interface. 70 func (s *BaseStore[K]) AddItem(item gossip.CommonItem) { 71 if s.cacheServerAddr == "" { 72 return 73 } 74 s.queueMu.Lock() 75 defer s.queueMu.Unlock() 76 if len(s.queueMu.itemQueue) >= maxItemCount { 77 return 78 } 79 item.TargetAddress = s.cacheServerAddr 80 s.queueMu.itemQueue = append(s.queueMu.itemQueue, item) 81 } 82 83 // Data implements the Module interface. 84 func (s *BaseStore[K]) Data(limit int) ([]gossip.CommonItem, int) { 85 var items []gossip.CommonItem 86 s.queueMu.Lock() 87 count := len(s.queueMu.itemQueue) 88 if count == 0 { 89 s.queueMu.Unlock() 90 return nil, limit 91 } 92 sz := s.queueMu.itemQueue[0].Size() 93 limitCount := limit / sz 94 var leftSize int 95 if count < limitCount { 96 items = s.queueMu.itemQueue 97 s.queueMu.itemQueue = make([]gossip.CommonItem, 0, defaultQueueSize) 98 leftSize = limit - count*sz 99 s.queueMu.Unlock() 100 } else { 101 items = s.queueMu.itemQueue[:limitCount] 102 s.queueMu.itemQueue = s.queueMu.itemQueue[limitCount:] 103 s.queueMu.Unlock() 104 } 105 return items, leftSize 106 } 107 108 func (s *BaseStore[K]) update(target string, ks []K) { 109 s.mu.Lock() 110 defer s.mu.Unlock() 111 for _, k := range ks { 112 s.mu.keyTarget[k] = target 113 } 114 }