okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

Aly Raffaufrefactor(cli): use generated response field metadata7e45521

main
3.3 KiB102 linesraw
1package daemon
2
3import (
4	"context"
5	"io"
6	"net/http"
7
8	"albedo/cli/internal/daemon/protocol"
9)
10
11type StorageFile struct {
12	Path  string `json:"path"`
13	Bytes int64  `json:"bytes"`
14}
15
16type StorageSession struct {
17	ID    string `json:"id"`
18	Bytes int64  `json:"bytes"`
19}
20
21type StorageDatabase struct {
22	Sessions  []StorageSession `json:"sessions"`
23	Images    int64            `json:"images"`
24	FreePages int64            `json:"free_pages"`
25	PageSize  int64            `json:"page_size"`
26}
27
28type StorageReport struct {
29	OldKernels        []StorageFile   `json:"old_kernels"`
30	OldBackups        []StorageFile   `json:"old_backups"`
31	DB                StorageDatabase `json:"db"`
32	Database          int64           `json:"database"`
33	WAL               int64           `json:"wal"`
34	Kernels           int64           `json:"kernels"`
35	Backups           int64           `json:"backups"`
36	Other             int64           `json:"other"`
37	RecentBackups     int64           `json:"recent_backups"`
38	RecentBackupCount int             `json:"recent_backup_count"`
39}
40
41func GetStorageReport(ctx context.Context, conn *Connection) (StorageReport, error) {
42	result := StorageReport{OldKernels: []StorageFile{}, OldBackups: []StorageFile{}, DB: StorageDatabase{Sessions: []StorageSession{}}}
43	params := protocol.GetStorageParams{Limit: new(int64(200))}
44	seenSessions, seenFiles := map[string]bool{}, map[string]bool{}
45	seenTokens := map[[2]string]bool{}
46	for {
47		var w protocol.StorageReport
48		err := executeRead(ctx, conn, operation{Capability: "storage_report", Name: "read storage", BuildRequest: func(base string, body io.Reader) (*http.Request, error) {
49			return protocol.NewGetStorageRequest(base, &params)
50		}, Policy: readRecovery}, func(data []byte) error {
51			return decodeRequired(data, &w)
52		})
53		if err != nil {
54			return result, err
55		}
56		result.Database = w.Database.MainFileBytes
57		result.WAL = w.Database.WalBytes
58		result.DB.Images = w.Images.Bytes
59		result.DB.FreePages = w.Database.FreePageCount
60		result.DB.PageSize = w.Database.PageSizeBytes
61		result.Kernels = w.Files.Totals.KernelBytes
62		result.Backups = w.Files.Totals.BackupBytes
63		result.Other = w.Files.Totals.OtherBytes
64		result.RecentBackups = w.Files.Totals.RecentBackupBytes
65		result.RecentBackupCount = int(w.Files.Totals.RecentBackupCount)
66		for _, row := range w.Sessions.Items {
67			if !seenSessions[row.ID] {
68				seenSessions[row.ID] = true
69				result.DB.Sessions = append(result.DB.Sessions, StorageSession{ID: row.ID, Bytes: row.EstimatedContentBytes})
70			}
71		}
72		for _, row := range w.Files.Items {
73			if seenFiles[row.Path] {
74				continue
75			}
76			seenFiles[row.Path] = true
77			file := StorageFile{Path: row.Path, Bytes: row.Bytes}
78			if row.CleanupCandidate {
79				switch row.Category {
80				case "kernel":
81					result.OldKernels = append(result.OldKernels, file)
82				case "backup":
83					result.OldBackups = append(result.OldBackups, file)
84				}
85			}
86		}
87		if w.Sessions.Next == nil && w.Files.Next == nil {
88			return result, nil
89		}
90		if w.Sessions.Next != nil {
91			params.SessionsNext = w.Sessions.Next
92		}
93		if w.Files.Next != nil {
94			params.FilesNext = w.Files.Next
95		}
96		key := [2]string{value(params.SessionsNext), value(params.FilesNext)}
97		if seenTokens[key] {
98			return result, fieldError("storage page cursor")
99		}
100		seenTokens[key] = true
101	}
102}