Beispiel #1
0
// getInternal implements the actual logic of get function.
// The values of multiple versions for the given key should
// be organized as follows:
// ...
// keyA : keyMetatata of keyA
// keyA_Timestamp_n : value of version_n
// keyA_Timestamp_n-1 : value of version_n-1
// ...
// keyA_Timestamp_0 : value of version_0
// keyB : keyMetadata of keyB
// ...
func (mvcc *MVCC) getInternal(key Key, timestamp hlc.HLTimestamp, txnID string) ([]byte, hlc.HLTimestamp, string, error) {
	keyMetadata := &keyMetadata{}
	ok, err := GetI(mvcc.engine, key, keyMetadata)
	if err != nil || !ok {
		return nil, hlc.HLTimestamp{}, "", err
	}

	// If the read timestamp is greater than the latest one, we can just
	// fetch the value without a scan.
	if !timestamp.Less(keyMetadata.Timestamp) {
		if len(keyMetadata.TxnID) > 0 && (len(txnID) == 0 || keyMetadata.TxnID != txnID) {
			return nil, hlc.HLTimestamp{}, "", &writeIntentError{TxnID: keyMetadata.TxnID}
		}

		latestKey := mvccEncodeKey(key, keyMetadata.Timestamp)
		val, err := mvcc.engine.Get(latestKey)
		return val, keyMetadata.Timestamp, keyMetadata.TxnID, err
	}

	nextKey := mvccEncodeKey(key, timestamp)
	// We use the PrefixEndKey(key) as the upper bound for scan.
	// If there is no other version after nextKey, it won't return
	// the value of the next key.
	kvs, err := mvcc.engine.Scan(nextKey, PrefixEndKey(key), 1)
	if len(kvs) > 0 {
		_, ts := mvccDecodeKey(kvs[0].Key)
		return kvs[0].Value, ts, "", err
	}
	return nil, hlc.HLTimestamp{}, "", err
}