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  }