Skip to content

Commit 6665d61

Browse files
committed
internal/manifest: track virtual table metadata in VirtualBackings
For each VirtualBacking, track the virtual tables that are using it. This allows us to more easily retrieve the virtual tables associated with a backing during compaction picking.
1 parent dd58b84 commit 6665d61

File tree

5 files changed

+100
-88
lines changed

5 files changed

+100
-88
lines changed

internal/manifest/testdata/virtual_backings

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,86 +2,96 @@
22
add n=1 size=100
33
----
44
1 virtual backings, total size 100:
5-
000001: size=100 useCount=0 protectionCount=0 virtualizedSize=0
5+
000001: size=100 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
66
unused virtual backings: 000001
77

88
add n=2 size=200
99
----
1010
2 virtual backings, total size 300:
11-
000001: size=100 useCount=0 protectionCount=0 virtualizedSize=0
12-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
11+
000001: size=100 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
12+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
1313
unused virtual backings: 000001 000002
1414

1515
add n=2 size=200
1616
----
1717
pebble: trying to add an existing file backing
1818

19-
add-table n=1 size=10
19+
add-table n=1 size=10 table=1
2020
----
2121
2 virtual backings, total size 300:
22-
000001: size=100 useCount=1 protectionCount=0 virtualizedSize=10
23-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
22+
000001: size=100 useCount=1 protectionCount=0 virtualizedSize=10 tables: [000001]
23+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
2424
unused virtual backings: 000002
2525

26-
add-table n=1 size=10
26+
remove-table n=2 table=1
27+
----
28+
table 000001 does not use backing 000002
29+
30+
31+
add-table n=1 size=10 table=3
2732
----
2833
2 virtual backings, total size 300:
29-
000001: size=100 useCount=2 protectionCount=0 virtualizedSize=20
30-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
34+
000001: size=100 useCount=2 protectionCount=0 virtualizedSize=20 tables: [000001 000003]
35+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
3136
unused virtual backings: 000002
3237

33-
add-table n=1 size=10
38+
add-table n=1 size=10 table=5
3439
----
3540
2 virtual backings, total size 300:
36-
000001: size=100 useCount=3 protectionCount=0 virtualizedSize=30
37-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
41+
000001: size=100 useCount=3 protectionCount=0 virtualizedSize=30 tables: [000001 000003 000005]
42+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
3843
unused virtual backings: 000002
3944

45+
add-table n=1 size=10 table=5
46+
----
47+
table 000005 already uses backing 000001
48+
49+
4050
remove n=1
4151
----
4252
backing 000001 still in use (useCount=3 protectionCount=0)
4353

44-
remove-table n=1 size=10
54+
remove-table n=1 table=1
4555
----
4656
2 virtual backings, total size 300:
47-
000001: size=100 useCount=2 protectionCount=0 virtualizedSize=20
48-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
57+
000001: size=100 useCount=2 protectionCount=0 virtualizedSize=20 tables: [000003 000005]
58+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
4959
unused virtual backings: 000002
5060

51-
remove-table n=1 size=10
61+
remove-table n=1 table=3
5262
----
5363
2 virtual backings, total size 300:
54-
000001: size=100 useCount=1 protectionCount=0 virtualizedSize=10
55-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
64+
000001: size=100 useCount=1 protectionCount=0 virtualizedSize=10 tables: [000005]
65+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
5666
unused virtual backings: 000002
5767

58-
remove-table n=1 size=10
68+
remove-table n=1 table=5
5969
----
6070
2 virtual backings, total size 300:
61-
000001: size=100 useCount=0 protectionCount=0 virtualizedSize=0
62-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
71+
000001: size=100 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
72+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
6373
unused virtual backings: 000001 000002
6474

6575
remove n=1
6676
----
6777
1 virtual backings, total size 200:
68-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
78+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
6979
unused virtual backings: 000002
7080

7181
protect n=2
7282
----
7383
1 virtual backings, total size 200:
74-
000002: size=200 useCount=0 protectionCount=1 virtualizedSize=0
84+
000002: size=200 useCount=0 protectionCount=1 virtualizedSize=0 tables: []
7585

7686
protect n=2
7787
----
7888
1 virtual backings, total size 200:
79-
000002: size=200 useCount=0 protectionCount=2 virtualizedSize=0
89+
000002: size=200 useCount=0 protectionCount=2 virtualizedSize=0 tables: []
8090

8191
unprotect n=2
8292
----
8393
1 virtual backings, total size 200:
84-
000002: size=200 useCount=0 protectionCount=1 virtualizedSize=0
94+
000002: size=200 useCount=0 protectionCount=1 virtualizedSize=0 tables: []
8595

8696
remove n=2
8797
----
@@ -90,36 +100,36 @@ backing 000002 still in use (useCount=0 protectionCount=1)
90100
unprotect n=2
91101
----
92102
1 virtual backings, total size 200:
93-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
103+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
94104
unused virtual backings: 000002
95105

