github.com/matrixorigin/matrixone@v1.2.0/pkg/incrservice/store_mem.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  	"math"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/pb/txn"
    24  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    25  )
    26  
    27  type memStore struct {
    28  	sync.Mutex
    29  	caches      map[uint64][]AutoColumn
    30  	uncommitted map[string]map[uint64][]AutoColumn
    31  }
    32  
    33  // NewMemStore new mem store
    34  func NewMemStore() IncrValueStore {
    35  	return &memStore{
    36  		caches:      make(map[uint64][]AutoColumn),
    37  		uncommitted: make(map[string]map[uint64][]AutoColumn),
    38  	}
    39  }
    40  
    41  func (s *memStore) NewTxnOperator(_ context.Context) client.TxnOperator {
    42  	return nil
    43  }
    44  
    45  func (s *memStore) SelectAll(_ context.Context, _ uint64, _ client.TxnOperator) (string, error) {
    46  	return "", nil
    47  }
    48  
    49  func (s *memStore) Create(
    50  	ctx context.Context,
    51  	tableID uint64,
    52  	cols []AutoColumn,
    53  	txnOp client.TxnOperator) error {
    54  	s.Lock()
    55  	defer s.Unlock()
    56  	m := s.caches
    57  	if txnOp != nil {
    58  		m = make(map[uint64][]AutoColumn)
    59  		s.uncommitted[string(txnOp.Txn().ID)] = m
    60  		txnOp.AppendEventCallback(
    61  			client.ClosedEvent,
    62  			func(event client.TxnEvent) {
    63  				txnMeta := event.Txn
    64  				s.Lock()
    65  				defer s.Unlock()
    66  				delete(s.uncommitted, string(txnMeta.ID))
    67  				if txnMeta.Status == txn.TxnStatus_Committed {
    68  					for k, v := range m {
    69  						s.caches[k] = v
    70  					}
    71  				}
    72  			})
    73  	}
    74  
    75  	caches := m[tableID]
    76  	for _, col := range cols {
    77  		has := false
    78  		for _, cache := range caches {
    79  			if cache.ColName == col.ColName {
    80  				has = true
    81  				break
    82  			}
    83  		}
    84  		if !has {
    85  			caches = append(caches, col)
    86  		}
    87  	}
    88  	m[tableID] = caches
    89  	return nil
    90  }
    91  
    92  func (s *memStore) GetColumns(
    93  	ctx context.Context,
    94  	tableID uint64,
    95  	txnOp client.TxnOperator) ([]AutoColumn, error) {
    96  	s.Lock()
    97  	defer s.Unlock()
    98  	s.Lock()
    99  	defer s.Unlock()
   100  	m := s.caches
   101  	if txnOp != nil {
   102  		m = s.uncommitted[string(txnOp.Txn().ID)]
   103  	}
   104  	return m[tableID], nil
   105  }
   106  
   107  func (s *memStore) Allocate(
   108  	ctx context.Context,
   109  	tableID uint64,
   110  	key string,
   111  	count int,
   112  	txnOp client.TxnOperator) (uint64, uint64, error) {
   113  	s.Lock()
   114  	defer s.Unlock()
   115  	m := s.caches
   116  	if txnOp != nil {
   117  		m = s.uncommitted[string(txnOp.Txn().ID)]
   118  	}
   119  
   120  	cols, ok := m[tableID]
   121  	if !ok {
   122  		panic("missing incr column record")
   123  	}
   124  
   125  	var c *AutoColumn
   126  	for i := range cols {
   127  		if cols[i].ColName == key {
   128  			c = &cols[i]
   129  		}
   130  	}
   131  	if !ok {
   132  		panic("missing incr column record")
   133  	}
   134  
   135  	curr := c.Offset
   136  	next := getNext(curr, count, int(c.Step))
   137  	c.Offset = next
   138  	from, to := getNextRange(curr, next, int(c.Step))
   139  	time.Sleep(time.Millisecond * 10)
   140  	return from, to, nil
   141  }
   142  
   143  func (s *memStore) UpdateMinValue(
   144  	ctx context.Context,
   145  	tableID uint64,
   146  	col string,
   147  	minValue uint64,
   148  	txnOp client.TxnOperator) error {
   149  	s.Lock()
   150  	defer s.Unlock()
   151  	m := s.caches
   152  	if txnOp != nil {
   153  		m = s.uncommitted[string(txnOp.Txn().ID)]
   154  	}
   155  
   156  	cols, ok := m[tableID]
   157  	if !ok {
   158  		panic("missing incr column record")
   159  	}
   160  
   161  	var c *AutoColumn
   162  	for i := range cols {
   163  		if cols[i].ColName == col {
   164  			c = &cols[i]
   165  		}
   166  	}
   167  	if !ok {
   168  		panic("missing incr column record")
   169  	}
   170  
   171  	if c != nil && c.Offset < minValue {
   172  		c.Offset = minValue
   173  	}
   174  	return nil
   175  }
   176  
   177  func (s *memStore) Delete(
   178  	ctx context.Context,
   179  	tableID uint64) error {
   180  	s.Lock()
   181  	defer s.Unlock()
   182  	delete(s.caches, tableID)
   183  	return nil
   184  }
   185  
   186  func (s *memStore) Close() {
   187  
   188  }
   189  
   190  func getNext(curr uint64, count, step int) uint64 {
   191  	n := uint64(count * step)
   192  	diff := math.MaxUint64 - curr
   193  	if diff <= n {
   194  		return math.MaxUint64
   195  	}
   196  	return curr + n
   197  }
   198  
   199  // [from, to)
   200  func getNextRange(curr uint64, next uint64, step int) (uint64, uint64) {
   201  	return curr + uint64(step), next + uint64(step)
   202  }