diff --git a/cli/command_status.go b/cli/command_status.go new file mode 100644 index 000000000..53140d2d1 --- /dev/null +++ b/cli/command_status.go @@ -0,0 +1,63 @@ +package cli + +import ( + "encoding/json" + "fmt" + + "github.com/kopia/kopia/blob" + "github.com/kopia/kopia/internal/units" + kingpin "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + statusCommand = app.Command("status", "Show status of repository") +) + +func runStatusCommand(context *kingpin.ParseContext) error { + rep := mustOpenRepository(nil) + defer rep.Close() + + s := rep.Status() + + fmt.Printf("Config file: %v\n", rep.ConfigFile) + fmt.Printf("Cache directory: %v\n", rep.CacheDirectory) + fmt.Println() + + if cip, ok := rep.Storage.(blob.ConnectionInfoProvider); ok { + ci := cip.ConnectionInfo() + fmt.Printf("Storage type: %v\n", ci.Type) + if cjson, err := json.MarshalIndent(ci.Config, " ", " "); err == nil { + fmt.Printf("Storage config: %v\n", string(cjson)) + } + fmt.Println() + } + + var splitterExtraInfo string + + switch s.Splitter { + case "DYNAMIC": + splitterExtraInfo = fmt.Sprintf( + " (min: %v; avg: %v; max: %v)", + units.BytesStringBase2(int64(s.MinBlockSize)), + units.BytesStringBase2(int64(s.AvgBlockSize)), + units.BytesStringBase2(int64(s.MaxBlockSize))) + case "FIXED": + splitterExtraInfo = fmt.Sprintf(" %v", units.BytesStringBase2(int64(s.MaxBlockSize))) + } + + fmt.Println() + fmt.Printf("Metadata manager: v%v\n", s.MetadataManagerVersion) + fmt.Printf("Metadata Encryption: %v\n", s.MetadataEncryptionAlgorithm) + fmt.Printf("Key Derivation: %v\n", s.KeyDerivationAlgorithm) + fmt.Printf("Unique ID: %v\n", s.UniqueID) + fmt.Println() + fmt.Printf("Object manager: v%v\n", s.ObjectManagerVersion) + fmt.Printf("Object format: %v\n", s.ObjectFormat) + fmt.Printf("Splitter: %v%v\n", s.Splitter, splitterExtraInfo) + + return nil +} + +func init() { + statusCommand.Action(runStatusCommand) +} diff --git a/repo/repository.go b/repo/repository.go index 2ed5fd453..88906c1f7 100644 --- a/repo/repository.go +++ b/repo/repository.go @@ -1,8 +1,8 @@ package repo -import ( - "github.com/kopia/kopia/blob" -) +import "github.com/kopia/kopia/blob" +import "encoding/hex" +import "fmt" // Repository represents storage where both content-addressable and user-addressable data is kept. type Repository struct { @@ -14,6 +14,44 @@ type Repository struct { CacheDirectory string } +// StatusInfo stores a snapshot of repository-wide statistics plus some general information about repository configuration. +type StatusInfo struct { + Stats + + MetadataManagerVersion string + MetadataEncryptionAlgorithm string + UniqueID string + KeyDerivationAlgorithm string + + ObjectManagerVersion string + ObjectFormat string + MaxInlineContentLength int + Splitter string + MinBlockSize int + AvgBlockSize int + MaxBlockSize int +} + +// Status returns a snapshot of repository-wide statistics plus some general information about repository configuration. +func (r *Repository) Status() StatusInfo { + return StatusInfo{ + Stats: r.ObjectManager.stats, + + MetadataManagerVersion: r.MetadataManager.format.Version, + UniqueID: hex.EncodeToString(r.MetadataManager.format.UniqueID), + MetadataEncryptionAlgorithm: r.MetadataManager.format.EncryptionAlgorithm, + KeyDerivationAlgorithm: r.MetadataManager.format.KeyDerivationAlgorithm, + + ObjectManagerVersion: fmt.Sprintf("%v", r.ObjectManager.format.Version), + ObjectFormat: r.ObjectManager.format.ObjectFormat, + Splitter: r.ObjectManager.format.Splitter, + MaxInlineContentLength: r.ObjectManager.format.MaxInlineContentLength, + MinBlockSize: r.ObjectManager.format.MinBlockSize, + AvgBlockSize: r.ObjectManager.format.AvgBlockSize, + MaxBlockSize: r.ObjectManager.format.MaxBlockSize, + } +} + // Close closes the repository and releases all resources. func (r *Repository) Close() error { if err := r.ObjectManager.Close(); err != nil { @@ -31,11 +69,6 @@ func (r *Repository) Flush() error { return nil } -// Stats returns repository-wide statistics. -func (r *Repository) Stats() Stats { - return r.ObjectManager.stats -} - // ResetStats resets all repository-wide statistics to zero values. func (r *Repository) ResetStats() { r.ObjectManager.stats = Stats{} diff --git a/snapshot/upload.go b/snapshot/upload.go index 1102d0343..847eaaa22 100644 --- a/snapshot/upload.go +++ b/snapshot/upload.go @@ -570,7 +570,7 @@ func Upload( s.EndTime = time.Now() s.Stats = *u.stats - s.Stats.Repository = u.repo.Stats() + s.Stats.Repository = u.repo.Status().Stats return s, nil }