Merge pull request #196 from fracai/more-check-stats

print additional, table-formatted stats for CHECK
This commit is contained in:
gilbertchen
2017-09-20 17:16:23 -04:00
committed by GitHub
3 changed files with 137 additions and 34 deletions

View File

@@ -812,12 +812,13 @@ func checkSnapshots(context *cli.Context) {
} }
showStatistics := context.Bool("stats") showStatistics := context.Bool("stats")
showTabular := context.Bool("tabular")
checkFiles := context.Bool("files") checkFiles := context.Bool("files")
searchFossils := context.Bool("fossils") searchFossils := context.Bool("fossils")
resurrect := context.Bool("resurrect") resurrect := context.Bool("resurrect")
backupManager.SetupSnapshotCache(preference.Name) backupManager.SetupSnapshotCache(preference.Name)
backupManager.SnapshotManager.CheckSnapshots(id, revisions, tag, showStatistics, checkFiles, searchFossils, resurrect) backupManager.SnapshotManager.CheckSnapshots(id, revisions, tag, showStatistics, showTabular, checkFiles, searchFossils, resurrect)
runScript(context, preference.Name, "post") runScript(context, preference.Name, "post")
} }
@@ -1363,6 +1364,10 @@ func main() {
Name: "stats", Name: "stats",
Usage: "show deduplication statistics (imply -all and all revisions)", Usage: "show deduplication statistics (imply -all and all revisions)",
}, },
cli.BoolFlag {
Name: "tabular",
Usage: "show tabular usage and deduplication statistics (imply -stats, -all, and all revisions)",
},
cli.StringFlag { cli.StringFlag {
Name: "storage", Name: "storage",
Usage: "retrieve snapshots from the specified storage", Usage: "retrieve snapshots from the specified storage",

View File

@@ -8,12 +8,14 @@ import (
"io" "io"
"os" "os"
"fmt" "fmt"
"text/tabwriter"
"sort" "sort"
"bytes" "bytes"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"math"
"path" "path"
"io/ioutil" "io/ioutil"
"encoding/json" "encoding/json"
@@ -748,7 +750,7 @@ func (manager *SnapshotManager) ListSnapshots(snapshotID string, revisionsToList
} }
// ListSnapshots shows the information about a snapshot. // ListSnapshots shows the information about a snapshot.
func (manager *SnapshotManager) CheckSnapshots(snapshotID string, revisionsToCheck []int, tag string, showStatistics bool, func (manager *SnapshotManager) CheckSnapshots(snapshotID string, revisionsToCheck []int, tag string, showStatistics bool, showTabular bool,
checkFiles bool, searchFossils bool, resurrect bool) bool { checkFiles bool, searchFossils bool, resurrect bool) bool {
LOG_DEBUG("LIST_PARAMETERS", "id: %s, revisions: %v, tag: %s, showStatistics: %t, checkFiles: %t, searchFossils: %t, resurrect: %t", LOG_DEBUG("LIST_PARAMETERS", "id: %s, revisions: %v, tag: %s, showStatistics: %t, checkFiles: %t, searchFossils: %t, resurrect: %t",
@@ -896,56 +898,145 @@ func (manager *SnapshotManager) CheckSnapshots(snapshotID string, revisionsToChe
snapshotIDIndex += 1 snapshotIDIndex += 1
} }
if showTabular {
manager.ShowStatisticsTabular(snapshotMap, chunkSizeMap, chunkUniqueMap, chunkSnapshotMap)
} else if showStatistics {
manager.ShowStatistics(snapshotMap, chunkSizeMap, chunkUniqueMap, chunkSnapshotMap)
}
if showStatistics { return true
for snapshotID, snapshotList := range snapshotMap { }
snapshotChunks := make(map[string]bool) // Print snapshot and revision statistics
func (manager *SnapshotManager) ShowStatistics(snapshotMap map[string] [] *Snapshot, chunkSizeMap map[string]int64, chunkUniqueMap map[string]bool,
chunkSnapshotMap map[string]int) {
for snapshotID, snapshotList := range snapshotMap {
for _, snapshot := range snapshotList { snapshotChunks := make(map[string]bool)
chunks := make(map[string]bool) for _, snapshot := range snapshotList {
for _, chunkID := range manager.GetSnapshotChunks(snapshot) {
chunks[chunkID] = true
snapshotChunks[chunkID] = true
}
var totalChunkSize int64 chunks := make(map[string]bool)
var uniqueChunkSize int64 for _, chunkID := range manager.GetSnapshotChunks(snapshot) {
chunks[chunkID] = true
for chunkID, _ := range chunks { snapshotChunks[chunkID] = true
chunkSize := chunkSizeMap[chunkID]
totalChunkSize += chunkSize
if chunkUniqueMap[chunkID] {
uniqueChunkSize += chunkSize
}
}
files := ""
if snapshot.FileSize != 0 && snapshot.NumberOfFiles != 0 {
files = fmt.Sprintf("%d files (%s bytes), ", snapshot.NumberOfFiles, PrettyNumber(snapshot.FileSize))
}
LOG_INFO("SNAPSHOT_CHECK", "Snapshot %s at revision %d: %s%s total chunk bytes, %s unique chunk bytes",
snapshot.ID, snapshot.Revision, files, PrettyNumber(totalChunkSize), PrettyNumber(uniqueChunkSize))
} }
var totalChunkSize int64 var totalChunkSize int64
var uniqueChunkSize int64 var uniqueChunkSize int64
for chunkID, _ := range snapshotChunks {
for chunkID, _ := range chunks {
chunkSize := chunkSizeMap[chunkID] chunkSize := chunkSizeMap[chunkID]
totalChunkSize += chunkSize totalChunkSize += chunkSize
if chunkUniqueMap[chunkID] {
if chunkSnapshotMap[chunkID] != -1 {
uniqueChunkSize += chunkSize uniqueChunkSize += chunkSize
} }
} }
LOG_INFO("SNAPSHOT_CHECK", "Snapshot %s all revisions: %s total chunk bytes, %s unique chunk bytes",
snapshotID, PrettyNumber(totalChunkSize), PrettyNumber(uniqueChunkSize)) files := ""
if snapshot.FileSize != 0 && snapshot.NumberOfFiles != 0 {
files = fmt.Sprintf("%d files (%s bytes), ", snapshot.NumberOfFiles, PrettyNumber(snapshot.FileSize))
}
LOG_INFO("SNAPSHOT_CHECK", "Snapshot %s at revision %d: %s%s total chunk bytes, %s unique chunk bytes",
snapshot.ID, snapshot.Revision, files, PrettyNumber(totalChunkSize), PrettyNumber(uniqueChunkSize))
} }
var totalChunkSize int64
var uniqueChunkSize int64
for chunkID, _ := range snapshotChunks {
chunkSize := chunkSizeMap[chunkID]
totalChunkSize += chunkSize
if chunkSnapshotMap[chunkID] != -1 {
uniqueChunkSize += chunkSize
}
}
LOG_INFO("SNAPSHOT_CHECK", "Snapshot %s all revisions: %s total chunk bytes, %s unique chunk bytes",
snapshotID, PrettyNumber(totalChunkSize), PrettyNumber(uniqueChunkSize))
} }
}
return true // Print snapshot and revision statistics in tabular format
func (manager *SnapshotManager) ShowStatisticsTabular(snapshotMap map[string] [] *Snapshot, chunkSizeMap map[string]int64, chunkUniqueMap map[string]bool,
chunkSnapshotMap map[string]int) {
tableBuffer := new(bytes.Buffer)
tableWriter := tabwriter.NewWriter(tableBuffer, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug)
for snapshotID, snapshotList := range snapshotMap {
fmt.Fprintln(tableWriter, "")
fmt.Fprintln(tableWriter, " snap \trev \t \tfiles \tbytes \tchunks \tbytes \tuniq \tbytes \tnew \tbytes \t")
snapshotChunks := make(map[string]bool)
earliestSeenChunks := make(map[string]int)
for _, snapshot := range snapshotList {
for _, chunkID := range manager.GetSnapshotChunks(snapshot) {
if earliestSeenChunks[chunkID] == 0 {
earliestSeenChunks[chunkID] = math.MaxInt64
}
earliestSeenChunks[chunkID] = MinInt(earliestSeenChunks[chunkID], snapshot.Revision)
}
}
for _, snapshot := range snapshotList {
chunks := make(map[string]bool)
for _, chunkID := range manager.GetSnapshotChunks(snapshot) {
chunks[chunkID] = true
snapshotChunks[chunkID] = true
}
var totalChunkSize int64
var uniqueChunkSize int64
var totalChunkCount int64
var uniqueChunkCount int64
var newChunkCount int64
var newChunkSize int64
for chunkID, _ := range chunks {
chunkSize := chunkSizeMap[chunkID]
totalChunkSize += chunkSize
totalChunkCount += 1
if earliestSeenChunks[chunkID] == snapshot.Revision {
newChunkCount += 1
newChunkSize += chunkSize
}
if chunkUniqueMap[chunkID] {
uniqueChunkSize += chunkSize
uniqueChunkCount += 1
}
}
files := " \t "
if snapshot.FileSize != 0 && snapshot.NumberOfFiles != 0 {
files = fmt.Sprintf("%d \t%s", snapshot.NumberOfFiles, PrettyNumber(snapshot.FileSize))
}
creationTime := time.Unix(snapshot.StartTime, 0).Format("2006-01-02 15:04")
fmt.Fprintln(tableWriter, fmt.Sprintf(
"%s \t%d \t@ %s %5s \t%s \t%d \t%s \t%d \t%s \t%d \t%s \t",
snapshotID, snapshot.Revision, creationTime, snapshot.Options, files, totalChunkCount, PrettyNumber(totalChunkSize), uniqueChunkCount, PrettyNumber(uniqueChunkSize), newChunkCount, PrettyNumber(newChunkSize)))
}
var totalChunkSize int64
var uniqueChunkSize int64
var totalChunkCount int64
var uniqueChunkCount int64
for chunkID, _ := range snapshotChunks {
chunkSize := chunkSizeMap[chunkID]
totalChunkSize += chunkSize
totalChunkCount += 1
if chunkSnapshotMap[chunkID] != -1 {
uniqueChunkSize += chunkSize
uniqueChunkCount += 1
}
}
fmt.Fprintln(tableWriter, fmt.Sprintf(
"%s \tall \t \t \t \t%d \t%s \t%d \t%s \t \t \t",
snapshotID, totalChunkCount, PrettyNumber(totalChunkSize), uniqueChunkCount, PrettyNumber(uniqueChunkSize)))
}
tableWriter.Flush()
LOG_INFO("SNAPSHOT_CHECK", tableBuffer.String())
} }
// ConvertSequence converts a sequence of chunk hashes into a sequence of chunk ids. // ConvertSequence converts a sequence of chunk hashes into a sequence of chunk ids.

View File

@@ -450,3 +450,10 @@ func AtoSize(sizeString string) (int) {
return size return size
} }
func MinInt(x, y int) (int) {
if x < y {
return x
}
return y
}