pub fn read_next(&mut self) -> Result<Option<TxnEntry>> {
        if !self.is_started {
            if self.lower_bound.is_some() {
                // TODO: `seek_to_first` is better, however it has performance issues currently.
                self.write_cursor.seek(
                    self.lower_bound.as_ref().unwrap(),
                    &mut self.statistics.write,
                )?;
                self.lock_cursor.seek(
                    self.lower_bound.as_ref().unwrap(),
                    &mut self.statistics.lock,
                )?;
            } else {
                self.write_cursor.seek_to_first(&mut self.statistics.write);
                self.lock_cursor.seek_to_first(&mut self.statistics.lock);
            }
            self.is_started = true;
        }

        // The general idea is to simultaneously step write cursor and lock cursor.

        // TODO: We don't need to seek lock CF if isolation level is RC.

        loop {
            // The overall implementation is the same as forward scanner.
            let (current_user_key, has_write, has_lock) = {
                let w_key = if self.write_cursor.valid()? {
                    Some(self.write_cursor.key(&mut self.statistics.write))
                } else {
                    None
                };
                let l_key = if self.lock_cursor.valid()? {
                    Some(self.lock_cursor.key(&mut self.statistics.lock))
                } else {
                    None
                };

                // `res` is `(current_user_key_slice, has_write, has_lock)`
                let res = match (w_key, l_key) {
                    (None, None) => {
                        // Both cursors yield `None`: we know that there is nothing remaining.
                        return Ok(None);
                    }
                    (None, Some(k)) => {
                        // Write cursor yields `None` but lock cursor yields something:
                        // In RC, it means we got nothing.
                        // In SI, we need to check if the lock will cause conflict.
                        (k, false, true)
                    }
                    (Some(k), None) => {
                        // Write cursor yields something but lock cursor yields `None`:
                        // We need to further step write cursor to our desired version
                        (Key::truncate_ts_for(k)?, true, false)
                    }
                    (Some(wk), Some(lk)) => {
                        let write_user_key = Key::truncate_ts_for(wk)?;
                        match write_user_key.cmp(lk) {
                            Ordering::Less => {
                                // Write cursor user key < lock cursor, it means the lock of the
                                // current key that write cursor is pointing to does not exist.
                                (write_user_key, true, false)
                            }
                            Ordering::Greater => {
                                // Write cursor user key > lock cursor, it means we got a lock of a
                                // key that does not have a write. In SI, we need to check if the
                                // lock will cause conflict.
                                (lk, false, true)
                            }
                            Ordering::Equal => {
                                // Write cursor user key == lock cursor, it means the lock of the
                                // current key that write cursor is pointing to *exists*.
                                (lk, true, true)
                            }
                        }
                    }
                };

                // Use `from_encoded_slice` to reserve space for ts, so later we can append ts to
                // the key or its clones without reallocation.
                (Key::from_encoded_slice(res.0), res.1, res.2)
            };

            // `result` stores intermediate values, including KeyLocked errors (but not other kind
            // of errors). If there is KeyLocked errors, we should be able to continue scanning.
            let mut result = Ok(None);

            // `met_next_user_key` stores whether the write cursor has been already pointing to
            // the next user key. If so, we don't need to compare it again when trying to step
            // to the next user key later.
            let mut met_next_user_key = false;

            let ts = self.cfg.ts;

            if has_lock {
                match self.cfg.isolation_level {
                    IsolationLevel::Si => {
                        // Only needs to check lock in SI
                        let lock = {
                            let lock_value = self.lock_cursor.value(&mut self.statistics.lock);
                            Lock::parse(lock_value)?
                        };
                        // TODO: We need to scan locks into batch
                        //       in the future.
                        result = super::super::util::check_lock(&current_user_key, ts, &lock)
                            .map(|_| None);
                    }
                    IsolationLevel::Rc => {}
                }
                self.lock_cursor.next(&mut self.statistics.lock);
            }
            if has_write {
                // We don't need to read version if there is a lock error already.
                if result.is_ok() {
                    // Attempt to read specified version of the key. Note that we may get `None`
                    // indicating that no desired version is found, or a DELETE version is found
                    result = self.get(&current_user_key, ts, &mut met_next_user_key);
                }
                // Even if there is a lock error, we still need to step the cursor for future
                // calls. However if we are already pointing at next user key, we don't need to
                // move it any more. `met_next_user_key` eliminates a key compare.
                if !met_next_user_key {
                    self.move_write_cursor_to_next_user_key(&current_user_key)?;
                }
            }

            // If we got something, it can be just used as the return value. Otherwise, we need
            // to continue stepping the cursor.
            if let Some(v) = result? {
                return Ok(Some(v));
            }
        }
    }
