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