github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/storage/memorystorage/memorytable/table.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 memorytable
    16  
    17  import (
    18  	"database/sql"
    19  	"io"
    20  	"sort"
    21  	"sync"
    22  	"sync/atomic"
    23  
    24  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    25  )
    26  
    27  // Table represents a table
    28  type Table[
    29  	K Ordered[K],
    30  	V any,
    31  	R Row[K, V],
    32  ] struct {
    33  	id int64
    34  	sync.Mutex
    35  	state atomic.Pointer[tableState[K, V]]
    36  
    37  	disableHistory atomic.Bool
    38  	history        []*history[K, V]
    39  }
    40  
    41  var nextTableID = int64(1)
    42  
    43  // Row represents a logical row in a table
    44  type Row[K any, V any] interface {
    45  	Key() K
    46  	Value() V
    47  	Indexes() []Tuple
    48  	UniqueIndexes() []Tuple
    49  }
    50  
    51  // NewTable creates new table
    52  func NewTable[
    53  	K Ordered[K],
    54  	V any,
    55  	R Row[K, V],
    56  ]() *Table[K, V, R] {
    57  	ret := &Table[K, V, R]{
    58  		id: atomic.AddInt64(&nextTableID, 1),
    59  	}
    60  	state := &tableState[K, V]{
    61  		tree: NewBTree[K, V](),
    62  		log:  NewSliceLog[K, V](),
    63  	}
    64  	ret.state.Store(state)
    65  	return ret
    66  }
    67  
    68  func (t *Table[K, V, R]) getTransactionTable(
    69  	tx *Transaction,
    70  ) (
    71  	txTable *transactionTable,
    72  	err error,
    73  ) {
    74  	tx.tables.Lock()
    75  	var ok bool
    76  	txTable, ok = tx.tables.Map[t.id]
    77  	if !ok {
    78  		return t.getTransactionTableSlow(tx)
    79  	}
    80  	tx.tables.Unlock()
    81  	return
    82  }
    83  
    84  func (t *Table[K, V, R]) getTransactionTableSlow(
    85  	tx *Transaction,
    86  ) (
    87  	txTable *transactionTable,
    88  	err error,
    89  ) {
    90  	defer tx.tables.Unlock()
    91  
    92  	txTable = &transactionTable{
    93  		table: t,
    94  	}
    95  
    96  	t.Lock()
    97  	defer t.Unlock()
    98  	if !tx.BeginTime.IsEmpty() && len(t.history) > 0 {
    99  		// get from history
   100  		i := sort.Search(len(t.history), func(i int) bool {
   101  			t := t.history[i]
   102  			return tx.BeginTime.Equal(t.EndTime) || tx.BeginTime.Less(t.EndTime)
   103  		})
   104  		if i < len(t.history) {
   105  			if i == 0 {
   106  				if tx.BeginTime.Less(t.history[0].EndTime) {
   107  					// too old
   108  					return nil, moerr.NewInternalErrorNoCtx("transaction begin time too old")
   109  				}
   110  			}
   111  			state := t.history[i].EndState
   112  			txTable.state.Store(state.clone())
   113  			txTable.initState = state
   114  		} else {
   115  			// after all history
   116  			state := t.state.Load()
   117  			txTable.state.Store(state.clone())
   118  			txTable.initState = state
   119  		}
   120  
   121  	} else {
   122  		// use latest
   123  		state := t.state.Load()
   124  		txTable.state.Store(state.clone())
   125  		txTable.initState = state
   126  	}
   127  
   128  	tx.tables.Map[t.id] = txTable
   129  
   130  	return
   131  }
   132  
   133  func (t *Table[K, V, R]) DisableHistory() {
   134  	t.disableHistory.Store(true)
   135  }
   136  
   137  // Insert inserts a row to the table
   138  func (t *Table[K, V, R]) Insert(
   139  	tx *Transaction,
   140  	row R,
   141  ) (
   142  	err error,
   143  ) {
   144  	bat, err := t.NewBatch(tx)
   145  	if err != nil {
   146  		return err
   147  	}
   148  	if err := bat.Insert(row); err != nil {
   149  		return err
   150  	}
   151  	bat.Commit()
   152  	return nil
   153  }
   154  
   155  // Update updates a row in the table
   156  func (t *Table[K, V, R]) Update(
   157  	tx *Transaction,
   158  	row R,
   159  ) (
   160  	err error,
   161  ) {
   162  	bat, err := t.NewBatch(tx)
   163  	if err != nil {
   164  		return err
   165  	}
   166  	if err := bat.Update(row); err != nil {
   167  		return err
   168  	}
   169  	bat.Commit()
   170  	return nil
   171  }
   172  
   173  // Delete deletes a row from the table
   174  func (t *Table[K, V, R]) Delete(
   175  	tx *Transaction,
   176  	key K,
   177  ) (
   178  	err error,
   179  ) {
   180  	bat, err := t.NewBatch(tx)
   181  	if err != nil {
   182  		return err
   183  	}
   184  	if err := bat.Delete(key); err != nil {
   185  		return err
   186  	}
   187  	bat.Commit()
   188  	return nil
   189  }
   190  
   191  // Upsert update a row in the table or insert the row to the table if not exists
   192  func (t *Table[K, V, R]) Upsert(
   193  	tx *Transaction,
   194  	row R,
   195  ) (
   196  	err error,
   197  ) {
   198  	bat, err := t.NewBatch(tx)
   199  	if err != nil {
   200  		return err
   201  	}
   202  	if err := bat.Upsert(row); err != nil {
   203  		return err
   204  	}
   205  	bat.Commit()
   206  	return nil
   207  }
   208  
   209  // Get gets the value of a key
   210  func (t *Table[K, V, R]) Get(
   211  	tx *Transaction,
   212  	key K,
   213  ) (
   214  	value V,
   215  	err error,
   216  ) {
   217  	txTable, err := t.getTransactionTable(tx)
   218  	if err != nil {
   219  		return
   220  	}
   221  	state := txTable.state.Load().(*tableState[K, V])
   222  	node := TreeNode[K, V]{
   223  		KVPair: &KVPair[K, V]{
   224  			Key: key,
   225  		},
   226  	}
   227  	node, ok := state.tree.Get(node)
   228  	if !ok {
   229  		err = sql.ErrNoRows
   230  		return
   231  	}
   232  	value = node.KVPair.Value
   233  	return
   234  }
   235  
   236  // NewIndexIter creates new index iter
   237  func (t *Table[K, V, R]) NewIndexIter(tx *Transaction, min Tuple, max Tuple) (Iter[*IndexEntry[K, V]], error) {
   238  	txTable, err := t.getTransactionTable(tx)
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  	state := txTable.state.Load().(*tableState[K, V])
   243  	iter := state.tree.Copy().Iter()
   244  	return NewBoundedIndexIter(iter, min, max), nil
   245  }
   246  
   247  // Index finds entry in table
   248  func (t *Table[K, V, R]) Index(tx *Transaction, index Tuple) (entries []*IndexEntry[K, V], err error) {
   249  	iter, err := t.NewIndexIter(
   250  		tx,
   251  		index,
   252  		index,
   253  	)
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	defer iter.Close()
   258  	for ok := iter.First(); ok; ok = iter.Next() {
   259  		entry, err := iter.Read()
   260  		if err != nil {
   261  			return nil, err
   262  		}
   263  		entries = append(entries, entry)
   264  	}
   265  	return
   266  }
   267  
   268  func (t *Table[K, V, R]) Dump(w io.Writer) {
   269  	state := t.state.Load()
   270  	state.dump(w)
   271  }