1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package clientv3
16
17 import pb "go.etcd.io/etcd/api/v3/etcdserverpb"
18
19 type opType int
20
21 const (
22
23 tRange opType = iota + 1
24 tPut
25 tDeleteRange
26 tTxn
27 )
28
29 var noPrefixEnd = []byte{0}
30
31
32 type Op struct {
33 t opType
34 key []byte
35 end []byte
36
37
38 limit int64
39 sort *SortOption
40 serializable bool
41 keysOnly bool
42 countOnly bool
43 minModRev int64
44 maxModRev int64
45 minCreateRev int64
46 maxCreateRev int64
47
48
49 rev int64
50
51
52 prevKV bool
53
54
55
56
57
58 fragment bool
59
60
61 ignoreValue bool
62 ignoreLease bool
63
64
65 progressNotify bool
66
67 createdNotify bool
68
69 filterPut bool
70 filterDelete bool
71
72
73 val []byte
74 leaseID LeaseID
75
76
77 cmps []Cmp
78 thenOps []Op
79 elseOps []Op
80
81 isOptsWithFromKey bool
82 isOptsWithPrefix bool
83 }
84
85
86
87
88 func (op Op) IsTxn() bool {
89 return op.t == tTxn
90 }
91
92
93 func (op Op) Txn() ([]Cmp, []Op, []Op) {
94 return op.cmps, op.thenOps, op.elseOps
95 }
96
97
98 func (op Op) KeyBytes() []byte { return op.key }
99
100
101 func (op *Op) WithKeyBytes(key []byte) { op.key = key }
102
103
104 func (op Op) RangeBytes() []byte { return op.end }
105
106
107 func (op Op) Rev() int64 { return op.rev }
108
109
110 func (op Op) IsPut() bool { return op.t == tPut }
111
112
113 func (op Op) IsGet() bool { return op.t == tRange }
114
115
116 func (op Op) IsDelete() bool { return op.t == tDeleteRange }
117
118
119 func (op Op) IsSerializable() bool { return op.serializable }
120
121
122 func (op Op) IsKeysOnly() bool { return op.keysOnly }
123
124
125 func (op Op) IsCountOnly() bool { return op.countOnly }
126
127
128 func (op Op) MinModRev() int64 { return op.minModRev }
129
130
131 func (op Op) MaxModRev() int64 { return op.maxModRev }
132
133
134 func (op Op) MinCreateRev() int64 { return op.minCreateRev }
135
136
137 func (op Op) MaxCreateRev() int64 { return op.maxCreateRev }
138
139
140 func (op *Op) WithRangeBytes(end []byte) { op.end = end }
141
142
143 func (op Op) ValueBytes() []byte { return op.val }
144
145
146 func (op *Op) WithValueBytes(v []byte) { op.val = v }
147
148 func (op Op) toRangeRequest() *pb.RangeRequest {
149 if op.t != tRange {
150 panic("op.t != tRange")
151 }
152 r := &pb.RangeRequest{
153 Key: op.key,
154 RangeEnd: op.end,
155 Limit: op.limit,
156 Revision: op.rev,
157 Serializable: op.serializable,
158 KeysOnly: op.keysOnly,
159 CountOnly: op.countOnly,
160 MinModRevision: op.minModRev,
161 MaxModRevision: op.maxModRev,
162 MinCreateRevision: op.minCreateRev,
163 MaxCreateRevision: op.maxCreateRev,
164 }
165 if op.sort != nil {
166 r.SortOrder = pb.RangeRequest_SortOrder(op.sort.Order)
167 r.SortTarget = pb.RangeRequest_SortTarget(op.sort.Target)
168 }
169 return r
170 }
171
172 func (op Op) toTxnRequest() *pb.TxnRequest {
173 thenOps := make([]*pb.RequestOp, len(op.thenOps))
174 for i, tOp := range op.thenOps {
175 thenOps[i] = tOp.toRequestOp()
176 }
177 elseOps := make([]*pb.RequestOp, len(op.elseOps))
178 for i, eOp := range op.elseOps {
179 elseOps[i] = eOp.toRequestOp()
180 }
181 cmps := make([]*pb.Compare, len(op.cmps))
182 for i := range op.cmps {
183 cmps[i] = (*pb.Compare)(&op.cmps[i])
184 }
185 return &pb.TxnRequest{Compare: cmps, Success: thenOps, Failure: elseOps}
186 }
187
188 func (op Op) toRequestOp() *pb.RequestOp {
189 switch op.t {
190 case tRange:
191 return &pb.RequestOp{Request: &pb.RequestOp_RequestRange{RequestRange: op.toRangeRequest()}}
192 case tPut:
193 r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue, IgnoreLease: op.ignoreLease}
194 return &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: r}}
195 case tDeleteRange:
196 r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
197 return &pb.RequestOp{Request: &pb.RequestOp_RequestDeleteRange{RequestDeleteRange: r}}
198 case tTxn:
199 return &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{RequestTxn: op.toTxnRequest()}}
200 default:
201 panic("Unknown Op")
202 }
203 }
204
205 func (op Op) isWrite() bool {
206 if op.t == tTxn {
207 for _, tOp := range op.thenOps {
208 if tOp.isWrite() {
209 return true
210 }
211 }
212 for _, tOp := range op.elseOps {
213 if tOp.isWrite() {
214 return true
215 }
216 }
217 return false
218 }
219 return op.t != tRange
220 }
221
222 func NewOp() *Op {
223 return &Op{key: []byte("")}
224 }
225
226
227 func OpGet(key string, opts ...OpOption) Op {
228
229 if IsOptsWithPrefix(opts) && IsOptsWithFromKey(opts) {
230 panic("`WithPrefix` and `WithFromKey` cannot be set at the same time, choose one")
231 }
232 ret := Op{t: tRange, key: []byte(key)}
233 ret.applyOpts(opts)
234 return ret
235 }
236
237
238 func OpDelete(key string, opts ...OpOption) Op {
239
240 if IsOptsWithPrefix(opts) && IsOptsWithFromKey(opts) {
241 panic("`WithPrefix` and `WithFromKey` cannot be set at the same time, choose one")
242 }
243 ret := Op{t: tDeleteRange, key: []byte(key)}
244 ret.applyOpts(opts)
245 switch {
246 case ret.leaseID != 0:
247 panic("unexpected lease in delete")
248 case ret.limit != 0:
249 panic("unexpected limit in delete")
250 case ret.rev != 0:
251 panic("unexpected revision in delete")
252 case ret.sort != nil:
253 panic("unexpected sort in delete")
254 case ret.serializable:
255 panic("unexpected serializable in delete")
256 case ret.countOnly:
257 panic("unexpected countOnly in delete")
258 case ret.minModRev != 0, ret.maxModRev != 0:
259 panic("unexpected mod revision filter in delete")
260 case ret.minCreateRev != 0, ret.maxCreateRev != 0:
261 panic("unexpected create revision filter in delete")
262 case ret.filterDelete, ret.filterPut:
263 panic("unexpected filter in delete")
264 case ret.createdNotify:
265 panic("unexpected createdNotify in delete")
266 }
267 return ret
268 }
269
270
271 func OpPut(key, val string, opts ...OpOption) Op {
272 ret := Op{t: tPut, key: []byte(key), val: []byte(val)}
273 ret.applyOpts(opts)
274 switch {
275 case ret.end != nil:
276 panic("unexpected range in put")
277 case ret.limit != 0:
278 panic("unexpected limit in put")
279 case ret.rev != 0:
280 panic("unexpected revision in put")
281 case ret.sort != nil:
282 panic("unexpected sort in put")
283 case ret.serializable:
284 panic("unexpected serializable in put")
285 case ret.countOnly:
286 panic("unexpected countOnly in put")
287 case ret.minModRev != 0, ret.maxModRev != 0:
288 panic("unexpected mod revision filter in put")
289 case ret.minCreateRev != 0, ret.maxCreateRev != 0:
290 panic("unexpected create revision filter in put")
291 case ret.filterDelete, ret.filterPut:
292 panic("unexpected filter in put")
293 case ret.createdNotify:
294 panic("unexpected createdNotify in put")
295 }
296 return ret
297 }
298
299
300 func OpTxn(cmps []Cmp, thenOps []Op, elseOps []Op) Op {
301 return Op{t: tTxn, cmps: cmps, thenOps: thenOps, elseOps: elseOps}
302 }
303
304 func opWatch(key string, opts ...OpOption) Op {
305 ret := Op{t: tRange, key: []byte(key)}
306 ret.applyOpts(opts)
307 switch {
308 case ret.leaseID != 0:
309 panic("unexpected lease in watch")
310 case ret.limit != 0:
311 panic("unexpected limit in watch")
312 case ret.sort != nil:
313 panic("unexpected sort in watch")
314 case ret.serializable:
315 panic("unexpected serializable in watch")
316 case ret.countOnly:
317 panic("unexpected countOnly in watch")
318 case ret.minModRev != 0, ret.maxModRev != 0:
319 panic("unexpected mod revision filter in watch")
320 case ret.minCreateRev != 0, ret.maxCreateRev != 0:
321 panic("unexpected create revision filter in watch")
322 }
323 return ret
324 }
325
326 func (op *Op) applyOpts(opts []OpOption) {
327 for _, opt := range opts {
328 opt(op)
329 }
330 }
331
332
333 type OpOption func(*Op)
334
335
336 func WithLease(leaseID LeaseID) OpOption {
337 return func(op *Op) { op.leaseID = leaseID }
338 }
339
340
341
342 func WithLimit(n int64) OpOption { return func(op *Op) { op.limit = n } }
343
344
345
346 func WithRev(rev int64) OpOption { return func(op *Op) { op.rev = rev } }
347
348
349
350
351
352 func WithSort(target SortTarget, order SortOrder) OpOption {
353 return func(op *Op) {
354 if target == SortByKey && order == SortAscend {
355
356
357
358
359
360 order = SortNone
361 }
362 op.sort = &SortOption{target, order}
363 }
364 }
365
366
367
368 func GetPrefixRangeEnd(prefix string) string {
369 return string(getPrefix([]byte(prefix)))
370 }
371
372 func getPrefix(key []byte) []byte {
373 end := make([]byte, len(key))
374 copy(end, key)
375 for i := len(end) - 1; i >= 0; i-- {
376 if end[i] < 0xff {
377 end[i] = end[i] + 1
378 end = end[:i+1]
379 return end
380 }
381 }
382
383
384 return noPrefixEnd
385 }
386
387
388
389
390 func WithPrefix() OpOption {
391 return func(op *Op) {
392 op.isOptsWithPrefix = true
393 if len(op.key) == 0 {
394 op.key, op.end = []byte{0}, []byte{0}
395 return
396 }
397 op.end = getPrefix(op.key)
398 }
399 }
400
401
402
403
404
405 func WithRange(endKey string) OpOption {
406 return func(op *Op) { op.end = []byte(endKey) }
407 }
408
409
410
411 func WithFromKey() OpOption {
412 return func(op *Op) {
413 if len(op.key) == 0 {
414 op.key = []byte{0}
415 }
416 op.end = []byte("\x00")
417 op.isOptsWithFromKey = true
418 }
419 }
420
421
422
423
424 func WithSerializable() OpOption {
425 return func(op *Op) { op.serializable = true }
426 }
427
428
429
430 func WithKeysOnly() OpOption {
431 return func(op *Op) { op.keysOnly = true }
432 }
433
434
435 func WithCountOnly() OpOption {
436 return func(op *Op) { op.countOnly = true }
437 }
438
439
440 func WithMinModRev(rev int64) OpOption { return func(op *Op) { op.minModRev = rev } }
441
442
443 func WithMaxModRev(rev int64) OpOption { return func(op *Op) { op.maxModRev = rev } }
444
445
446 func WithMinCreateRev(rev int64) OpOption { return func(op *Op) { op.minCreateRev = rev } }
447
448
449 func WithMaxCreateRev(rev int64) OpOption { return func(op *Op) { op.maxCreateRev = rev } }
450
451
452 func WithFirstCreate() []OpOption { return withTop(SortByCreateRevision, SortAscend) }
453
454
455 func WithLastCreate() []OpOption { return withTop(SortByCreateRevision, SortDescend) }
456
457
458 func WithFirstKey() []OpOption { return withTop(SortByKey, SortAscend) }
459
460
461 func WithLastKey() []OpOption { return withTop(SortByKey, SortDescend) }
462
463
464 func WithFirstRev() []OpOption { return withTop(SortByModRevision, SortAscend) }
465
466
467 func WithLastRev() []OpOption { return withTop(SortByModRevision, SortDescend) }
468
469
470 func withTop(target SortTarget, order SortOrder) []OpOption {
471 return []OpOption{WithPrefix(), WithSort(target, order), WithLimit(1)}
472 }
473
474
475
476
477 func WithProgressNotify() OpOption {
478 return func(op *Op) {
479 op.progressNotify = true
480 }
481 }
482
483
484 func WithCreatedNotify() OpOption {
485 return func(op *Op) {
486 op.createdNotify = true
487 }
488 }
489
490
491 func WithFilterPut() OpOption {
492 return func(op *Op) { op.filterPut = true }
493 }
494
495
496 func WithFilterDelete() OpOption {
497 return func(op *Op) { op.filterDelete = true }
498 }
499
500
501
502 func WithPrevKV() OpOption {
503 return func(op *Op) {
504 op.prevKV = true
505 }
506 }
507
508
509
510
511
512
513
514
515 func WithFragment() OpOption {
516 return func(op *Op) { op.fragment = true }
517 }
518
519
520
521
522 func WithIgnoreValue() OpOption {
523 return func(op *Op) {
524 op.ignoreValue = true
525 }
526 }
527
528
529
530
531 func WithIgnoreLease() OpOption {
532 return func(op *Op) {
533 op.ignoreLease = true
534 }
535 }
536
537
538 type LeaseOp struct {
539 id LeaseID
540
541
542 attachedKeys bool
543 }
544
545
546 type LeaseOption func(*LeaseOp)
547
548 func (op *LeaseOp) applyOpts(opts []LeaseOption) {
549 for _, opt := range opts {
550 opt(op)
551 }
552 }
553
554
555 func WithAttachedKeys() LeaseOption {
556 return func(op *LeaseOp) { op.attachedKeys = true }
557 }
558
559 func toLeaseTimeToLiveRequest(id LeaseID, opts ...LeaseOption) *pb.LeaseTimeToLiveRequest {
560 ret := &LeaseOp{id: id}
561 ret.applyOpts(opts)
562 return &pb.LeaseTimeToLiveRequest{ID: int64(id), Keys: ret.attachedKeys}
563 }
564
565
566 func IsOptsWithPrefix(opts []OpOption) bool {
567 ret := NewOp()
568 for _, opt := range opts {
569 opt(ret)
570 }
571
572 return ret.isOptsWithPrefix
573 }
574
575
576 func IsOptsWithFromKey(opts []OpOption) bool {
577 ret := NewOp()
578 for _, opt := range opts {
579 opt(ret)
580 }
581
582 return ret.isOptsWithFromKey
583 }
584
View as plain text