github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/table/tables/memory_tables.go (about) 1 // Copyright 2016 PingCAP, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package tables 15 16 import ( 17 "sync" 18 19 "github.com/insionng/yougam/libraries/juju/errors" 20 "github.com/insionng/yougam/libraries/ngaut/log" 21 "github.com/insionng/yougam/libraries/petar/GoLLRB/llrb" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/column" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 24 "github.com/insionng/yougam/libraries/pingcap/tidb/kv" 25 "github.com/insionng/yougam/libraries/pingcap/tidb/meta/autoid" 26 "github.com/insionng/yougam/libraries/pingcap/tidb/model" 27 "github.com/insionng/yougam/libraries/pingcap/tidb/table" 28 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 29 ) 30 31 var ( 32 errRowNotFound = errors.New("Can not find the row") 33 ) 34 35 type itemKey int64 36 37 type itemPair struct { 38 handle itemKey 39 data []types.Datum 40 } 41 42 func (r *itemPair) Less(item llrb.Item) bool { 43 switch x := item.(type) { 44 case itemKey: 45 return r.handle < x 46 case *itemPair: 47 return r.handle < x.handle 48 } 49 log.Errorf("invalid type %T", item) 50 return true 51 } 52 53 func (k itemKey) Less(item llrb.Item) bool { 54 switch x := item.(type) { 55 case itemKey: 56 return k < x 57 case *itemPair: 58 return k < x.handle 59 } 60 log.Errorf("invalid type %T", item) 61 return true 62 } 63 64 // MemoryTable implements table.Table interface. 65 type MemoryTable struct { 66 ID int64 67 Name model.CIStr 68 Columns []*column.Col 69 pkHandleCol *column.Col 70 71 recordPrefix kv.Key 72 alloc autoid.Allocator 73 meta *model.TableInfo 74 75 tree *llrb.LLRB 76 mu sync.RWMutex 77 } 78 79 // MemoryTableFromMeta creates a Table instance from model.TableInfo. 80 func MemoryTableFromMeta(alloc autoid.Allocator, tblInfo *model.TableInfo) (table.Table, error) { 81 columns := make([]*column.Col, 0, len(tblInfo.Columns)) 82 var pkHandleColumn *column.Col 83 for _, colInfo := range tblInfo.Columns { 84 col := &column.Col{ColumnInfo: *colInfo} 85 columns = append(columns, col) 86 if col.IsPKHandleColumn(tblInfo) { 87 pkHandleColumn = col 88 } 89 } 90 t := newMemoryTable(tblInfo.ID, tblInfo.Name.O, columns, alloc) 91 t.pkHandleCol = pkHandleColumn 92 t.meta = tblInfo 93 return t, nil 94 } 95 96 // newMemoryTable constructs a MemoryTable instance. 97 func newMemoryTable(tableID int64, tableName string, cols []*column.Col, alloc autoid.Allocator) *MemoryTable { 98 name := model.NewCIStr(tableName) 99 t := &MemoryTable{ 100 ID: tableID, 101 Name: name, 102 alloc: alloc, 103 Columns: cols, 104 recordPrefix: genTableRecordPrefix(tableID), 105 tree: llrb.New(), 106 } 107 return t 108 } 109 110 // Seek seeks the handle 111 func (t *MemoryTable) Seek(ctx context.Context, handle int64) (int64, bool, error) { 112 var found bool 113 var result int64 114 t.mu.RLock() 115 t.tree.AscendGreaterOrEqual(itemKey(handle), func(item llrb.Item) bool { 116 found = true 117 result = int64(item.(*itemPair).handle) 118 return false 119 }) 120 t.mu.RUnlock() 121 return result, found, nil 122 } 123 124 // Indices implements table.Table Indices interface. 125 func (t *MemoryTable) Indices() []*column.IndexedCol { 126 return nil 127 } 128 129 // Meta implements table.Table Meta interface. 130 func (t *MemoryTable) Meta() *model.TableInfo { 131 return t.meta 132 } 133 134 // Cols implements table.Table Cols interface. 135 func (t *MemoryTable) Cols() []*column.Col { 136 return t.Columns 137 } 138 139 // RecordPrefix implements table.Table RecordPrefix interface. 140 func (t *MemoryTable) RecordPrefix() kv.Key { 141 return t.recordPrefix 142 } 143 144 // IndexPrefix implements table.Table IndexPrefix interface. 145 func (t *MemoryTable) IndexPrefix() kv.Key { 146 return nil 147 } 148 149 // RecordKey implements table.Table RecordKey interface. 150 func (t *MemoryTable) RecordKey(h int64, col *column.Col) kv.Key { 151 colID := int64(0) 152 if col != nil { 153 colID = col.ID 154 } 155 return encodeRecordKey(t.recordPrefix, h, colID) 156 } 157 158 // FirstKey implements table.Table FirstKey interface. 159 func (t *MemoryTable) FirstKey() kv.Key { 160 return t.RecordKey(0, nil) 161 } 162 163 // Truncate implements table.Table Truncate interface. 164 func (t *MemoryTable) Truncate(ctx context.Context) error { 165 t.tree = llrb.New() 166 return nil 167 } 168 169 // UpdateRecord implements table.Table UpdateRecord interface. 170 func (t *MemoryTable) UpdateRecord(ctx context.Context, h int64, oldData []types.Datum, newData []types.Datum, touched map[int]bool) error { 171 t.mu.Lock() 172 defer t.mu.Unlock() 173 item := t.tree.Get(itemKey(h)) 174 if item == nil { 175 return errRowNotFound 176 } 177 pair := item.(*itemPair) 178 pair.data = newData 179 return nil 180 } 181 182 // AddRecord implements table.Table AddRecord interface. 183 func (t *MemoryTable) AddRecord(ctx context.Context, r []types.Datum) (recordID int64, err error) { 184 if t.pkHandleCol != nil { 185 recordID, err = types.ToInt64(r[t.pkHandleCol.Offset].GetValue()) 186 if err != nil { 187 return 0, errors.Trace(err) 188 } 189 } else { 190 recordID, err = t.alloc.Alloc(t.ID) 191 if err != nil { 192 return 0, errors.Trace(err) 193 } 194 } 195 item := &itemPair{ 196 handle: itemKey(recordID), 197 data: r, 198 } 199 t.mu.Lock() 200 defer t.mu.Unlock() 201 if t.tree.Get(itemKey(recordID)) != nil { 202 return 0, kv.ErrKeyExists 203 } 204 t.tree.ReplaceOrInsert(item) 205 return 206 } 207 208 // RowWithCols implements table.Table RowWithCols interface. 209 func (t *MemoryTable) RowWithCols(ctx context.Context, h int64, cols []*column.Col) ([]types.Datum, error) { 210 t.mu.RLock() 211 defer t.mu.RUnlock() 212 item := t.tree.Get(itemKey(h)) 213 if item == nil { 214 return nil, errRowNotFound 215 } 216 row := item.(*itemPair).data 217 v := make([]types.Datum, len(cols)) 218 for i, col := range cols { 219 if col == nil { 220 continue 221 } 222 v[i] = row[col.Offset] 223 } 224 return v, nil 225 } 226 227 // Row implements table.Table Row interface. 228 func (t *MemoryTable) Row(ctx context.Context, h int64) ([]types.Datum, error) { 229 r, err := t.RowWithCols(nil, h, t.Cols()) 230 if err != nil { 231 return nil, errors.Trace(err) 232 } 233 return r, nil 234 } 235 236 // LockRow implements table.Table LockRow interface. 237 func (t *MemoryTable) LockRow(ctx context.Context, h int64, forRead bool) error { 238 return nil 239 } 240 241 // RemoveRecord implements table.Table RemoveRecord interface. 242 func (t *MemoryTable) RemoveRecord(ctx context.Context, h int64, r []types.Datum) error { 243 t.mu.Lock() 244 t.tree.Delete(itemKey(h)) 245 t.mu.Unlock() 246 return nil 247 } 248 249 // AllocAutoID implements table.Table AllocAutoID interface. 250 func (t *MemoryTable) AllocAutoID() (int64, error) { 251 return t.alloc.Alloc(t.ID) 252 } 253 254 // RebaseAutoID implements table.Table RebaseAutoID interface. 255 func (t *MemoryTable) RebaseAutoID(newBase int64, isSetStep bool) error { 256 return t.alloc.Rebase(t.ID, newBase, isSetStep) 257 } 258 259 // IterRecords implements table.Table IterRecords interface. 260 func (t *MemoryTable) IterRecords(ctx context.Context, startKey kv.Key, cols []*column.Col, 261 fn table.RecordIterFunc) error { 262 return nil 263 }