feat: add debug commands for folder counts and files (#10206)
This adds two debugging commands that print information directly from the database; one for folder counts, and one for file metadata for files matching a pattern in a folder. E.g., ``` % syncthing debug database-counts p3jms-73gps DEVICE TYPE FLAGS DELETED COUNT SIZE -local- FILE ------- --- 0 0 -local- FILE --G---- --- 2473 70094796496 -local- DIRECTORY ------- --- 0 0 -local- DIRECTORY --G---- --- 19 2432 PSEUDOP FILE ------- --- 2473 70094796496 PSEUDOP FILE -nG---- --- 0 0 PSEUDOP DIRECTORY ------- --- 19 2432 PSEUDOP DIRECTORY -nG---- --- 0 0 ``` ``` % syncthing debug database-file p3jms-73gps 20240929-DSCF1387 DSCF1387 DEVICE TYPE NAME SEQUENCE DELETED MODIFIED SIZE FLAGS VERSION BLOCKLIST -local- FILE Austin/20240929-DSCF1387.raf 1204 --- 2024-09-29T01:10:54Z 48911888 --G---- HX2ELNU:1744213700 fsQdMvUL PSEUDOP FILE Austin/20240929-DSCF1387.raf 22279 --- 2024-09-29T01:10:54Z 48911888 ------- HX2ELNU:1744213700 fsQdMvUL -local- FILE Austin/20240929-DSCF1387.xmp 1196 --- 2024-10-16T08:08:35.137501751Z 5579 --G---- HX2ELNU:1744213700 xDGMnepi PSEUDOP FILE Austin/20240929-DSCF1387.xmp 19910 --- 2024-10-16T08:08:35.137501751Z 5579 ------- HX2ELNU:1744213700 xDGMnepi ``` The local flag bits get a string representation for the bitmask, ``` FlagLocalUnsupported: "u", FlagLocalIgnored: "i", FlagLocalMustRescan: "r", FlagLocalReceiveOnly: "e", FlagLocalGlobal: "G", FlagLocalNeeded: "n", FlagLocalRemoteInvalid: "v", ```
This commit is contained in:
@@ -11,6 +11,8 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/gen/bep"
|
||||
@@ -40,10 +42,52 @@ const (
|
||||
LocalAllFlags = FlagLocalUnsupported | FlagLocalIgnored | FlagLocalMustRescan | FlagLocalReceiveOnly | FlagLocalGlobal | FlagLocalNeeded | FlagLocalRemoteInvalid
|
||||
)
|
||||
|
||||
// localFlagBitNames maps flag values to characters which can be used to
|
||||
// build a permission-like bit string for easier reading.
|
||||
var localFlagBitNames = map[FlagLocal]string{
|
||||
FlagLocalUnsupported: "u",
|
||||
FlagLocalIgnored: "i",
|
||||
FlagLocalMustRescan: "r",
|
||||
FlagLocalReceiveOnly: "e",
|
||||
FlagLocalGlobal: "G",
|
||||
FlagLocalNeeded: "n",
|
||||
FlagLocalRemoteInvalid: "v",
|
||||
}
|
||||
|
||||
func (f FlagLocal) IsInvalid() bool {
|
||||
return f&LocalInvalidFlags != 0
|
||||
}
|
||||
|
||||
// HumanString returns a permission-like string representation of the flag bits
|
||||
func (f FlagLocal) HumanString() string {
|
||||
if f == 0 {
|
||||
return strings.Repeat("-", len(localFlagBitNames))
|
||||
}
|
||||
|
||||
bit := FlagLocal(1)
|
||||
var res bytes.Buffer
|
||||
var extra strings.Builder
|
||||
for f != 0 {
|
||||
if f&bit != 0 {
|
||||
if name, ok := localFlagBitNames[bit]; ok {
|
||||
res.WriteString(name)
|
||||
} else {
|
||||
fmt.Fprintf(&extra, "+0x%x", bit)
|
||||
}
|
||||
} else {
|
||||
res.WriteString("-")
|
||||
}
|
||||
f &^= bit
|
||||
bit <<= 1
|
||||
}
|
||||
if res.Len() < len(localFlagBitNames) {
|
||||
res.WriteString(strings.Repeat("-", len(localFlagBitNames)-res.Len()))
|
||||
}
|
||||
base := res.Bytes()
|
||||
slices.Reverse(base)
|
||||
return string(base) + extra.String()
|
||||
}
|
||||
|
||||
// BlockSizes is the list of valid block sizes, from min to max
|
||||
var BlockSizes []int
|
||||
|
||||
|
||||
@@ -38,6 +38,17 @@ func (v *Vector) String() string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (v *Vector) HumanString() string {
|
||||
var buf strings.Builder
|
||||
for i, c := range v.Counters {
|
||||
if i > 0 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
fmt.Fprintf(&buf, "%s:%d", c.ID, c.Value)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (v *Vector) ToWire() *bep.Vector {
|
||||
counters := make([]*bep.Counter, len(v.Counters))
|
||||
for i, c := range v.Counters {
|
||||
|
||||
Reference in New Issue
Block a user