github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/model/transfer.go (about) 1 // Copyright 2021 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 model 16 17 import ( 18 v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" 19 "sync" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 24 ) 25 26 type PageT[T common.IRef] interface { 27 common.IRef 28 Pin() *common.PinnedItem[T] 29 TTL(time.Time, time.Duration) bool 30 ID() *common.ID 31 Length() int 32 } 33 34 type TransferTable[T PageT[T]] struct { 35 sync.RWMutex 36 ttl time.Duration 37 pages map[common.ID]*common.PinnedItem[T] 38 } 39 40 func NewTransferTable[T PageT[T]](ttl time.Duration) *TransferTable[T] { 41 return &TransferTable[T]{ 42 ttl: ttl, 43 pages: make(map[common.ID]*common.PinnedItem[T]), 44 } 45 } 46 47 func (table *TransferTable[T]) Pin(id common.ID) (pinned *common.PinnedItem[T], err error) { 48 table.RLock() 49 defer table.RUnlock() 50 var found bool 51 if pinned, found = table.pages[id]; !found { 52 err = moerr.GetOkExpectedEOB() 53 } else { 54 pinned = pinned.Item().Pin() 55 } 56 return 57 } 58 func (table *TransferTable[T]) Len() int { 59 table.RLock() 60 defer table.RUnlock() 61 return len(table.pages) 62 } 63 func (table *TransferTable[T]) prepareTTL(now time.Time) (items []*common.PinnedItem[T]) { 64 table.RLock() 65 defer table.RUnlock() 66 for _, page := range table.pages { 67 if page.Item().TTL(now, table.ttl) { 68 items = append(items, page) 69 } 70 } 71 return 72 } 73 74 func (table *TransferTable[T]) executeTTL(items []*common.PinnedItem[T]) { 75 if len(items) == 0 { 76 return 77 } 78 79 cnt := 0 80 81 table.Lock() 82 for _, pinned := range items { 83 cnt += pinned.Val.Length() 84 delete(table.pages, *pinned.Item().ID()) 85 } 86 table.Unlock() 87 for _, pinned := range items { 88 pinned.Close() 89 } 90 91 v2.TaskMergeTransferPageLengthGauge.Sub(float64(cnt)) 92 } 93 94 func (table *TransferTable[T]) RunTTL(now time.Time) { 95 items := table.prepareTTL(now) 96 table.executeTTL(items) 97 } 98 99 func (table *TransferTable[T]) AddPage(page T) (dup bool) { 100 pinned := page.Pin() 101 defer func() { 102 if dup { 103 pinned.Close() 104 } 105 }() 106 table.Lock() 107 defer table.Unlock() 108 id := *page.ID() 109 if _, found := table.pages[id]; found { 110 dup = true 111 return 112 } 113 table.pages[id] = pinned 114 115 v2.TaskMergeTransferPageLengthGauge.Add(float64(page.Length())) 116 return 117 } 118 119 func (table *TransferTable[T]) DeletePage(id *common.ID) (deleted bool) { 120 table.Lock() 121 defer table.Unlock() 122 if _, deleted = table.pages[*id]; !deleted { 123 return 124 } 125 delete(table.pages, *id) 126 127 // to pass ut 128 if len(table.pages) == 0 || table.pages[*id] == nil { 129 return 130 } 131 132 cnt := table.pages[*id].Val.Length() 133 v2.TaskMergeTransferPageLengthGauge.Sub(float64(cnt)) 134 return 135 } 136 137 func (table *TransferTable[T]) Close() { 138 table.Lock() 139 defer table.Unlock() 140 for _, item := range table.pages { 141 item.Close() 142 } 143 table.pages = make(map[common.ID]*common.PinnedItem[T]) 144 }