Skip to content

Commit 05e4a11

Browse files
committed
Expose snapshot reference counts
1 parent 6b0ae98 commit 05e4a11

6 files changed

Lines changed: 164 additions & 125 deletions

File tree

cmd/api/api/snapshots.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ func snapshotToOAPI(snapshot instances.Snapshot) oapi.Snapshot {
336336
SourceHypervisor: sourceHypervisor,
337337
CreatedAt: snapshot.CreatedAt,
338338
SizeBytes: snapshot.SizeBytes,
339+
RefCount: snapshot.RefCount,
339340
Name: lo.ToPtr(snapshot.Name),
340341
}
341342
if snapshot.CompressionState != "" {

lib/instances/snapshot.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ func (m *manager) listSnapshots(ctx context.Context, filter *ListSnapshotsFilter
3232
if err != nil {
3333
return nil, fmt.Errorf("list snapshots: %w", err)
3434
}
35+
counts, err := m.snapshotForkCounts()
36+
if err != nil {
37+
return nil, err
38+
}
39+
for i := range snapshots {
40+
snapshots[i].RefCount = counts[snapshots[i].Id]
41+
}
3542
return snapshots, nil
3643
}
3744

@@ -44,6 +51,11 @@ func (m *manager) getSnapshot(ctx context.Context, snapshotID string) (*Snapshot
4451
}
4552
return nil, err
4653
}
54+
refCount, err := m.countSnapshotForks(snapshotID)
55+
if err != nil {
56+
return nil, err
57+
}
58+
snapshot.RefCount = refCount
4759
return snapshot, nil
4860
}
4961

@@ -679,26 +691,34 @@ func (m *manager) listSnapshotRecords() ([]snapshotRecord, error) {
679691
}
680692

681693
func (m *manager) countSnapshotForks(snapshotID string) (int, error) {
682-
metaFiles, err := m.listMetadataFiles()
694+
counts, err := m.snapshotForkCounts()
683695
if err != nil {
684696
return 0, err
685697
}
698+
return counts[snapshotID], nil
699+
}
700+
701+
func (m *manager) snapshotForkCounts() (map[string]int, error) {
702+
metaFiles, err := m.listMetadataFiles()
703+
if err != nil {
704+
return nil, err
705+
}
686706

687-
count := 0
707+
counts := make(map[string]int)
688708
for _, metaPath := range metaFiles {
689709
content, err := os.ReadFile(metaPath)
690710
if err != nil {
691-
return 0, fmt.Errorf("read instance metadata %s: %w", metaPath, err)
711+
return nil, fmt.Errorf("read instance metadata %s: %w", metaPath, err)
692712
}
693713
var meta metadata
694714
if err := json.Unmarshal(content, &meta); err != nil {
695-
return 0, fmt.Errorf("unmarshal instance metadata %s: %w", metaPath, err)
715+
return nil, fmt.Errorf("unmarshal instance metadata %s: %w", metaPath, err)
696716
}
697-
if meta.ForkOfSnapshot == snapshotID {
698-
count++
717+
if meta.ForkOfSnapshot != "" {
718+
counts[meta.ForkOfSnapshot]++
699719
}
700720
}
701-
return count, nil
721+
return counts, nil
702722
}
703723

704724
func snapshotMemHardlinkSource(srcDir string) (absPath, relSlash string, ok bool) {

lib/instances/snapshot_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func TestStoppedSnapshotLifecycleAndForkAfterSourceDeletion(t *testing.T) {
4343
got, err := mgr.GetSnapshot(ctx, snap.Id)
4444
require.NoError(t, err)
4545
require.Equal(t, snap.Id, got.Id)
46+
require.Equal(t, 0, got.RefCount)
4647

4748
forked, err := mgr.ForkSnapshot(ctx, snap.Id, ForkSnapshotRequest{
4849
Name: "snapshot-stopped-fork",
@@ -57,6 +58,15 @@ func TestStoppedSnapshotLifecycleAndForkAfterSourceDeletion(t *testing.T) {
5758
require.NoError(t, err)
5859
require.Equal(t, snap.Id, forkMeta.ForkOfSnapshot)
5960

61+
got, err = mgr.GetSnapshot(ctx, snap.Id)
62+
require.NoError(t, err)
63+
require.Equal(t, 1, got.RefCount)
64+
65+
snapshots, err := mgr.ListSnapshots(ctx, &ListSnapshotsFilter{SourceInstanceID: &sourceID})
66+
require.NoError(t, err)
67+
require.Len(t, snapshots, 1)
68+
require.Equal(t, 1, snapshots[0].RefCount)
69+
6070
err = mgr.DeleteSnapshot(ctx, snap.Id)
6171
require.Error(t, err)
6272
assert.ErrorIs(t, err, ErrInvalidState)

0 commit comments

Comments
 (0)