/// Get the next txn entry, in forward order.
Get the next txn entry, in forward order.
Get the next txn entry in forward order .
pub fn read_next(&mut self) -> Result<Option<TxnEntry>> {
        if !self.is_started {
            if self.lower_bound.is_some() {
                // TODO: `seek_to_first` is better, however it has performance issues currently.
                self.write_cursor.seek(
                    self.lower_bound.as_ref().unwrap(),
                    &mut self.statistics.write,
                )?;
                self.lock_cursor.seek(
                    self.lower_bound.as_ref().unwrap(),
                    &mut self.statistics.lock,
                )?;
            } else {
                self.write_cursor.seek_to_first(&mut self.statistics.write);
                self.lock_cursor.seek_to_first(&mut self.statistics.lock);
            }
            self.is_started = true;
        }
        // The general idea is to simultaneously step write cursor and lock cursor.
        // TODO: We don't need to seek lock CF if isolation level is RC.
        loop {
            // The overall implementation is the same as forward scanner.
            let (current_user_key, has_write, has_lock) = {
                let w_key = if self.write_cursor.valid()? {
                    Some(self.write_cursor.key(&mut self.statistics.write))
                } else {
                    None
                };
                let l_key = if self.lock_cursor.valid()? {
                    Some(self.lock_cursor.key(&mut self.statistics.lock))
                } else {
                    None
                };
                // `res` is `(current_user_key_slice, has_write, has_lock)`
                let res = match (w_key, l_key) {
                    (None, None) => {
                        // Both cursors yield `None`: we know that there is nothing remaining.
                        return Ok(None);
                    }
                    (None, Some(k)) => {
                        // Write cursor yields `None` but lock cursor yields something:
                        // In RC, it means we got nothing.
                        // In SI, we need to check if the lock will cause conflict.
                        (k, false, true)
                    }
                    (Some(k), None) => {
                        // Write cursor yields something but lock cursor yields `None`:
                        // We need to further step write cursor to our desired version
                        (Key::truncate_ts_for(k)?, true, false)
                    }
                    (Some(wk), Some(lk)) => {
                        let write_user_key = Key::truncate_ts_for(wk)?;
                        match write_user_key.cmp(lk) {
                            Ordering::Less => {
                                // Write cursor user key < lock cursor, it means the lock of the
                                // current key that write cursor is pointing to does not exist.
                                (write_user_key, true, false)
                            }
                            Ordering::Greater => {
                                // Write cursor user key > lock cursor, it means we got a lock of a
                                // key that does not have a write. In SI, we need to check if the
                                // lock will cause conflict.
                                (lk, false, true)
                            }
                            Ordering::Equal => {
                                // Write cursor user key == lock cursor, it means the lock of the
                                // current key that write cursor is pointing to *exists*.
                                (lk, true, true)
                            }
                        }
                    }
                };
                // Use `from_encoded_slice` to reserve space for ts, so later we can append ts to
                // the key or its clones without reallocation.
                (Key::from_encoded_slice(res.0), res.1, res.2)
            };
            // `result` stores intermediate values, including KeyLocked errors (but not other kind
            // of errors). If there is KeyLocked errors, we should be able to continue scanning.
            let mut result = Ok(None);
            // `met_next_user_key` stores whether the write cursor has been already pointing to
            // the next user key. If so, we don't need to compare it again when trying to step
            // to the next user key later.
            let mut met_next_user_key = false;
            let ts = self.cfg.ts;
            if has_lock {
                match self.cfg.isolation_level {
                    IsolationLevel::Si => {
                        // Only needs to check lock in SI
                        let lock = {
                            let lock_value = self.lock_cursor.value(&mut self.statistics.lock);
                            Lock::parse(lock_value)?
                        };
                        // TODO: We need to scan locks into batch
                        //       in the future.
                        result = super::super::util::check_lock(&current_user_key, ts, &lock)
                            .map(|_| None);
                    }
                    IsolationLevel::Rc => {}
                }
                self.lock_cursor.next(&mut self.statistics.lock);
            }
            if has_write {
                // We don't need to read version if there is a lock error already.
                if result.is_ok() {
                    // Attempt to read specified version of the key. Note that we may get `None`
                    // indicating that no desired version is found, or a DELETE version is found
                    result = self.get(&current_user_key, ts, &mut met_next_user_key);
                }
                // Even if there is a lock error, we still need to step the cursor for future
                // calls. However if we are already pointing at next user key, we don't need to
                // move it any more. `met_next_user_key` eliminates a key compare.
                if !met_next_user_key {
                    self.move_write_cursor_to_next_user_key(&current_user_key)?;
                }
            }
            // If we got something, it can be just used as the return value. Otherwise, we need
            // to continue stepping the cursor.
            if let Some(v) = result? {
                return Ok(Some(v));
            }
        }
    }
