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 }