Repository navigation
Expand file tree
/
Copy pathcompression.go
More file actions
90 lines (82 loc) · 2.96 KB
/
Copy pathcompression.go
File metadata and controls
90 lines (82 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package dstore
import (
"compress/gzip"
"fmt"
"net/url"
"strconv"
"strings"
)
// newCommonStore builds the common part of a store from its constructor
// arguments and opts.
//
// The compression type is the Compression option when given, compressionType
// otherwise. The `compression_config` query parameter of baseURL tunes it: for
// zstd, the encoder level and window as `<level>` or `<level>/<window MiB>`
// (`best`, `better/32`, `best/64`), optionally followed by the decoder settings
// `lowmem=<bool>` and `pool=<name>` (`best/32,lowmem=false,pool=blocks`, see
// parseZstdConfig); for gzip, an integer level from -2 to 9 as defined by
// compress/gzip (`1` fastest, `9` smallest). It is an error on a store without
// compression, or when the value is not valid for its compression.
//
// zstd stores read with the `default` decoder pool unless the parameter names
// another one or `pool=none`.
func newCommonStore(baseURL *url.URL, extension, compressionType string, overwrite bool, opts ...Option) (*commonStore, error) {
conf := config{}
for _, opt := range opts {
opt.apply(&conf)
}
if conf.compression != "" {
compressionType = conf.compression
}
common := &commonStore{
compressionType: compressionType,
extension: extension,
overwrite: overwrite,
uncompressedReadCallback: conf.uncompressedReadCallback,
compressedReadCallback: conf.compressedReadCallback,
uncompressedWriteCallback: conf.uncompressedWriteCallback,
compressedWriteCallback: conf.compressedWriteCallback,
}
spec := baseURL.Query().Get("compression_config")
if spec == "" {
if compressionType == "zstd" {
conf, err := parseZstdConfig("")
if err != nil {
return nil, err
}
common.zstdConfig = conf
common.zstdDecoders = zstdDecoderPoolFor(conf)
}
return common, nil
}
switch compressionType {
case "zstd":
conf, err := parseZstdConfig(spec)
if err != nil {
return nil, err
}
common.zstdConfig = conf
common.zstdDecoders = zstdDecoderPoolFor(conf)
case "gzip":
if strings.ContainsAny(spec, ",=") {
return nil, fmt.Errorf("invalid compression_config %q for gzip: lowmem and pool apply to zstd stores only, expected an integer level from %d to %d", spec, gzip.HuffmanOnly, gzip.BestCompression)
}
level, err := parseGzipConfig(spec)
if err != nil {
return nil, err
}
common.gzipLevel = &level
default:
return nil, fmt.Errorf("compression_config %q requires a zstd or gzip store, this store has no compression", spec)
}
return common, nil
}
// parseGzipConfig reads a gzip compression level, an integer from
// gzip.HuffmanOnly (-2) to gzip.BestCompression (9).
func parseGzipConfig(spec string) (int, error) {
level, err := strconv.Atoi(spec)
if err != nil || level < gzip.HuffmanOnly || level > gzip.BestCompression {
return 0, fmt.Errorf("invalid compression_config %q for gzip: expected an integer level from %d to %d", spec, gzip.HuffmanOnly, gzip.BestCompression)
}
return level, nil
}