github.com/matrixorigin/matrixone@v1.2.0/pkg/incrservice/range_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  type ranges struct {
    18  	step        uint64
    19  	values      []uint64
    20  	minCanAdded uint64
    21  }
    22  
    23  func (r *ranges) rangeCount() int {
    24  	return len(r.values) / 2
    25  }
    26  
    27  func (r *ranges) empty() bool {
    28  	n := r.rangeCount()
    29  	for i := 0; i < n; i++ {
    30  		from, to := r.values[2*i], r.values[2*i+1]
    31  		if from < to {
    32  			return false
    33  		}
    34  	}
    35  	return true
    36  }
    37  
    38  func (r *ranges) next() uint64 {
    39  	n := r.rangeCount()
    40  	for i := 0; i < n; i++ {
    41  		from, to := r.values[2*i], r.values[2*i+1]
    42  		if from < to {
    43  			r.values[2*i] += r.step
    44  			if r.values[2*i] == to {
    45  				r.values = r.values[2*i+2:]
    46  			}
    47  			return from
    48  		}
    49  	}
    50  	return 0
    51  }
    52  
    53  func (r *ranges) current() uint64 {
    54  	n := r.rangeCount()
    55  	for i := 0; i < n; i++ {
    56  		from, to := r.values[2*i], r.values[2*i+1]
    57  		if from < to {
    58  			return from
    59  		}
    60  	}
    61  	return 0
    62  }
    63  
    64  func (r *ranges) left() int {
    65  	v := 0
    66  	n := r.rangeCount()
    67  	for i := 0; i < n; i++ {
    68  		from, to := r.values[2*i], r.values[2*i+1]
    69  		v += int((to - from) / r.step)
    70  	}
    71  	return v
    72  }
    73  
    74  func (r *ranges) setManual(
    75  	value uint64,
    76  	skipped *ranges) {
    77  	newValues := r.values[:0]
    78  	n := r.rangeCount()
    79  	for i := 0; i < n; i++ {
    80  		from, to := r.values[2*i], r.values[2*i+1]
    81  		if to <= value {
    82  			skipped.add(from, to)
    83  			continue
    84  		}
    85  		if from > value {
    86  			newValues = append(newValues, from, to)
    87  			continue
    88  		}
    89  		skipped.add(from, value)
    90  		if value+1 < to {
    91  			newValues = append(newValues, value+1, to)
    92  		}
    93  	}
    94  	r.values = newValues
    95  }
    96  
    97  func (r *ranges) add(from, to uint64) {
    98  	if r.minCanAdded >= to {
    99  		return
   100  	}
   101  	if r.minCanAdded >= from {
   102  		from = r.minCanAdded
   103  	}
   104  	if from < to {
   105  		r.values = append(r.values, from, to)
   106  	}
   107  	r.minCanAdded = to
   108  }
   109  
   110  // updateTo after updateTo returns, make sure that the value
   111  // returned by ranges.next() must be greater than value.
   112  // Return true means the value is include in old ranges, otherwise
   113  // the value of this value must be updated to the store to avoid
   114  // skipping the value when restarting or other cache is allocated
   115  // next time.
   116  func (r *ranges) updateTo(value uint64) bool {
   117  	n := r.rangeCount()
   118  	compactTo := -1
   119  	contains := false
   120  	for i := 0; i < n; i++ {
   121  		from, to := r.values[2*i], r.values[2*i+1]
   122  		if from > value {
   123  			contains = true
   124  			break
   125  		}
   126  		if value >= to {
   127  			compactTo = 2*i + 2
   128  			continue
   129  		}
   130  		r.values[2*i] = value
   131  		contains = true
   132  		break
   133  	}
   134  	if compactTo != -1 {
   135  		r.values = r.values[compactTo:]
   136  	}
   137  	if !contains {
   138  		r.minCanAdded = value
   139  	}
   140  	return contains
   141  }