96-
add-table n=2 size=10
106+
add-table n=2 size=10 table=2
97107
----
98108
1 virtual backings, total size 200:
99-
000002: size=200 useCount=1 protectionCount=0 virtualizedSize=10
109+
000002: size=200 useCount=1 protectionCount=0 virtualizedSize=10 tables: [000002]
100110

101-
add-table n=2 size=10
111+
add-table n=2 size=10 table=4
102112
----
103113
1 virtual backings, total size 200:
104-
000002: size=200 useCount=2 protectionCount=0 virtualizedSize=20
114+
000002: size=200 useCount=2 protectionCount=0 virtualizedSize=20 tables: [000002 000004]
105115

106116
protect n=2
107117
----
108118
1 virtual backings, total size 200:
109-
000002: size=200 useCount=2 protectionCount=1 virtualizedSize=20
119+
000002: size=200 useCount=2 protectionCount=1 virtualizedSize=20 tables: [000002 000004]
110120

111-
remove-table n=2 size=10
121+
remove-table n=2 size=10 table=4
112122
----
113123
1 virtual backings, total size 200:
114-
000002: size=200 useCount=1 protectionCount=1 virtualizedSize=10
124+
000002: size=200 useCount=1 protectionCount=1 virtualizedSize=10 tables: [000002]
115125

116-
remove-table n=2 size=10
126+
remove-table n=2 size=10 table=2
117127
----
118128
1 virtual backings, total size 200:
119-
000002: size=200 useCount=0 protectionCount=1 virtualizedSize=0
129+
000002: size=200 useCount=0 protectionCount=1 virtualizedSize=0 tables: []
120130

121131
unprotect n=2
122132
----
123133
1 virtual backings, total size 200:
124-
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0
134+
000002: size=200 useCount=0 protectionCount=0 virtualizedSize=0 tables: []
125135
unused virtual backings: 000002

internal/manifest/virtual_backings.go

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bytes"
99
stdcmp "cmp"
1010
"fmt"
11+
"maps"
1112
"slices"
1213

