1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
package dual
import (
"errors"
"fmt"
"io"
"lindenii.org/go/furgit/object/id"
"lindenii.org/go/furgit/object/store"
"lindenii.org/go/furgit/object/store/mix"
"lindenii.org/go/furgit/object/typ"
)
// BeginObjectQuarantine begins an object-wise quarantine on the object side.
//
//nolint:ireturn
func (dual *Dual) BeginObjectQuarantine(opts store.ObjectQuarantineOptions) (store.ObjectQuarantine, error) {
return dual.object.BeginObjectQuarantine(opts) //nolint:wrapcheck
}
// BeginPackQuarantine begins a pack-wise quarantine on the pack side.
//
//nolint:ireturn
func (dual *Dual) BeginPackQuarantine(opts store.PackQuarantineOptions) (store.PackQuarantine, error) {
return dual.pack.BeginPackQuarantine(opts) //nolint:wrapcheck
}
// BeginCoordinatedQuarantine begins a quarantine spanning both sides.
//
// If the pack side fails to begin,
// the already-begun object side is discarded before returning.
//
//nolint:ireturn
func (dual *Dual) BeginCoordinatedQuarantine(opts store.CoordinatedQuarantineOptions) (store.CoordinatedQuarantine, error) {
objectQ, err := dual.object.BeginObjectQuarantine(opts.Object)
if err != nil {
return nil, fmt.Errorf("object/store/dual: begin object quarantine: %w", err)
}
packQ, err := dual.pack.BeginPackQuarantine(opts.Pack)
if err != nil {
_ = objectQ.Discard()
return nil, fmt.Errorf("object/store/dual: begin pack quarantine: %w", err)
}
return newCoordinatedQuarantine(objectQ, packQ), nil
}
// coordinatedQuarantine is one coordinated quarantine over both sides.
type coordinatedQuarantine struct {
objectQ store.ObjectQuarantine
packQ store.PackQuarantine
reader store.ObjectReader
}
var _ store.CoordinatedQuarantine = (*coordinatedQuarantine)(nil)
func newCoordinatedQuarantine(
objectQ store.ObjectQuarantine,
packQ store.PackQuarantine,
) *coordinatedQuarantine {
return &coordinatedQuarantine{
objectQ: objectQ,
packQ: packQ,
reader: mix.New(objectQ, packQ),
}
}
func (quarantine *coordinatedQuarantine) ReadBytesFull(id id.ObjectID) ([]byte, error) {
return quarantine.reader.ReadBytesFull(id) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) ReadBytesContent(id id.ObjectID) (typ.Type, []byte, error) {
return quarantine.reader.ReadBytesContent(id) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) ReadReaderFull(id id.ObjectID) (io.ReadCloser, error) {
return quarantine.reader.ReadReaderFull(id) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) ReadReaderContent(id id.ObjectID) (typ.Type, int, io.ReadCloser, error) {
return quarantine.reader.ReadReaderContent(id) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) ReadSize(id id.ObjectID) (int, error) {
return quarantine.reader.ReadSize(id) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) ReadHeader(id id.ObjectID) (typ.Type, int, error) {
return quarantine.reader.ReadHeader(id) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) Refresh() error {
return quarantine.reader.Refresh() //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) WriteBytesFull(raw []byte) (id.ObjectID, error) {
return quarantine.objectQ.WriteBytesFull(raw) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) WriteBytesContent(ty typ.Type, content []byte) (id.ObjectID, error) {
return quarantine.objectQ.WriteBytesContent(ty, content) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) WriteReaderFull(src io.Reader) (id.ObjectID, error) {
return quarantine.objectQ.WriteReaderFull(src) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) WriteReaderContent(ty typ.Type, size int, src io.Reader) (id.ObjectID, error) {
return quarantine.objectQ.WriteReaderContent(ty, size, src) //nolint:wrapcheck
}
func (quarantine *coordinatedQuarantine) WritePack(src io.Reader, opts store.PackWriteOptions) error {
return quarantine.packQ.WritePack(src, opts) //nolint:wrapcheck
}
// Promote publishes both halves and joins their errors.
func (quarantine *coordinatedQuarantine) Promote() error {
return errors.Join(quarantine.objectQ.Promote(), quarantine.packQ.Promote())
}
// Discard abandons both halves and joins their errors.
func (quarantine *coordinatedQuarantine) Discard() error {
return errors.Join(quarantine.objectQ.Discard(), quarantine.packQ.Discard())
}
|