pub fn read_next ( & mut self ) -> Result < Option < TxnEntry > > { if ! self . is_started { if self . lower_bound . is_some ( ) { // TODO: `seek_to_first` is better, however it has performance issues currently. self . write_cursor . seek ( self . lower_bound . as_ref ( ) . unwrap ( ) , & mut self . statistics . write , ) ? ; self . lock_cursor . seek ( self . lower_bound . as_ref ( ) . unwrap ( ) , & mut self . statistics . lock , ) ? ; } else { self . write_cursor . seek_to_first ( & mut self . statistics . write ) ; self . lock_cursor . seek_to_first ( & mut self . statistics . lock ) ; } self . is_started = true ; } // The general idea is to simultaneously step write cursor and lock cursor. // TODO: We don't need to seek lock CF if isolation level is RC. loop { // The overall implementation is the same as forward scanner. let ( current_user_key , has_write , has_lock ) = { let w_key = if self . write_cursor . valid ( ) ? { Some ( self . write_cursor . key ( & mut self . statistics . write ) ) } else { None } ; let l_key = if self . lock_cursor . valid ( ) ? { Some ( self . lock_cursor . key ( & mut self . statistics . lock ) ) } else { None } ; // `res` is `(current_user_key_slice, has_write, has_lock)` let res = match ( w_key , l_key ) { ( None , None ) => { // Both cursors yield `None`: we know that there is nothing remaining. return Ok ( None ) ; } ( None , Some ( k ) ) => { // Write cursor yields `None` but lock cursor yields something: // In RC, it means we got nothing. // In SI, we need to check if the lock will cause conflict. ( k , false , true ) } ( Some ( k ) , None ) => { // Write cursor yields something but lock cursor yields `None`: // We need to further step write cursor to our desired version ( Key :: truncate_ts_for ( k ) ? , true , false ) } ( Some ( wk ) , Some ( lk ) ) => { let write_user_key = Key :: truncate_ts_for ( wk ) ? ; match write_user_key . cmp ( lk ) { Ordering :: Less => { // Write cursor user key < lock cursor, it means the lock of the // current key that write cursor is pointing to does not exist. ( write_user_key , true , false ) } Ordering :: Greater => { // Write cursor user key > lock cursor, it means we got a lock of a // key that does not have a write. In SI, we need to check if the // lock will cause conflict. ( lk , false , true ) } Ordering :: Equal => { // Write cursor user key == lock cursor, it means the lock of the // current key that write cursor is pointing to *exists*. ( lk , true , true ) } } } } ; // Use `from_encoded_slice` to reserve space for ts, so later we can append ts to // the key or its clones without reallocation. ( Key :: from_encoded_slice ( res . 0 ) , res . 1 , res . 2 ) } ; // `result` stores intermediate values, including KeyLocked errors (but not other kind // of errors). If there is KeyLocked errors, we should be able to continue scanning. let mut result = Ok ( None ) ; // `met_next_user_key` stores whether the write cursor has been already pointing to // the next user key. If so, we don't need to compare it again when trying to step // to the next user key later. let mut met_next_user_key = false ; let ts = self . cfg . ts ; if has_lock { match self . cfg . isolation_level { IsolationLevel :: Si => { // Only needs to check lock in SI let lock = { let lock_value = self . lock_cursor . value ( & mut self . statistics . lock ) ; Lock :: parse ( lock_value ) ? } ; // TODO: We need to scan locks into batch //       in the future. result = super :: super :: util :: check_lock ( & current_user_key , ts , & lock ) . map ( | _ | None ) ; } IsolationLevel :: Rc => { } } self . lock_cursor . next ( & mut self . statistics . lock ) ; } if has_write { // We don't need to read version if there is a lock error already. if result . is_ok ( ) { // Attempt to read specified version of the key. Note that we may get `None` // indicating that no desired version is found, or a DELETE version is found result = self . get ( & current_user_key , ts , & mut met_next_user_key ) ; } // Even if there is a lock error, we still need to step the cursor for future // calls. However if we are already pointing at next user key, we don't need to // move it any more. `met_next_user_key` eliminates a key compare. if ! met_next_user_key { self . move_write_cursor_to_next_user_key ( & current_user_key ) ? ; } } // If we got something, it can be just used as the return value. Otherwise, we need // to continue stepping the cursor. if let Some ( v ) = result ? { return Ok ( Some ( v ) ) ; } } }
Get the next txn entry, in forward order.
Get the next txn entry in forward order .
&mut self
&mut self