// 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) }
// 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 }
// 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 }
// 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 }