github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/snapshot_iterator.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 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 storage 16 17 import ( 18 "bytes" 19 "sync" 20 21 "github.com/cenkalti/backoff" 22 "github.com/cockroachdb/pebble" 23 "github.com/vescale/zgraph/storage/kv" 24 "github.com/vescale/zgraph/storage/mvcc" 25 "github.com/vescale/zgraph/storage/resolver" 26 ) 27 28 // SnapshotIter represents a iterator which provides a consistent view of key/value store. 29 type SnapshotIter struct { 30 db *pebble.DB 31 vp kv.VersionProvider 32 ver kv.Version 33 inner *pebble.Iterator 34 resolver *resolver.Scheduler 35 mu struct { 36 sync.RWMutex 37 resolved []kv.Version 38 } 39 40 // Iterator states 41 valid bool 42 reverse bool 43 key kv.Key 44 val []byte 45 nextKey kv.Key 46 47 // Only for reverse iterator 48 entry mvcc.Entry 49 } 50 51 // Valid implements the Iterator interface. 52 func (i *SnapshotIter) Valid() bool { 53 return i.valid 54 } 55 56 // Key implements the Iterator interface. 57 func (i *SnapshotIter) Key() kv.Key { 58 return i.key 59 } 60 61 // Value implements the Iterator interface. 62 func (i *SnapshotIter) Value() []byte { 63 return i.val 64 } 65 66 // Next implements the Iterator interface. 67 func (i *SnapshotIter) Next() error { 68 err := backoff.RetryNotify(func() error { 69 i.valid = i.inner.Valid() 70 if !i.valid { 71 return nil 72 } 73 74 var err error 75 if i.reverse { 76 err = i.reverseNext() 77 } else { 78 err = i.next() 79 } 80 81 if err != nil { 82 lockedErr, ok := err.(*mvcc.LockedError) 83 if !ok { 84 return err 85 } 86 // Try to resolve lock 87 status, err := resolver.CheckTxnStatus(i.db, i.vp, lockedErr.Primary, lockedErr.StartVer) 88 if err != nil { 89 return &backoff.PermanentError{Err: err} 90 } 91 switch status.Action { 92 case resolver.TxnActionNone: 93 // Transaction is still alive and try it letter. 94 err = resolver.ErrRetryable("txn still alive") 95 96 case resolver.TxnActionTTLExpireRollback, 97 resolver.TxnActionLockNotExistRollback: 98 // Resolve the current key. 99 i.resolver.Resolve([]kv.Key{lockedErr.Key}, lockedErr.StartVer, 0, nil) 100 // Put the resolve transaction into the resolved list to make the 101 // subsequent request bypass them. 102 i.mu.Lock() 103 i.mu.resolved = append(i.mu.resolved, lockedErr.StartVer) 104 i.mu.Unlock() 105 err = resolver.ErrRetryable("bypass rollback transaction") 106 107 default: 108 // TxnActionLockNotExistDoNothing 109 // Transaction committed: we try to resolve the current key and backoff. 110 i.resolver.Resolve([]kv.Key{lockedErr.Key}, lockedErr.StartVer, status.CommitVer, nil) 111 err = resolver.ErrRetryable("resolving committed transaction") 112 } 113 114 // We must make the iterator point to the correct key. 115 i.resetIter() 116 return err 117 } 118 119 return nil 120 }, expoBackoff(), BackoffErrReporter("SnapshotIter.Next")) 121 122 return err 123 } 124 125 func (i *SnapshotIter) resetIter() { 126 lowerBound, upperBound := i.inner.RangeBounds() 127 if i.reverse { 128 iter := i.db.NewIter(&pebble.IterOptions{ 129 LowerBound: lowerBound, 130 UpperBound: i.nextKey.PrefixNext(), 131 }) 132 iter.Last() 133 i.inner = iter 134 } else { 135 iter := i.db.NewIter(&pebble.IterOptions{ 136 LowerBound: mvcc.LockKey(i.nextKey), 137 UpperBound: upperBound, 138 }) 139 iter.First() 140 i.inner = iter 141 } 142 } 143 144 // Close implements the Iterator interface. 145 func (i *SnapshotIter) Close() { 146 _ = i.inner.Close() 147 } 148 149 func (i *SnapshotIter) next() error { 150 for hasNext := true; hasNext; { 151 i.mu.RLock() 152 resolved := i.mu.resolved 153 i.mu.RUnlock() 154 val, err := getValue(i.inner, i.nextKey, i.ver, resolved) 155 if err != nil { 156 return err 157 } 158 159 // We cannot early return here because we must skip the remained 160 // versions and set the next key properly. 161 if val != nil { 162 i.key = i.nextKey 163 i.val = val 164 } 165 166 // Skip the remained multiple versions if we found a valid value. 167 // Or seek to the next valid key. 168 skip := mvcc.SkipDecoder{CurrKey: i.nextKey} 169 hasNext, err = skip.Decode(i.inner) 170 if err != nil { 171 return err 172 } 173 i.nextKey = skip.CurrKey 174 175 // Early return if we found a valid value. 176 if val != nil { 177 return nil 178 } 179 } 180 181 // This position means we didn't find a valid value in the above loop. 182 // We should set the valid flag into false to avoid the caller read 183 // previous key/value. 184 i.valid = false 185 186 return nil 187 } 188 189 func (i *SnapshotIter) reverseNext() error { 190 for hasPrev := true; hasPrev; { 191 key, ver, err := mvcc.Decode(i.inner.Key()) 192 if err != nil { 193 return err 194 } 195 if !bytes.Equal(key, i.nextKey) { 196 err := i.finishEntry() 197 if err != nil { 198 return err 199 } 200 i.key = i.nextKey 201 i.nextKey = key 202 203 // Early return if we found a valid value. The SnapshotReverseIter will 204 // continue to decode the next different key because the inner iterator 205 // had pointed to next different key. 206 if len(i.val) > 0 { 207 return nil 208 } 209 } 210 val, err := i.inner.ValueAndErr() 211 if err != nil { 212 return err 213 } 214 if ver == mvcc.LockVer { 215 var lock mvcc.Lock 216 err = lock.UnmarshalBinary(val) 217 } else { 218 var value mvcc.Value 219 err = value.UnmarshalBinary(val) 220 i.entry.Values = append(i.entry.Values, value) 221 } 222 if err != nil { 223 return err 224 } 225 hasPrev = i.inner.Prev() 226 227 // Set the key/value to properly value if there is no previous key/value. 228 if !hasPrev { 229 err := i.finishEntry() 230 if err != nil { 231 return err 232 } 233 i.key = i.nextKey 234 } 235 } 236 237 // This position means there is no previous key in the specified range of iterator. 238 // The `finishEntry` method always was called even there is no previous key remained 239 // because there maybe some old versions are stored in `entry.values`. 240 // The i.val nil means we didn't find any valid data for the current key. So, we 241 // should set the valid flag into false to avoid the caller read previous key/value. 242 if len(i.val) == 0 { 243 i.valid = false 244 } 245 246 return nil 247 } 248 249 func reverse(values []mvcc.Value) { 250 i, j := 0, len(values)-1 251 for i < j { 252 values[i], values[j] = values[j], values[i] 253 i++ 254 j-- 255 } 256 } 257 258 func (i *SnapshotIter) finishEntry() error { 259 if i.entry.Lock != nil { 260 return i.entry.Lock.LockErr(i.nextKey) 261 } 262 263 reverse(i.entry.Values) 264 i.entry.Key = mvcc.NewKey(i.nextKey) 265 val, err := i.entry.Get(i.ver, nil) 266 if err != nil { 267 return err 268 } 269 i.val = val 270 i.entry = mvcc.Entry{} 271 return nil 272 }