@@ -39,14 +39,17 @@ var (
3939
4040type columnCache struct {
4141 sync.RWMutex
42- logger * log.MOLogger
43- col AutoColumn
44- cfg Config
45- ranges * ranges
46- allocator valueAllocator
47- allocating bool
48- allocatingC chan error
49- overflow bool
42+ logger * log.MOLogger
43+ col AutoColumn
44+ cfg Config
45+ ranges * ranges
46+ allocator valueAllocator
47+ allocating bool
48+ allocatingC chan error
49+ overflow bool
50+ terminal bool
51+ terminalValue uint64
52+ terminalTS timestamp.Timestamp
5053 // For the load scenario, if the machine is good enough, there will be very many goroutines to
5154 // concurrently fetch the value of the self-increasing column, which will immediately trigger
5255 // the cache of the self-increasing column to be insufficient and thus go to the store to allocate
@@ -94,7 +97,13 @@ func (col *columnCache) current(ctx context.Context) (uint64, error) {
9497 if err := col .waitPrevAllocatingLocked (ctx ); err != nil {
9598 return 0 , err
9699 }
97- return col .ranges .current (), nil
100+ if v := col .ranges .current (); v != 0 {
101+ return v , nil
102+ }
103+ if col .terminal {
104+ return col .terminalValue , nil
105+ }
106+ return 0 , nil
98107}
99108
100109func (col * columnCache ) insertAutoValues (
@@ -271,8 +280,18 @@ func (col *columnCache) updateTo(
271280 col .Lock ()
272281
273282 contains := col .ranges .updateTo (manualValue )
283+ if col .terminal && manualValue >= col .terminalValue {
284+ col .terminal = false
285+ col .terminalValue = 0
286+ col .terminalTS = timestamp.Timestamp {}
287+ col .overflow = true
288+ contains = true
289+ }
274290 // mark col next() is overflow
275291 if manualValue == math .MaxUint64 {
292+ col .terminal = false
293+ col .terminalValue = 0
294+ col .terminalTS = timestamp.Timestamp {}
276295 col .overflow = true
277296 }
278297 col .Unlock ()
@@ -311,7 +330,7 @@ func (col *columnCache) applyAutoValues(
311330 return true , nil
312331 }
313332
314- if col .ranges .empty () {
333+ if col .ranges .empty () && ! col . terminal {
315334 if err := col .allocateLocked (ctx , tableID , rows , cul , txnOp ); err != nil {
316335 return false , err
317336 }
@@ -336,7 +355,15 @@ func (col *columnCache) applyAutoValues(
336355 if overflow {
337356 return apply (i , 0 )
338357 }
339- if err := apply (i , col .ranges .next ()); err != nil {
358+ value := col .ranges .next ()
359+ if value == 0 && col .terminal {
360+ value = col .terminalValue
361+ col .terminal = false
362+ col .terminalValue = 0
363+ col .terminalTS = timestamp.Timestamp {}
364+ col .overflow = true
365+ }
366+ if err := apply (i , value ); err != nil {
340367 return err
341368 }
342369 }
@@ -354,7 +381,7 @@ func (col *columnCache) preAllocate(
354381 return
355382 }
356383
357- if col .ranges .left () >= count {
384+ if col .ranges .left () >= count || col . terminal {
358385 return
359386 }
360387
@@ -435,7 +462,7 @@ func (col *columnCache) allocateLocked(
435462func (col * columnCache ) maybeAllocate (ctx context.Context , tableID uint64 , txnOp client.TxnOperator ) error {
436463 col .Lock ()
437464 committed := col .committed
438- low := col .ranges .left () <= col .cfg .LowCapacity
465+ low := col .ranges .left () <= col .cfg .LowCapacity && ! col . terminal
439466 retired := col .retired
440467 col .Unlock ()
441468 if low && committed && ! retired {
@@ -480,13 +507,30 @@ func (col *columnCache) applyAllocateLocked(
480507 }
481508 }
482509
483- if to > from {
510+ // A wrapped exclusive upper bound means the allocation reached the end of
511+ // uint64. Keep its final value separately because max+step is not representable.
512+ if to < from {
513+ terminalValue := to - col .col .Step
514+ if from < terminalValue {
515+ col .ranges .addWithTimestamp (from , terminalValue , allocateAt )
516+ }
517+ col .terminal = true
518+ col .terminalValue = terminalValue
519+ col .terminalTS = allocateAt
520+ } else if to > from {
484521 col .ranges .addWithTimestamp (from , to , allocateAt )
485522 }
486523 close (col .allocatingC )
487524 col .allocating = false
488525}
489526
527+ func (col * columnCache ) oldestAllocateAtLocked () timestamp.Timestamp {
528+ if ! col .ranges .empty () {
529+ return col .ranges .oldestAllocateAt ()
530+ }
531+ return col .terminalTS
532+ }
533+
490534func (col * columnCache ) waitPrevAllocatingLocked (ctx context.Context ) error {
491535 for {
492536 if ! col .allocating {
0 commit comments