Example #1
0
// Increment fetches the value for key, and assuming the value is an
// "integer" type, increments it by inc and stores the new value. The
// newly incremented value is returned.
func (mvcc *MVCC) Increment(key Key, timestamp proto.Timestamp, txn *proto.Transaction, inc int64) (int64, error) {
	// Handle check for non-existence of key. In order to detect
	// the potential write intent by another concurrent transaction
	// with a newer timestamp, we need to use the max timestamp
	// while reading.
	value, err := mvcc.Get(key, proto.MaxTimestamp, txn)
	if err != nil {
		return 0, err
	}

	var int64Val int64
	// If the value exists, verify it's an integer type not a byte slice.
	if value != nil {
		if value.Bytes != nil || value.Integer == nil {
			return 0, util.Errorf("cannot increment key %q which already has a generic byte value: %+v", key, *value)
		}
		int64Val = value.GetInteger()
	}

	// Check for overflow and underflow.
	if encoding.WillOverflow(int64Val, inc) {
		return 0, util.Errorf("key %q with value %d incremented by %d results in overflow", key, int64Val, inc)
	}

	if inc == 0 {
		return int64Val, nil
	}

	r := int64Val + inc
	value = &proto.Value{Integer: gogoproto.Int64(r)}
	value.InitChecksum(key)
	return r, mvcc.Put(key, timestamp, *value, txn)
}
Example #2
0
// Merge updates the value of this Counter with the supplied
// update and returns an error in case of an integer overflow.
func (n Counter) Merge(o Mergable) (Mergable, error) {
	m, ok := o.(Counter)
	if !ok {
		return n, util.Error("parameter is of wrong type")
	}
	if encoding.WillOverflow(int64(n), int64(m)) {
		return n, util.Errorf("merge error: %d + %d overflows", n, m)
	}
	result := Counter(n + m)
	return result, nil
}
Example #3
0
// Increment fetches the varint encoded int64 value specified by key
// and adds "inc" to it then re-encodes as varint. The newly incremented
// value is returned.
func (mvcc *MVCC) Increment(key Key, timestamp proto.Timestamp, txnID []byte, inc int64) (int64, error) {
	// Handle check for non-existence of key. In order to detect
	// the potential write intent by another concurrent transaction
	// with a newer timestamp, we need to use the max timestamp
	// while reading.
	val, err := mvcc.Get(key, proto.MaxTimestamp, txnID)
	if err != nil {
		return 0, err
	}

	var int64Val int64
	// If the value exists, attempt to decode it as a varint.
	if len(val.Bytes) != 0 {
		decoded, err := encoding.Decode(key, val.Bytes)
		if err != nil {
			return 0, err
		}
		if _, ok := decoded.(int64); !ok {
			return 0, util.Errorf("received value of wrong type %v", reflect.TypeOf(decoded))
		}
		int64Val = decoded.(int64)
	}

	// Check for overflow and underflow.
	if encoding.WillOverflow(int64Val, inc) {
		return 0, util.Errorf("key %q with value %d incremented by %d results in overflow", key, int64Val, inc)
	}

	if inc == 0 {
		return int64Val, nil
	}

	r := int64Val + inc
	encoded, err := encoding.Encode(key, r)
	if err != nil {
		return 0, util.Errorf("error encoding %d", r)
	}

	err = mvcc.Put(key, timestamp, proto.Value{Bytes: encoded, Timestamp: timestamp}, txnID)
	if err != nil {
		return 0, err
	}
	return r, nil
}
Example #4
0
// Increment fetches the varint encoded int64 value specified by key
// and adds "inc" to it then re-encodes as varint. The newly incremented
// value is returned.
func Increment(engine Engine, key Key, inc int64) (int64, error) {
	// First retrieve existing value.
	val, err := engine.Get(key)
	if err != nil {
		return 0, err
	}
	var int64Val int64
	// If the value exists, attempt to decode it as a varint.
	if len(val) != 0 {
		decoded, err := encoding.Decode(key, val)
		if err != nil {
			return 0, err
		}
		if _, ok := decoded.(int64); !ok {
			return 0, util.Errorf("received value of wrong type %v", reflect.TypeOf(decoded))
		}
		int64Val = decoded.(int64)
	}

	// Check for overflow and underflow.
	if encoding.WillOverflow(int64Val, inc) {
		return 0, util.Errorf("key %q with value %d incremented by %d results in overflow", key, int64Val, inc)
	}

	if inc == 0 {
		return int64Val, nil
	}

	r := int64Val + inc
	encoded, err := encoding.Encode(key, r)
	if err != nil {
		return 0, util.Errorf("error encoding %d", r)
	}
	if err = engine.Put(key, encoded); err != nil {
		return 0, err
	}
	return r, nil
}