[archiver] Add support for progress reporting and statistics.

This commit is contained in:
Ciprian Dorin Craciun 2021-11-18 18:15:16 +02:00
parent 7aae2fc9f5
commit b295bbafb8

View file

@ -17,6 +17,7 @@ import "os"
import "sort" import "sort"
import "strings" import "strings"
import "syscall" import "syscall"
import "time"
import "github.com/colinmarc/cdb" import "github.com/colinmarc/cdb"
@ -28,19 +29,30 @@ import . "github.com/volution/kawipiko/lib/archiver"
type context struct { type context struct {
cdbWriter *cdb.Writer cdbWriter *cdb.Writer
cdbWriteCount int
cdbWriteKeySize int
cdbWriteDataSize int
storedFilePaths []string storedFilePaths []string
storedFolderPaths []string storedFolderPaths []string
storedDataMeta map[string]bool storedDataMeta map[string]bool
storedDataContent map[string]bool storedDataContent map[string]bool
storedDataContentMeta map[string]map[string]string storedDataContentMeta map[string]map[string]string
storedFiles map[[2]uint64][2]string storedFiles map[[2]uint64][2]string
archivedReferences uint
compress string compress string
dataUncompressedCount int
dataUncompressedSize int
dataCompressedCount int
dataCompressedSize int
includeIndex bool includeIndex bool
includeStripped bool includeStripped bool
includeCache bool includeCache bool
includeEtag bool includeEtag bool
includeFileListing bool includeFileListing bool
includeFolderListing bool includeFolderListing bool
progress bool
progressStarted time.Time
progressLast time.Time
debug bool debug bool
} }
@ -284,6 +296,9 @@ func archiveDataContent (_context *context, _fingerprintContent string, _dataCon
if _error := _context.cdbWriter.Put ([]byte (_key), _dataContent); _error != nil { if _error := _context.cdbWriter.Put ([]byte (_key), _dataContent); _error != nil {
return _error return _error
} }
_context.cdbWriteCount += 1
_context.cdbWriteKeySize += len (_key)
_context.cdbWriteDataSize += len (_dataContent)
} }
_context.storedDataContent[_fingerprintContent] = true _context.storedDataContent[_fingerprintContent] = true
@ -306,6 +321,9 @@ func archiveDataMeta (_context *context, _fingerprintMeta string, _dataMeta []by
if _error := _context.cdbWriter.Put ([]byte (_key), _dataMeta); _error != nil { if _error := _context.cdbWriter.Put ([]byte (_key), _dataMeta); _error != nil {
return _error return _error
} }
_context.cdbWriteCount += 1
_context.cdbWriteKeySize += len (_key)
_context.cdbWriteDataSize += len (_dataMeta)
} }
_context.storedDataMeta[_fingerprintMeta] = true _context.storedDataMeta[_fingerprintMeta] = true
@ -326,16 +344,42 @@ func archiveReference (_context *context, _namespace string, _pathInArchive stri
default : default :
return fmt.Errorf ("[051a102a]") return fmt.Errorf ("[051a102a]")
} }
_context.archivedReferences += 1
_key := fmt.Sprintf ("%s:%s", _namespace, _pathInArchive)
if _context.debug { if _context.debug {
log.Printf ("[ ] reference ++ `%s` :: `%s` -> `%s` ~ `%s`\n", _namespace, _pathInArchive, _fingerprintContent[:16], _fingerprintMeta[:16]) log.Printf ("[ ] reference ++ `%s` :: `%s` -> `%s` ~ `%s`\n", _namespace, _pathInArchive, _fingerprintContent[:16], _fingerprintMeta[:16])
} }
_key := fmt.Sprintf ("%s:%s", _namespace, _pathInArchive)
_fingerprints := fmt.Sprintf ("%s:%s", _fingerprintContent, _fingerprintMeta) _fingerprints := fmt.Sprintf ("%s:%s", _fingerprintContent, _fingerprintMeta)
if _error := _context.cdbWriter.Put ([]byte (_key), []byte (_fingerprints)); _error != nil { if _error := _context.cdbWriter.Put ([]byte (_key), []byte (_fingerprints)); _error != nil {
return _error return _error
} }
_context.cdbWriteCount += 1
_context.cdbWriteKeySize += len (_key)
_context.cdbWriteDataSize += len (_fingerprints)
if _context.progress {
if _context.archivedReferences <= 1 {
_context.progressLast = time.Now ()
}
if ((_context.archivedReferences % 1000) == 0) || (((_context.archivedReferences % 10) == 0) && (time.Since (_context.progressLast) .Seconds () >= 6)) {
log.Printf ("[ ] pogress -- %0.2f minutes -- %d files, %d folders, %0.2f MiB (%0.2f MiB/s) -- %d compressed (%0.2f MiB, %0.2f%%) -- %d records (%0.2f MiB)\n",
time.Since (_context.progressStarted) .Minutes (),
len (_context.storedFilePaths),
len (_context.storedFolderPaths),
float32 (_context.dataUncompressedSize) / 1024 / 1024,
float64 (_context.dataUncompressedSize) / 1024 / 1024 / (time.Since (_context.progressStarted) .Seconds () + 0.001),
_context.dataCompressedCount,
float32 (_context.dataUncompressedSize - _context.dataCompressedSize) / 1024 / 1024,
(float32 (_context.dataUncompressedSize - _context.dataCompressedSize) / float32 (_context.dataUncompressedSize) * 100),
_context.cdbWriteCount,
float32 (_context.cdbWriteKeySize + _context.cdbWriteDataSize) / 1024 / 1024,
)
_context.progressLast = time.Now ()
}
}
return nil return nil
} }
@ -410,6 +454,13 @@ func prepareDataContent (_context *context, _pathResolved string, _pathInArchive
} }
} }
_context.dataUncompressedSize += _dataUncompressedSize
_context.dataUncompressedCount += 1
_context.dataCompressedSize += _dataSize
if _dataSize != _dataUncompressedSize {
_context.dataCompressedCount += 1
}
_dataMeta := make (map[string]string, 16) _dataMeta := make (map[string]string, 16)
// _dataMeta["Content-Length"] = fmt.Sprintf ("%d", _dataSize) // _dataMeta["Content-Length"] = fmt.Sprintf ("%d", _dataSize)
@ -527,8 +578,11 @@ func walkPath (_context *context, _pathResolved string, _pathInArchive string, _
if _stream, _error := os.Open (_pathResolved); _error == nil { if _stream, _error := os.Open (_pathResolved); _error == nil {
defer _stream.Close () defer _stream.Close ()
_loop : for { _loop : for {
switch _buffer, _error := _stream.Readdir (128); _error { switch _buffer, _error := _stream.Readdir (1024); _error {
case nil : case nil :
if _context.debug && (len (_childsStat) > 0) {
log.Printf ("[ ] folder ~~ `%s` ~~ %d\n", _pathInArchive, len (_childsStat))
}
for _, _childStat := range _buffer { for _, _childStat := range _buffer {
_childName := _childStat.Name () _childName := _childStat.Name ()
@ -641,6 +695,7 @@ func main_0 () (error) {
var _includeEtag bool var _includeEtag bool
var _includeFileListing bool var _includeFileListing bool
var _includeFolderListing bool var _includeFolderListing bool
var _progress bool
var _debug bool var _debug bool
{ {
@ -675,6 +730,7 @@ func main_0 () (error) {
--exclude-file-listing --exclude-file-listing
--include-folder-listing --include-folder-listing
--progress
--debug --debug
** for details see: ** for details see:
@ -692,6 +748,7 @@ func main_0 () (error) {
_includeEtag_0 := _flags.Bool ("include-etag", false, "") _includeEtag_0 := _flags.Bool ("include-etag", false, "")
_excludeFileListing_0 := _flags.Bool ("exclude-file-listing", false, "") _excludeFileListing_0 := _flags.Bool ("exclude-file-listing", false, "")
_includeFolderListing_0 := _flags.Bool ("include-folder-listing", false, "") _includeFolderListing_0 := _flags.Bool ("include-folder-listing", false, "")
_progress_0 := _flags.Bool ("progress", false, "")
_debug_0 := _flags.Bool ("debug", false, "") _debug_0 := _flags.Bool ("debug", false, "")
FlagsParse (_flags, 0, 0) FlagsParse (_flags, 0, 0)
@ -705,6 +762,7 @@ func main_0 () (error) {
_includeEtag = *_includeEtag_0 _includeEtag = *_includeEtag_0
_includeFileListing = ! *_excludeFileListing_0 _includeFileListing = ! *_excludeFileListing_0
_includeFolderListing = *_includeFolderListing_0 _includeFolderListing = *_includeFolderListing_0
_progress = *_progress_0
_debug = *_debug_0 _debug = *_debug_0
if _sourcesFolder == "" { if _sourcesFolder == "" {
@ -723,10 +781,6 @@ func main_0 () (error) {
AbortError (_error, "[85234ba0] failed creating archive (while opening)!") AbortError (_error, "[85234ba0] failed creating archive (while opening)!")
} }
if _error := _cdbWriter.Put ([]byte (NamespaceSchemaVersion), []byte (CurrentSchemaVersion)); _error != nil {
AbortError (_error, "[43228812] failed writing archive!")
}
_context := & context { _context := & context {
cdbWriter : _cdbWriter, cdbWriter : _cdbWriter,
storedFilePaths : make ([]string, 0, 16 * 1024), storedFilePaths : make ([]string, 0, 16 * 1024),
@ -742,9 +796,19 @@ func main_0 () (error) {
includeEtag : _includeEtag, includeEtag : _includeEtag,
includeFileListing : _includeFileListing, includeFileListing : _includeFileListing,
includeFolderListing : _includeFolderListing, includeFolderListing : _includeFolderListing,
progress : _progress,
debug : _debug, debug : _debug,
} }
_context.progressStarted = time.Now ()
if _error := _context.cdbWriter.Put ([]byte (NamespaceSchemaVersion), []byte (CurrentSchemaVersion)); _error != nil {
AbortError (_error, "[43228812] failed writing archive!")
}
_context.cdbWriteCount += 1
_context.cdbWriteKeySize += len (NamespaceSchemaVersion)
_context.cdbWriteDataSize += len (CurrentSchemaVersion)
if _, _error := walkPath (_context, _sourcesFolder, "/", filepath.Base (_sourcesFolder), nil, true); _error != nil { if _, _error := walkPath (_context, _sourcesFolder, "/", filepath.Base (_sourcesFolder), nil, true); _error != nil {
AbortError (_error, "[b6a19ef4] failed walking folder!") AbortError (_error, "[b6a19ef4] failed walking folder!")
} }
@ -755,9 +819,12 @@ func main_0 () (error) {
_buffer = append (_buffer, _path ...) _buffer = append (_buffer, _path ...)
_buffer = append (_buffer, '\n') _buffer = append (_buffer, '\n')
} }
if _error := _cdbWriter.Put ([]byte (NamespaceFilesIndex), _buffer); _error != nil { if _error := _context.cdbWriter.Put ([]byte (NamespaceFilesIndex), _buffer); _error != nil {
AbortError (_error, "[1dbdde05] failed writing archive!") AbortError (_error, "[1dbdde05] failed writing archive!")
} }
_context.cdbWriteCount += 1
_context.cdbWriteKeySize += len (NamespaceFilesIndex)
_context.cdbWriteDataSize += len (_buffer)
} }
if _includeFolderListing { if _includeFolderListing {
@ -766,14 +833,33 @@ func main_0 () (error) {
_buffer = append (_buffer, _path ...) _buffer = append (_buffer, _path ...)
_buffer = append (_buffer, '\n') _buffer = append (_buffer, '\n')
} }
if _error := _cdbWriter.Put ([]byte (NamespaceFoldersIndex), _buffer); _error != nil { if _error := _context.cdbWriter.Put ([]byte (NamespaceFoldersIndex), _buffer); _error != nil {
AbortError (_error, "[e2dd2de0] failed writing archive!") AbortError (_error, "[e2dd2de0] failed writing archive!")
} }
_context.cdbWriteCount += 1
_context.cdbWriteKeySize += len (NamespaceFilesIndex)
_context.cdbWriteDataSize += len (_buffer)
} }
if _error := _cdbWriter.Close (); _error != nil { if _error := _context.cdbWriter.Close (); _error != nil {
AbortError (_error, "[bbfb8478] failed creating archive (while closing)!") AbortError (_error, "[bbfb8478] failed creating archive (while closing)!")
} }
_context.cdbWriter = nil
if true {
log.Printf ("[ ] completed -- %0.2f minutes -- %d files, %d folders, %0.2f MiB (%0.2f MiB/s) -- %d compressed (%0.2f MiB, %0.2f%%) -- %d records (%0.2f MiB)\n",
time.Since (_context.progressStarted) .Minutes (),
len (_context.storedFilePaths),
len (_context.storedFolderPaths),
float32 (_context.dataUncompressedSize) / 1024 / 1024,
float64 (_context.dataUncompressedSize) / 1024 / 1024 / (time.Since (_context.progressStarted) .Seconds () + 0.001),
_context.dataCompressedCount,
float32 (_context.dataUncompressedSize - _context.dataCompressedSize) / 1024 / 1024,
(float32 (_context.dataUncompressedSize - _context.dataCompressedSize) / float32 (_context.dataUncompressedSize) * 100),
_context.cdbWriteCount,
float32 (_context.cdbWriteKeySize + _context.cdbWriteDataSize) / 1024 / 1024,
)
}
return nil return nil
} }