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  }