diff --git a/cli/command_benchmark_compression.go b/cli/command_benchmark_compression.go index 9636503c6..2ba751aad 100644 --- a/cli/command_benchmark_compression.go +++ b/cli/command_benchmark_compression.go @@ -26,6 +26,7 @@ type commandBenchmarkCompression struct { verifyStable bool optionPrint bool parallel int + deprecated bool out textOutput } @@ -39,6 +40,7 @@ func (c *commandBenchmarkCompression) setup(svc appServices, parent commandParen cmd.Flag("parallel", "Number of parallel goroutines").Default("1").IntVar(&c.parallel) cmd.Flag("verify-stable", "Verify that compression is stable").BoolVar(&c.verifyStable) cmd.Flag("print-options", "Print out options usable for repository creation").BoolVar(&c.optionPrint) + cmd.Flag("deprecated", "Included deprecated compression algorithms").BoolVar(&c.deprecated) cmd.Action(svc.noRepositoryAction(c.run)) c.out.setup(svc) } @@ -107,6 +109,10 @@ func (c *commandBenchmarkCompression) run(ctx context.Context) error { log(ctx).Infof("Repeating %v times per compression method (total %v). Override with --repeat=N.", repeatCount, units.BytesStringBase2(int64(repeatCount*len(data)))) for name, comp := range compression.ByName { + if compression.IsDeprecated[name] && !c.deprecated { + continue + } + log(ctx).Infof("Benchmarking compressor '%v'...", name) cnt := repeatCount @@ -197,13 +203,19 @@ func (c *commandBenchmarkCompression) printResults(results []compressionBechmark c.out.printStdout("------------------------------------------------------------------------------------------------\n") for ndx, r := range results { - c.out.printStdout("%3d. %-26v %-12v %-12v %-8v %v", + maybeDeprecated := "" + if compression.IsDeprecated[r.compression] { + maybeDeprecated = " (deprecated)" + } + + c.out.printStdout("%3d. %-26v %-12v %-12v %-8v %v%v", ndx, r.compression, units.BytesStringBase2(r.compressedSize), units.BytesStringBase2(int64(r.throughput))+"/s", r.allocations, units.BytesStringBase2(r.allocBytes), + maybeDeprecated, ) if c.optionPrint { diff --git a/go.mod b/go.mod index dc8cc84ed..c9d25d105 100644 --- a/go.mod +++ b/go.mod @@ -83,7 +83,7 @@ require ( github.com/googleapis/gax-go/v2 v2.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b + github.com/kopia/htmluibuild v0.0.0-20220703174648-d70429a8dad7 github.com/kr/fs v0.1.0 // indirect github.com/mattn/go-ieproxy v0.0.1 // indirect github.com/mattn/go-isatty v0.0.14 // indirect diff --git a/go.sum b/go.sum index 74b030ef9..661bf693f 100644 --- a/go.sum +++ b/go.sum @@ -349,6 +349,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b h1:ox9MBvtiRvcnVjYQd5XYmk9IhRGMo7lK/pbJA1Ud2EY= github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw= +github.com/kopia/htmluibuild v0.0.0-20220703174648-d70429a8dad7 h1:OdKsyukYW8aww2naIL2HECJbcuicvJrOb884tI+2FWM= +github.com/kopia/htmluibuild v0.0.0-20220703174648-d70429a8dad7/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= diff --git a/internal/server/api_repo.go b/internal/server/api_repo.go index 5aea68980..806658917 100644 --- a/internal/server/api_repo.go +++ b/internal/server/api_repo.go @@ -251,25 +251,59 @@ func handleRepoSetDescription(ctx context.Context, rc requestContext) (interface func handleRepoSupportedAlgorithms(ctx context.Context, rc requestContext) (interface{}, *apiError) { res := &serverapi.SupportedAlgorithmsResponse{ - DefaultHashAlgorithm: hashing.DefaultAlgorithm, - HashAlgorithms: hashing.SupportedAlgorithms(), + DefaultHashAlgorithm: hashing.DefaultAlgorithm, + SupportedHashAlgorithms: toAlgorithmInfo(hashing.SupportedAlgorithms(), neverDeprecated), - DefaultEncryptionAlgorithm: encryption.DefaultAlgorithm, - EncryptionAlgorithms: encryption.SupportedAlgorithms(false), + DefaultEncryptionAlgorithm: encryption.DefaultAlgorithm, + SupportedEncryptionAlgorithms: toAlgorithmInfo(encryption.SupportedAlgorithms(false), neverDeprecated), - DefaultSplitterAlgorithm: splitter.DefaultAlgorithm, - SplitterAlgorithms: splitter.SupportedAlgorithms(), + DefaultSplitterAlgorithm: splitter.DefaultAlgorithm, + SupportedSplitterAlgorithms: toAlgorithmInfo(splitter.SupportedAlgorithms(), neverDeprecated), } for k := range compression.ByName { - res.CompressionAlgorithms = append(res.CompressionAlgorithms, string(k)) + res.SupportedCompressionAlgorithms = append(res.SupportedCompressionAlgorithms, serverapi.AlgorithmInfo{ + ID: string(k), + Deprecated: compression.IsDeprecated[k], + }) } - sort.Strings(res.CompressionAlgorithms) + sortAlgorithms(res.SupportedHashAlgorithms) + sortAlgorithms(res.SupportedEncryptionAlgorithms) + sortAlgorithms(res.SupportedCompressionAlgorithms) + sortAlgorithms(res.SupportedSplitterAlgorithms) return res, nil } +func neverDeprecated(n string) bool { + return false +} + +func toAlgorithmInfo(names []string, isDeprecated func(id string) bool) []serverapi.AlgorithmInfo { + var result []serverapi.AlgorithmInfo + + for _, n := range names { + result = append(result, serverapi.AlgorithmInfo{ + ID: n, + Deprecated: isDeprecated(n), + }) + } + + return result +} + +func sortAlgorithms(a []serverapi.AlgorithmInfo) { + sort.Slice(a, func(i, j int) bool { + if l, r := a[i].Deprecated, a[j].Deprecated; l != r { + // non-deprecated first + return !l + } + + return a[i].ID < a[j].ID + }) +} + func handleRepoGetThrottle(ctx context.Context, rc requestContext) (interface{}, *apiError) { dr, ok := rc.rep.(repo.DirectRepository) if !ok { diff --git a/internal/serverapi/serverapi.go b/internal/serverapi/serverapi.go index da980b04e..7c4ec5ff1 100644 --- a/internal/serverapi/serverapi.go +++ b/internal/serverapi/serverapi.go @@ -128,15 +128,22 @@ type ConnectRepositoryRequest struct { SyncWaitTimeSeconds int `json:"syncWaitTime"` // if non-zero, force particular wait time, negative == forever } +// AlgorithmInfo is an information about a single algorithm. +type AlgorithmInfo struct { + ID string `json:"id"` + Deprecated bool `json:"deprecated"` +} + // SupportedAlgorithmsResponse returns the list of supported algorithms for repository creation. type SupportedAlgorithmsResponse struct { - DefaultHashAlgorithm string `json:"defaultHash"` - DefaultEncryptionAlgorithm string `json:"defaultEncryption"` - DefaultSplitterAlgorithm string `json:"defaultSplitter"` - HashAlgorithms []string `json:"hash"` - EncryptionAlgorithms []string `json:"encryption"` - SplitterAlgorithms []string `json:"splitter"` - CompressionAlgorithms []string `json:"compression"` + DefaultHashAlgorithm string `json:"defaultHash"` + DefaultEncryptionAlgorithm string `json:"defaultEncryption"` + DefaultSplitterAlgorithm string `json:"defaultSplitter"` + + SupportedHashAlgorithms []AlgorithmInfo `json:"hash"` + SupportedEncryptionAlgorithms []AlgorithmInfo `json:"encryption"` + SupportedSplitterAlgorithms []AlgorithmInfo `json:"splitter"` + SupportedCompressionAlgorithms []AlgorithmInfo `json:"compression"` } // CreateSnapshotSourceRequest contains request to create snapshot source and optionally create first snapshot. diff --git a/repo/compression/compressor.go b/repo/compression/compressor.go index f0300ff46..debdf2c1a 100644 --- a/repo/compression/compressor.go +++ b/repo/compression/compressor.go @@ -28,6 +28,7 @@ type Compressor interface { ByHeaderID = map[HeaderID]Compressor{} ByName = map[Name]Compressor{} HeaderIDToName = map[HeaderID]Name{} + IsDeprecated = map[Name]bool{} ) // RegisterCompressor registers the provided compressor implementation. @@ -45,6 +46,13 @@ func RegisterCompressor(name Name, c Compressor) { HeaderIDToName[c.HeaderID()] = name } +// RegisterDeprecatedCompressor registers the provided compressor implementation. +func RegisterDeprecatedCompressor(name Name, c Compressor) { + RegisterCompressor(name, c) + + IsDeprecated[name] = true +} + func compressionHeader(id HeaderID) []byte { b := make([]byte, compressionHeaderSize) binary.BigEndian.PutUint32(b, uint32(id)) diff --git a/repo/compression/compressor_lz4.go b/repo/compression/compressor_lz4.go index 5ce929769..e5b8c1ec5 100644 --- a/repo/compression/compressor_lz4.go +++ b/repo/compression/compressor_lz4.go @@ -11,7 +11,7 @@ ) func init() { - RegisterCompressor("lz4", newLZ4Compressor(headerLZ4Default)) + RegisterDeprecatedCompressor("lz4", newLZ4Compressor(headerLZ4Default)) } func newLZ4Compressor(id HeaderID) Compressor { diff --git a/repo/compression/compressor_zstd.go b/repo/compression/compressor_zstd.go index e96646b66..c57216729 100644 --- a/repo/compression/compressor_zstd.go +++ b/repo/compression/compressor_zstd.go @@ -14,7 +14,7 @@ func init() { RegisterCompressor("zstd", newZstdCompressor(HeaderZstdDefault, zstd.SpeedDefault)) RegisterCompressor("zstd-fastest", newZstdCompressor(HeaderZstdFastest, zstd.SpeedFastest)) RegisterCompressor("zstd-better-compression", newZstdCompressor(HeaderZstdBetterCompression, zstd.SpeedBetterCompression)) - RegisterCompressor("zstd-best-compression", newZstdCompressor(HeaderZstdBestCompression, zstd.SpeedBestCompression)) + RegisterDeprecatedCompressor("zstd-best-compression", newZstdCompressor(HeaderZstdBestCompression, zstd.SpeedBestCompression)) } func newZstdCompressor(id HeaderID, level zstd.EncoderLevel) Compressor {