Ejemplo n.º 1
0
// CopyFrom copies all the persisted results from the originRangeID
// sequence cache into this one. Note that the cache will not be
// locked while copying is in progress. Failures decoding individual
// entries return an error. The copy is done directly using the engine
// instead of interpreting values through MVCC for efficiency.
func (sc *SequenceCache) CopyFrom(e engine.Engine, originRangeID roachpb.RangeID) error {
	originMin := engine.MakeMVCCMetadataKey(
		keys.SequenceCacheKey(originRangeID, txnIDMin, math.MaxUint32, math.MaxUint32))
	originMax := engine.MakeMVCCMetadataKey(
		keys.SequenceCacheKey(originRangeID, txnIDMax, 0, 0))
	return copySeqCache(e, originRangeID, sc.rangeID, originMin, originMax)
}
Ejemplo n.º 2
0
// NewSequenceCache returns a new sequence cache. Every range replica
// maintains a sequence cache, not just the leader.
func NewSequenceCache(rangeID roachpb.RangeID) *SequenceCache {
	return &SequenceCache{
		rangeID: rangeID,
		// The epoch and sequence numbers are encoded in decreasing order.
		min: keys.SequenceCacheKey(rangeID, txnIDMin, math.MaxUint32, math.MaxUint32),
		max: keys.SequenceCacheKey(rangeID, txnIDMax, 0, 0),
	}
}
Ejemplo n.º 3
0
func copySeqCache(e engine.Engine, srcID, dstID roachpb.RangeID, keyMin, keyMax engine.MVCCKey) error {
	var scratch [64]byte
	return e.Iterate(keyMin, keyMax,
		func(kv engine.MVCCKeyValue) (bool, error) {
			// Decode the key into a cmd, skipping on error. Otherwise,
			// write it to the corresponding key in the new cache.
			id, epoch, seq, err := decodeSequenceCacheMVCCKey(kv.Key, scratch[:0])
			if err != nil {
				return false, util.Errorf("could not decode a sequence cache key %s: %s",
					kv.Key, err)
			}
			key := keys.SequenceCacheKey(dstID, id, epoch, seq)
			encKey := engine.MakeMVCCMetadataKey(key)
			// Decode the value, update the checksum and re-encode.
			meta := &engine.MVCCMetadata{}
			if err := proto.Unmarshal(kv.Value, meta); err != nil {
				return false, util.Errorf("could not decode sequence cache value %s [% x]: %s",
					kv.Key, kv.Value, err)
			}
			value := meta.Value()
			value.ClearChecksum()
			value.InitChecksum(key)
			meta.RawBytes = value.RawBytes
			_, _, err = engine.PutProto(e, encKey, meta)
			return false, err
		})
}
// createRangeData creates sample range data in all possible areas of
// the key space. Returns a slice of the encoded keys of all created
// data.
func createRangeData(r *Replica, t *testing.T) []engine.MVCCKey {
	ts0 := roachpb.ZeroTimestamp
	ts := roachpb.Timestamp{WallTime: 1}
	keyTSs := []struct {
		key roachpb.Key
		ts  roachpb.Timestamp
	}{
		{keys.SequenceCacheKey(r.Desc().RangeID, testTxnID, testTxnEpoch, 2), ts0},
		{keys.SequenceCacheKey(r.Desc().RangeID, testTxnID, testTxnEpoch, 1), ts0},
		{keys.RaftHardStateKey(r.Desc().RangeID), ts0},
		{keys.RaftLogKey(r.Desc().RangeID, 1), ts0},
		{keys.RaftLogKey(r.Desc().RangeID, 2), ts0},
		{keys.RangeGCMetadataKey(r.Desc().RangeID), ts0},
		{keys.RangeLastVerificationTimestampKey(r.Desc().RangeID), ts0},
		{keys.RangeStatsKey(r.Desc().RangeID), ts0},
		{keys.RangeDescriptorKey(r.Desc().StartKey), ts},
		{keys.TransactionKey(roachpb.Key(r.Desc().StartKey), []byte("1234")), ts0},
		{keys.TransactionKey(roachpb.Key(r.Desc().StartKey.Next()), []byte("5678")), ts0},
		{keys.TransactionKey(fakePrevKey(r.Desc().EndKey), []byte("2468")), ts0},
		// TODO(bdarnell): KeyMin.Next() results in a key in the reserved system-local space.
		// Once we have resolved https://github.com/cockroachdb/cockroach/issues/437,
		// replace this with something that reliably generates the first valid key in the range.
		//{r.Desc().StartKey.Next(), ts},
		// The following line is similar to StartKey.Next() but adds more to the key to
		// avoid falling into the system-local space.
		{append(append([]byte{}, r.Desc().StartKey...), '\x01'), ts},
		{fakePrevKey(r.Desc().EndKey), ts},
	}

	keys := []engine.MVCCKey{}
	for _, keyTS := range keyTSs {
		if err := engine.MVCCPut(r.store.Engine(), nil, keyTS.key, keyTS.ts, roachpb.MakeValueFromString("value"), nil); err != nil {
			t.Fatal(err)
		}
		keys = append(keys, engine.MVCCEncodeKey(keyTS.key))
		if !keyTS.ts.Equal(ts0) {
			keys = append(keys, engine.MVCCEncodeVersionKey(keyTS.key, keyTS.ts))
		}
	}
	return keys
}
Ejemplo n.º 5
0
// Put writes a sequence number for the specified transaction ID.
func (sc *SequenceCache) Put(e engine.Engine, id []byte, epoch, seq uint32, txnKey roachpb.Key, txnTS roachpb.Timestamp, pErr *roachpb.Error) error {
	if seq <= 0 || len(id) == 0 {
		return errEmptyTxnID
	}
	if !sc.shouldCacheError(pErr) {
		return nil
	}

	// Write the response value to the engine.
	key := keys.SequenceCacheKey(sc.rangeID, id, epoch, seq)
	sc.scratchEntry = roachpb.SequenceCacheEntry{Key: txnKey, Timestamp: txnTS}
	return engine.MVCCPutProto(e, nil /* ms */, key, roachpb.ZeroTimestamp, nil /* txn */, &sc.scratchEntry)
}
Ejemplo n.º 6
0
func TestSequenceCacheEncodeDecode(t *testing.T) {
	defer leaktest.AfterTest(t)
	const rangeID = 123
	const expSeq = 987
	key := keys.SequenceCacheKey(rangeID, testTxnID, expSeq)
	id, seq, err := decodeSequenceCacheKey(key, nil)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(id, testTxnID) {
		t.Fatalf("expected %q, got %q", testTxnID, id)
	}
	if seq != expSeq {
		t.Fatalf("expected %d, got %d", expSeq, seq)
	}
}
Ejemplo n.º 7
0
func TestSequenceCacheEncodeDecode(t *testing.T) {
	defer leaktest.AfterTest(t)
	const rangeID = 123
	const expSeq = 987
	key := keys.SequenceCacheKey(rangeID, testTxnID, testTxnEpoch, expSeq)
	txnID, epoch, seq, err := decodeSequenceCacheKey(key, nil)
	if err != nil {
		t.Fatal(err)
	}
	if !roachpb.TxnIDEqual(txnID, testTxnID) {
		t.Fatalf("expected txnID %q, got %q", testTxnID, txnID)
	}
	if epoch != testTxnEpoch {
		t.Fatalf("expected epoch %d, got %d", testTxnEpoch, epoch)
	}
	if seq != expSeq {
		t.Fatalf("expected sequence %d, got %d", expSeq, seq)
	}
}
Ejemplo n.º 8
0
// Put writes a sequence number for the specified transaction ID.
func (sc *SequenceCache) Put(
	e engine.Engine,
	ms *engine.MVCCStats,
	txnID *uuid.UUID,
	epoch, seq uint32,
	txnKey roachpb.Key,
	txnTS roachpb.Timestamp,
	pErr *roachpb.Error,
) error {
	if seq <= 0 || txnID == nil {
		return errEmptyTxnID
	}
	if !sc.shouldCacheError(pErr) {
		return nil
	}

	// Write the response value to the engine.
	key := keys.SequenceCacheKey(sc.rangeID, txnID, epoch, seq)
	sc.scratchEntry = roachpb.SequenceCacheEntry{Key: txnKey, Timestamp: txnTS}
	return engine.MVCCPutProto(e, ms, key, roachpb.ZeroTimestamp, nil /* txn */, &sc.scratchEntry)
}