1314
"github.com/cockroachdb/errors"
@@ -86,16 +87,16 @@ func MakeVirtualBackings() VirtualBackings {
8687
type backingWithMetadata struct {
8788
backing *TableBacking
8889

89-
// A backing initially has a useCount of 0. The useCount is increased by
90-
// AddTable and decreased by RemoveTable. Backings that have useCount=0 are
91-
92-
useCount int32
9390
// protectionCount is used by Protect to temporarily prevent a backing from
9491
// being reported as unused.
9592
protectionCount int32
96-
// virtualizedSize is the sum of the sizes of the useCount virtual tables
93+
// virtualizedSize is the sum of the sizes of the virtual tables
9794
// associated with this backing.
9895
virtualizedSize uint64
96+
97+
// virtualTables is the list of virtual tables that use this backing.
98+
// AddTable/RemoveTable maintain this map.
99+
virtualTables map[base.TableNum]*TableMetadata
99100
}
100101

101102
// AddAndRef adds a new backing to the set and takes a reference on it. Another
@@ -108,7 +109,8 @@ func (bv *VirtualBackings) AddAndRef(backing *TableBacking) {
108109
// (see Protect), we might be the only ones holding on to a backing.
109110
backing.Ref()
110111
bv.mustAdd(backingWithMetadata{
111-
backing: backing,
112+
backing: backing,
113+
virtualTables: make(map[base.TableNum]*TableMetadata),
112114
})
113115
bv.unused[backing] = struct{}{}
114116
bv.totalSize += backing.Size
@@ -123,43 +125,43 @@ func (bv *VirtualBackings) Remove(n base.DiskFileNum) {
123125
if v.inUse() {
124126
panic(errors.AssertionFailedf(
125127
"backing %s still in use (useCount=%d protectionCount=%d)",
126-
v.backing.DiskFileNum, v.useCount, v.protectionCount,
128+
v.backing.DiskFileNum, len(v.virtualTables), v.protectionCount,
127129
))
128130
}
129131
delete(bv.m, n)
130132
delete(bv.unused, v.backing)
131133
bv.totalSize -= v.backing.Size
132134
}
133135

134-
// AddTable is used when a new table is using an exiting backing. The backing
136+
// AddTable is used when a new table is using an existing backing. The backing
135137
// must be in the set already.
136138
func (bv *VirtualBackings) AddTable(m *TableMetadata) {
137139
if !m.Virtual {
138140
panic(errors.AssertionFailedf("table %s not virtual", m.TableNum))
139141
}
140142
v := bv.mustGet(m.TableBacking.DiskFileNum)
143+
if _, ok := v.virtualTables[m.TableNum]; ok {
144+
panic(errors.AssertionFailedf("table %s already uses backing %s", m.TableNum, v.backing.DiskFileNum))
145+
}
141146
if !v.inUse() {
142147
delete(bv.unused, v.backing)
143148
}
144-
v.useCount++
145149
v.virtualizedSize += m.Size
150+
v.virtualTables[m.TableNum] = m
146151
bv.m[m.TableBacking.DiskFileNum] = v
147152
}
148153

149154
// RemoveTable is used when a table using a backing is removed. The backing is
150155
// not removed from the set, even if it becomes unused.
151-
func (bv *VirtualBackings) RemoveTable(m *TableMetadata) {
152-
if !m.Virtual {
153-
panic(errors.AssertionFailedf("table %s not virtual", m.TableNum))
154-
}
155-
v := bv.mustGet(m.TableBacking.DiskFileNum)
156-
157-
if v.useCount <= 0 {
158-
panic(errors.AssertionFailedf("invalid useCount"))
156+
func (bv *VirtualBackings) RemoveTable(backing base.DiskFileNum, table base.TableNum) {
157+
v := bv.mustGet(backing)
158+
t, ok := v.virtualTables[table]
159+
if !ok {
160+
panic(errors.AssertionFailedf("table %s does not use backing %s", table, v.backing.DiskFileNum))
159161
}
160-
v.useCount--
161-
v.virtualizedSize -= m.Size
162-
bv.m[m.TableBacking.DiskFileNum] = v
162+
delete(v.virtualTables, table)
163+
v.virtualizedSize -= t.Size
164+
bv.m[backing] = v
163165
if !v.inUse() {
164166
bv.unused[v.backing] = struct{}{}
165167
}
@@ -210,7 +212,7 @@ func (bv *VirtualBackings) Stats() (count int, totalSize uint64) {
210212
// virtual sstable with a higher priority.
211213
func (bv *VirtualBackings) Usage(n base.DiskFileNum) (useCount int, virtualizedSize uint64) {
212214
v := bv.mustGet(n)
213-
return int(v.useCount), v.virtualizedSize
215+
return len(v.virtualTables), v.virtualizedSize
214216
}
215217

216218
// Unused returns all backings that are and no longer used by the latest version
@@ -273,8 +275,10 @@ func (bv *VirtualBackings) String() string {
273275
fmt.Fprintf(&buf, "%d virtual backings, total size %d:\n", count, totalSize)
274276
for _, n := range nums {
275277
v := bv.m[n]
276-
fmt.Fprintf(&buf, " %s: size=%d useCount=%d protectionCount=%d virtualizedSize=%d\n",
277-
n, v.backing.Size, v.useCount, v.protectionCount, v.virtualizedSize)
278+
fmt.Fprintf(&buf, " %s: size=%d useCount=%d protectionCount=%d virtualizedSize=%d",
279+
n, v.backing.Size, len(v.virtualTables), v.protectionCount, v.virtualizedSize)
280+
tableNums := slices.Sorted(maps.Keys(v.virtualTables))
281+
fmt.Fprintf(&buf, " tables: %v\n", tableNums)
278282
}
279283
}
280284
unused := bv.Unused()
@@ -306,5 +310,5 @@ func (bv *VirtualBackings) mustGet(n base.DiskFileNum) backingWithMetadata {
306310

307311
// inUse returns true if b is used to back at least one virtual table.
308312
func (v *backingWithMetadata) inUse() bool {
309-
return v.useCount > 0 || v.protectionCount > 0
313+
return len(v.virtualTables) > 0 || v.protectionCount > 0
310314
}

internal/manifest/virtual_backings_test.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ import (
1515
func TestVirtualBackings(t *testing.T) {
1616
bv := MakeVirtualBackings()
1717
datadriven.RunTest(t, "testdata/virtual_backings", func(t *testing.T, d *datadriven.TestData) (retVal string) {
18-
var nInt, size uint64
18+
var nInt, size, tInt uint64
1919
d.MaybeScanArgs(t, "n", &nInt)
2020
d.MaybeScanArgs(t, "size", &size)
21+
d.MaybeScanArgs(t, "table", &tInt)
2122
n := base.DiskFileNum(nInt)
23+
tableNum := base.TableNum(tInt)
2224

2325
defer func() {
2426
if r := recover(); r != nil {
@@ -38,19 +40,15 @@ func TestVirtualBackings(t *testing.T) {
3840

3941
case "add-table":
4042
m := &TableMetadata{
43+
TableNum: tableNum,
4144
TableBacking: &TableBacking{DiskFileNum: n},
4245
Size: size,
4346
Virtual: true,
4447
}
4548
bv.AddTable(m)
4649

4750
case "remove-table":
48-
m := &TableMetadata{
49-
TableBacking: &TableBacking{DiskFileNum: n},
50-
Size: size,
51-
Virtual: true,
52-
}
53-
bv.RemoveTable(m)
51+
bv.RemoveTable(n, tableNum)
5452

5553
case "protect":
5654
bv.Protect(n)

0 commit comments

Comments
 (0)