github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/kv/union_iter.go (about)

     1  // Copyright 2015 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 kv
    15  
    16  import "github.com/insionng/yougam/libraries/ngaut/log"
    17  
    18  // UnionIter is the iterator on an UnionStore.
    19  type UnionIter struct {
    20  	dirtyIt    Iterator
    21  	snapshotIt Iterator
    22  
    23  	dirtyValid    bool
    24  	snapshotValid bool
    25  
    26  	curIsDirty bool
    27  	isValid    bool
    28  	reverse    bool
    29  }
    30  
    31  func newUnionIter(dirtyIt Iterator, snapshotIt Iterator, reverse bool) *UnionIter {
    32  	it := &UnionIter{
    33  		dirtyIt:       dirtyIt,
    34  		snapshotIt:    snapshotIt,
    35  		dirtyValid:    dirtyIt.Valid(),
    36  		snapshotValid: snapshotIt.Valid(),
    37  		reverse:       reverse,
    38  	}
    39  	it.updateCur()
    40  	return it
    41  }
    42  
    43  // Go next and update valid status.
    44  func (iter *UnionIter) dirtyNext() {
    45  	iter.dirtyIt.Next()
    46  	iter.dirtyValid = iter.dirtyIt.Valid()
    47  }
    48  
    49  // Go next and update valid status.
    50  func (iter *UnionIter) snapshotNext() {
    51  	iter.snapshotIt.Next()
    52  	iter.snapshotValid = iter.snapshotIt.Valid()
    53  }
    54  
    55  func (iter *UnionIter) updateCur() {
    56  	iter.isValid = true
    57  	for {
    58  		if !iter.dirtyValid && !iter.snapshotValid {
    59  			iter.isValid = false
    60  			return
    61  		}
    62  
    63  		if !iter.dirtyValid {
    64  			iter.curIsDirty = false
    65  			return
    66  		}
    67  
    68  		if !iter.snapshotValid {
    69  			iter.curIsDirty = true
    70  			// if delete it
    71  			if len(iter.dirtyIt.Value()) == 0 {
    72  				iter.dirtyNext()
    73  				continue
    74  			}
    75  			break
    76  		}
    77  
    78  		// both valid
    79  		if iter.snapshotValid && iter.dirtyValid {
    80  			snapshotKey := iter.snapshotIt.Key()
    81  			dirtyKey := iter.dirtyIt.Key()
    82  			cmp := dirtyKey.Cmp(snapshotKey)
    83  			if iter.reverse {
    84  				cmp = -cmp
    85  			}
    86  			// if equal, means both have value
    87  			if cmp == 0 {
    88  				if len(iter.dirtyIt.Value()) == 0 {
    89  					// snapshot has a record, but txn says we have deleted it
    90  					// just go next
    91  					iter.dirtyNext()
    92  					iter.snapshotNext()
    93  					continue
    94  				}
    95  				// both go next
    96  				iter.snapshotNext()
    97  				iter.curIsDirty = true
    98  				break
    99  			} else if cmp > 0 {
   100  				// record from snapshot comes first
   101  				iter.curIsDirty = false
   102  				break
   103  			} else {
   104  				// record from dirty comes first
   105  				if len(iter.dirtyIt.Value()) == 0 {
   106  					log.Warnf("[kv] delete a record not exists? k = %q", iter.dirtyIt.Key())
   107  					// jump over this deletion
   108  					iter.dirtyNext()
   109  					continue
   110  				}
   111  				iter.curIsDirty = true
   112  				break
   113  			}
   114  		}
   115  	}
   116  }
   117  
   118  // Next implements the Iterator Next interface.
   119  func (iter *UnionIter) Next() error {
   120  	if !iter.curIsDirty {
   121  		iter.snapshotNext()
   122  	} else {
   123  		iter.dirtyNext()
   124  	}
   125  	iter.updateCur()
   126  	return nil
   127  }
   128  
   129  // Value implements the Iterator Value interface.
   130  // Multi columns
   131  func (iter *UnionIter) Value() []byte {
   132  	if !iter.curIsDirty {
   133  		return iter.snapshotIt.Value()
   134  	}
   135  	return iter.dirtyIt.Value()
   136  }
   137  
   138  // Key implements the Iterator Key interface.
   139  func (iter *UnionIter) Key() Key {
   140  	if !iter.curIsDirty {
   141  		return iter.snapshotIt.Key()
   142  	}
   143  	return iter.dirtyIt.Key()
   144  }
   145  
   146  // Valid implements the Iterator Valid interface.
   147  func (iter *UnionIter) Valid() bool {
   148  	return iter.isValid
   149  }
   150  
   151  // Close implements the Iterator Close interface.
   152  func (iter *UnionIter) Close() {
   153  	if iter.snapshotIt != nil {
   154  		iter.snapshotIt.Close()
   155  		iter.snapshotIt = nil
   156  	}
   157  	if iter.dirtyIt != nil {
   158  		iter.dirtyIt.Close()
   159  		iter.dirtyIt = nil
   160  	}
   161  }