v0.1.1 e7b3a25

batch.go RawHistoryFolder

1// SPDX-License-Identifier: MIT
2
3package kv
4
5// Batch is an ordered set of mutations and preconditions that Apply commits
6// atomically. The zero value is ready to use. A Batch must not be modified
7// while Apply runs and is not safe for concurrent use.
8//
9// Batch methods do not return errors: the batch records its first error and
10// Apply returns it.
11type Batch struct {
12	ops      []op
13	pre      []precond
14	opsBytes int // encoded size of ops
15	err      error
16}
17
18// precond is a precondition checked by the writer before any op.
19type precond struct {
20	key     []byte
21	absent  bool   // the key must not exist
22	version uint64 // otherwise the key must exist at this version
23}
24
25// Put sets key to value. It copies key and value.
26func (b *Batch) Put(key, value []byte) {
27	if !b.validKey(key) {
28		return
29	}
30	// One allocation holds both; the tree retains the slices, so they are
31	// never reused (not even by Reset).
32	buf := make([]byte, len(key)+len(value))
33	n := copy(buf, key)
34	copy(buf[n:], value)
35	b.add(op{kind: opPut, key: buf[:n:n], value: buf[n:len(buf):len(buf)]})
36}
37
38// Delete removes key. It copies key. Deleting a missing key is not an error.
39func (b *Batch) Delete(key []byte) {
40	if !b.validKey(key) {
41		return
42	}
43	b.add(op{kind: opDelete, key: append([]byte(nil), key...)})
44}
45
46// RequireAbsent adds the precondition that key does not exist. If it does
47// not hold when the batch is committed, Apply returns ErrConflict.
48func (b *Batch) RequireAbsent(key []byte) {
49	if !b.validKey(key) {
50		return
51	}
52	b.pre = append(b.pre, precond{key: append([]byte(nil), key...), absent: true})
53}
54
55// RequireVersion adds the precondition that key exists at version v, the seq
56// of the batch that last wrote it. v must be greater than zero, otherwise the
57// batch records ErrInvalidKey.
58func (b *Batch) RequireVersion(key []byte, v uint64) {
59	if !b.validKey(key) {
60		return
61	}
62	if v == 0 {
63		b.fail(ErrInvalidKey)
64		return
65	}
66	b.pre = append(b.pre, precond{key: append([]byte(nil), key...), version: v})
67}
68
69// Len returns the number of ops and preconditions.
70func (b *Batch) Len() int { return len(b.ops) + len(b.pre) }
71
72// Reset empties the batch, clears its error and keeps allocated capacity for
73// the op list.
74func (b *Batch) Reset() {
75	clear(b.ops)
76	b.ops = b.ops[:0]
77	clear(b.pre)
78	b.pre = b.pre[:0]
79	b.opsBytes = 0
80	b.err = nil
81}
82
83// encodedSize returns the size of the batch in a log record (op count and
84// ops), which MaxBatchBytes limits; 0 for a batch without ops, which writes
85// nothing.
86func (b *Batch) encodedSize() int {
87	if len(b.ops) == 0 {
88		return 0
89	}
90	return batchHeader + b.opsBytes
91}
92
93func (b *Batch) add(o op) {
94	b.ops = append(b.ops, o)
95	b.opsBytes += opSize(o)
96}
97
98func (b *Batch) fail(err error) {
99	if b.err == nil {
100		b.err = err
101	}
102}
103
104// validKey records ErrInvalidKey and reports false for an invalid key.
105func (b *Batch) validKey(key []byte) bool {
106	if len(key) == 0 || len(key) > maxKeyLen {
107		b.fail(ErrInvalidKey)
108		return false
109	}
110	return b.err == nil
111}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 2

↑↓ moveenter openesc close