1// Copyright 2016 The etcd Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package clientv3 16 17import ( 18 pb "go.etcd.io/etcd/api/v3/etcdserverpb" 19) 20 21type CompareTarget int 22type CompareResult int 23 24const ( 25 CompareVersion CompareTarget = iota 26 CompareCreated 27 CompareModified 28 CompareValue 29) 30 31type Cmp pb.Compare 32 33func Compare(cmp Cmp, result string, v interface{}) Cmp { 34 var r pb.Compare_CompareResult 35 36 switch result { 37 case "=": 38 r = pb.Compare_EQUAL 39 case "!=": 40 r = pb.Compare_NOT_EQUAL 41 case ">": 42 r = pb.Compare_GREATER 43 case "<": 44 r = pb.Compare_LESS 45 default: 46 panic("Unknown result op") 47 } 48 49 cmp.Result = r 50 switch cmp.Target { 51 case pb.Compare_VALUE: 52 val, ok := v.(string) 53 if !ok { 54 panic("bad compare value") 55 } 56 cmp.TargetUnion = &pb.Compare_Value{Value: []byte(val)} 57 case pb.Compare_VERSION: 58 cmp.TargetUnion = &pb.Compare_Version{Version: mustInt64(v)} 59 case pb.Compare_CREATE: 60 cmp.TargetUnion = &pb.Compare_CreateRevision{CreateRevision: mustInt64(v)} 61 case pb.Compare_MOD: 62 cmp.TargetUnion = &pb.Compare_ModRevision{ModRevision: mustInt64(v)} 63 case pb.Compare_LEASE: 64 cmp.TargetUnion = &pb.Compare_Lease{Lease: mustInt64orLeaseID(v)} 65 default: 66 panic("Unknown compare type") 67 } 68 return cmp 69} 70 71func Value(key string) Cmp { 72 return Cmp{Key: []byte(key), Target: pb.Compare_VALUE} 73} 74 75func Version(key string) Cmp { 76 return Cmp{Key: []byte(key), Target: pb.Compare_VERSION} 77} 78 79func CreateRevision(key string) Cmp { 80 return Cmp{Key: []byte(key), Target: pb.Compare_CREATE} 81} 82 83func ModRevision(key string) Cmp { 84 return Cmp{Key: []byte(key), Target: pb.Compare_MOD} 85} 86 87// LeaseValue compares a key's LeaseID to a value of your choosing. The empty 88// LeaseID is 0, otherwise known as `NoLease`. 89func LeaseValue(key string) Cmp { 90 return Cmp{Key: []byte(key), Target: pb.Compare_LEASE} 91} 92 93// KeyBytes returns the byte slice holding with the comparison key. 94func (cmp *Cmp) KeyBytes() []byte { return cmp.Key } 95 96// WithKeyBytes sets the byte slice for the comparison key. 97func (cmp *Cmp) WithKeyBytes(key []byte) { cmp.Key = key } 98 99// ValueBytes returns the byte slice holding the comparison value, if any. 100func (cmp *Cmp) ValueBytes() []byte { 101 if tu, ok := cmp.TargetUnion.(*pb.Compare_Value); ok { 102 return tu.Value 103 } 104 return nil 105} 106 107// WithValueBytes sets the byte slice for the comparison's value. 108func (cmp *Cmp) WithValueBytes(v []byte) { cmp.TargetUnion.(*pb.Compare_Value).Value = v } 109 110// WithRange sets the comparison to scan the range [key, end). 111func (cmp Cmp) WithRange(end string) Cmp { 112 cmp.RangeEnd = []byte(end) 113 return cmp 114} 115 116// WithPrefix sets the comparison to scan all keys prefixed by the key. 117func (cmp Cmp) WithPrefix() Cmp { 118 cmp.RangeEnd = getPrefix(cmp.Key) 119 return cmp 120} 121 122// mustInt64 panics if val isn't an int or int64. It returns an int64 otherwise. 123func mustInt64(val interface{}) int64 { 124 if v, ok := val.(int64); ok { 125 return v 126 } 127 if v, ok := val.(int); ok { 128 return int64(v) 129 } 130 panic("bad value") 131} 132 133// mustInt64orLeaseID panics if val isn't a LeaseID, int or int64. It returns an 134// int64 otherwise. 135func mustInt64orLeaseID(val interface{}) int64 { 136 if v, ok := val.(LeaseID); ok { 137 return int64(v) 138 } 139 return mustInt64(val) 140} 141