github.com/matrixorigin/matrixone@v1.2.0/pkg/incrservice/table_cache.go (about)

     1  // Copyright 2023 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 incrservice
    16  
    17  import (
    18  	"context"
    19  	"sync"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/common/log"
    22  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    23  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    24  )
    25  
    26  type tableCache struct {
    27  	logger  *log.MOLogger
    28  	tableID uint64
    29  	cols    []AutoColumn
    30  
    31  	mu struct {
    32  		sync.RWMutex
    33  		committed bool
    34  		txnOp     client.TxnOperator
    35  		cols      map[string]*columnCache
    36  	}
    37  }
    38  
    39  func newTableCache(
    40  	ctx context.Context,
    41  	tableID uint64,
    42  	cols []AutoColumn,
    43  	cfg Config,
    44  	allocator valueAllocator,
    45  	txnOp client.TxnOperator,
    46  	committed bool) (incrTableCache, error) {
    47  	c := &tableCache{
    48  		logger:  getLogger(),
    49  		tableID: tableID,
    50  		cols:    cols,
    51  	}
    52  	c.mu.cols = make(map[string]*columnCache, 1)
    53  	c.mu.txnOp = txnOp
    54  	c.mu.committed = committed
    55  	for _, col := range cols {
    56  		cc, err := newColumnCache(
    57  			ctx,
    58  			tableID,
    59  			col,
    60  			cfg,
    61  			committed,
    62  			allocator,
    63  			txnOp)
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  		c.mu.cols[col.ColName] = cc
    68  	}
    69  	return c, nil
    70  }
    71  
    72  func (c *tableCache) commit() {
    73  	c.mu.Lock()
    74  	defer c.mu.Unlock()
    75  	if c.mu.committed {
    76  		panic("commit already committed cache")
    77  	}
    78  	c.mu.committed = true
    79  	c.mu.txnOp = nil
    80  	for _, col := range c.mu.cols {
    81  		col.Lock()
    82  		col.committed = true
    83  		col.Unlock()
    84  	}
    85  }
    86  
    87  func (c *tableCache) getTxn() client.TxnOperator {
    88  	c.mu.Lock()
    89  	defer c.mu.Unlock()
    90  	return c.mu.txnOp
    91  }
    92  
    93  func (c *tableCache) insertAutoValues(
    94  	ctx context.Context,
    95  	tableID uint64,
    96  	bat *batch.Batch,
    97  	estimate int64,
    98  ) (uint64, error) {
    99  	lastInsert := uint64(0)
   100  	txnOp := c.getTxn()
   101  	for _, col := range c.cols {
   102  		cc := c.getColumnCache(col.ColName)
   103  		if cc == nil {
   104  			panic("column cache should not be nil, " + col.ColName)
   105  		}
   106  
   107  		if estimate > int64(cc.cfg.CountPerAllocate) {
   108  			cc.preAllocate(ctx, tableID, int(estimate), txnOp)
   109  		}
   110  
   111  		rows := bat.RowCount()
   112  		vec := bat.GetVector(int32(col.ColIndex))
   113  		if v, err := cc.insertAutoValues(ctx, tableID, vec, rows, txnOp); err != nil {
   114  			return 0, err
   115  		} else {
   116  			lastInsert = v
   117  		}
   118  	}
   119  	return lastInsert, nil
   120  }
   121  
   122  func (c *tableCache) currentValue(
   123  	ctx context.Context,
   124  	tableID uint64,
   125  	targetCol string) (uint64, error) {
   126  	for _, col := range c.cols {
   127  		if col.ColName == targetCol {
   128  			cc := c.getColumnCache(col.ColName)
   129  			if cc == nil {
   130  				panic("column cache should not be nil, " + col.ColName)
   131  			}
   132  			return cc.current(ctx)
   133  		}
   134  	}
   135  	return 0, nil
   136  }
   137  
   138  func (c *tableCache) table() uint64 {
   139  	return c.tableID
   140  }
   141  
   142  func (c *tableCache) columns() []AutoColumn {
   143  	return c.cols
   144  }
   145  
   146  func (c *tableCache) getColumnCache(col string) *columnCache {
   147  	c.mu.RLock()
   148  	defer c.mu.RUnlock()
   149  	return c.mu.cols[col]
   150  }
   151  
   152  func (c *tableCache) close() error {
   153  	c.mu.Lock()
   154  	defer c.mu.Unlock()
   155  	for _, cc := range c.mu.cols {
   156  		if err := cc.close(); err != nil {
   157  			return err
   158  		}
   159  	}
   160  	return nil
   161  }
   162  
   163  func (c *tableCache) adjust(
   164  	ctx context.Context,
   165  	cols []AutoColumn) error {
   166  	c.mu.Lock()
   167  	defer c.mu.Unlock()
   168  	for idx := range c.cols {
   169  		v, err := c.mu.cols[c.cols[idx].ColName].current(ctx)
   170  		if err != nil {
   171  			return err
   172  		}
   173  		if v > 0 {
   174  			cols[idx].Offset = v - 1
   175  		}
   176  	}
   177  	return nil
   178  }