* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			157 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 PingCAP, Inc.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package kv
 | |
| 
 | |
| import "github.com/ngaut/log"
 | |
| 
 | |
| // UnionIter is the iterator on an UnionStore.
 | |
| type UnionIter struct {
 | |
| 	dirtyIt    Iterator
 | |
| 	snapshotIt Iterator
 | |
| 
 | |
| 	dirtyValid    bool
 | |
| 	snapshotValid bool
 | |
| 
 | |
| 	curIsDirty bool
 | |
| 	isValid    bool
 | |
| }
 | |
| 
 | |
| func newUnionIter(dirtyIt Iterator, snapshotIt Iterator) *UnionIter {
 | |
| 	it := &UnionIter{
 | |
| 		dirtyIt:       dirtyIt,
 | |
| 		snapshotIt:    snapshotIt,
 | |
| 		dirtyValid:    dirtyIt.Valid(),
 | |
| 		snapshotValid: snapshotIt.Valid(),
 | |
| 	}
 | |
| 	it.updateCur()
 | |
| 	return it
 | |
| }
 | |
| 
 | |
| // Go next and update valid status.
 | |
| func (iter *UnionIter) dirtyNext() {
 | |
| 	iter.dirtyIt.Next()
 | |
| 	iter.dirtyValid = iter.dirtyIt.Valid()
 | |
| }
 | |
| 
 | |
| // Go next and update valid status.
 | |
| func (iter *UnionIter) snapshotNext() {
 | |
| 	iter.snapshotIt.Next()
 | |
| 	iter.snapshotValid = iter.snapshotIt.Valid()
 | |
| }
 | |
| 
 | |
| func (iter *UnionIter) updateCur() {
 | |
| 	iter.isValid = true
 | |
| 	for {
 | |
| 		if !iter.dirtyValid && !iter.snapshotValid {
 | |
| 			iter.isValid = false
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if !iter.dirtyValid {
 | |
| 			iter.curIsDirty = false
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if !iter.snapshotValid {
 | |
| 			iter.curIsDirty = true
 | |
| 			// if delete it
 | |
| 			if len(iter.dirtyIt.Value()) == 0 {
 | |
| 				iter.dirtyNext()
 | |
| 				continue
 | |
| 			}
 | |
| 			break
 | |
| 		}
 | |
| 
 | |
| 		// both valid
 | |
| 		if iter.snapshotValid && iter.dirtyValid {
 | |
| 			snapshotKey := iter.snapshotIt.Key()
 | |
| 			dirtyKey := iter.dirtyIt.Key()
 | |
| 			cmp := dirtyKey.Cmp(snapshotKey)
 | |
| 			// if equal, means both have value
 | |
| 			if cmp == 0 {
 | |
| 				if len(iter.dirtyIt.Value()) == 0 {
 | |
| 					// snapshot has a record, but txn says we have deleted it
 | |
| 					// just go next
 | |
| 					iter.dirtyNext()
 | |
| 					iter.snapshotNext()
 | |
| 					continue
 | |
| 				}
 | |
| 				// both go next
 | |
| 				iter.snapshotNext()
 | |
| 				iter.curIsDirty = true
 | |
| 				break
 | |
| 			} else if cmp > 0 {
 | |
| 				// record from snapshot comes first
 | |
| 				iter.curIsDirty = false
 | |
| 				break
 | |
| 			} else {
 | |
| 				// record from dirty comes first
 | |
| 				if len(iter.dirtyIt.Value()) == 0 {
 | |
| 					log.Warnf("[kv] delete a record not exists? k = %q", iter.dirtyIt.Key())
 | |
| 					// jump over this deletion
 | |
| 					iter.dirtyNext()
 | |
| 					continue
 | |
| 				}
 | |
| 				iter.curIsDirty = true
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Next implements the Iterator Next interface.
 | |
| func (iter *UnionIter) Next() error {
 | |
| 	if !iter.curIsDirty {
 | |
| 		iter.snapshotNext()
 | |
| 	} else {
 | |
| 		iter.dirtyNext()
 | |
| 	}
 | |
| 	iter.updateCur()
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Value implements the Iterator Value interface.
 | |
| // Multi columns
 | |
| func (iter *UnionIter) Value() []byte {
 | |
| 	if !iter.curIsDirty {
 | |
| 		return iter.snapshotIt.Value()
 | |
| 	}
 | |
| 	return iter.dirtyIt.Value()
 | |
| }
 | |
| 
 | |
| // Key implements the Iterator Key interface.
 | |
| func (iter *UnionIter) Key() Key {
 | |
| 	if !iter.curIsDirty {
 | |
| 		return iter.snapshotIt.Key()
 | |
| 	}
 | |
| 	return iter.dirtyIt.Key()
 | |
| }
 | |
| 
 | |
| // Valid implements the Iterator Valid interface.
 | |
| func (iter *UnionIter) Valid() bool {
 | |
| 	return iter.isValid
 | |
| }
 | |
| 
 | |
| // Close implements the Iterator Close interface.
 | |
| func (iter *UnionIter) Close() {
 | |
| 	if iter.snapshotIt != nil {
 | |
| 		iter.snapshotIt.Close()
 | |
| 		iter.snapshotIt = nil
 | |
| 	}
 | |
| 	if iter.dirtyIt != nil {
 | |
| 		iter.dirtyIt.Close()
 | |
| 		iter.dirtyIt = nil
 | |
| 	}
 | |
| }
 |