@@ -206,11 +206,11 @@ type tarSplitData struct {
206
206
packer storage.Packer
207
207
}
208
208
209
- func newTarSplitData (level int ) (* tarSplitData , error ) {
209
+ func newTarSplitData (createZstdWriter minimal. CreateZstdWriterFunc ) (* tarSplitData , error ) {
210
210
compressed := bytes .NewBuffer (nil )
211
211
digester := digest .Canonical .Digester ()
212
212
213
- zstdWriter , err := minimal . ZstdWriterWithLevel (io .MultiWriter (compressed , digester .Hash ()), level )
213
+ zstdWriter , err := createZstdWriter (io .MultiWriter (compressed , digester .Hash ()))
214
214
if err != nil {
215
215
return nil , err
216
216
}
@@ -227,11 +227,11 @@ func newTarSplitData(level int) (*tarSplitData, error) {
227
227
}, nil
228
228
}
229
229
230
- func writeZstdChunkedStream (destFile io.Writer , outMetadata map [string ]string , reader io.Reader , level int ) error {
230
+ func writeZstdChunkedStream (destFile io.Writer , outMetadata map [string ]string , reader io.Reader , createZstdWriter minimal. CreateZstdWriterFunc ) error {
231
231
// total written so far. Used to retrieve partial offsets in the file
232
232
dest := ioutils .NewWriteCounter (destFile )
233
233
234
- tarSplitData , err := newTarSplitData (level )
234
+ tarSplitData , err := newTarSplitData (createZstdWriter )
235
235
if err != nil {
236
236
return err
237
237
}
@@ -251,7 +251,7 @@ func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, r
251
251
252
252
buf := make ([]byte , 4096 )
253
253
254
- zstdWriter , err := minimal . ZstdWriterWithLevel (dest , level )
254
+ zstdWriter , err := createZstdWriter (dest )
255
255
if err != nil {
256
256
return err
257
257
}
@@ -420,7 +420,7 @@ func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, r
420
420
UncompressedSize : tarSplitData .uncompressedCounter .Count ,
421
421
}
422
422
423
- return minimal .WriteZstdChunkedManifest (dest , outMetadata , uint64 (dest .Count ), & ts , metadata , level )
423
+ return minimal .WriteZstdChunkedManifest (dest , outMetadata , uint64 (dest .Count ), & ts , metadata , createZstdWriter )
424
424
}
425
425
426
426
type zstdChunkedWriter struct {
@@ -447,7 +447,7 @@ func (w zstdChunkedWriter) Write(p []byte) (int, error) {
447
447
}
448
448
}
449
449
450
- // zstdChunkedWriterWithLevel writes a zstd compressed tarball where each file is
450
+ // makeZstdChunkedWriter writes a zstd compressed tarball where each file is
451
451
// compressed separately so it can be addressed separately. Idea based on CRFS:
452
452
// https://github.com/google/crfs
453
453
// The difference with CRFS is that the zstd compression is used instead of gzip.
@@ -462,12 +462,12 @@ func (w zstdChunkedWriter) Write(p []byte) (int, error) {
462
462
// [SKIPPABLE FRAME 1]: [ZSTD SKIPPABLE FRAME, SIZE=MANIFEST LENGTH][MANIFEST]
463
463
// [SKIPPABLE FRAME 2]: [ZSTD SKIPPABLE FRAME, SIZE=16][MANIFEST_OFFSET][MANIFEST_LENGTH][MANIFEST_LENGTH_UNCOMPRESSED][MANIFEST_TYPE][CHUNKED_ZSTD_MAGIC_NUMBER]
464
464
// MANIFEST_OFFSET, MANIFEST_LENGTH, MANIFEST_LENGTH_UNCOMPRESSED and CHUNKED_ZSTD_MAGIC_NUMBER are 64 bits unsigned in little endian format.
465
- func zstdChunkedWriterWithLevel (out io.Writer , metadata map [string ]string , level int ) (io.WriteCloser , error ) {
465
+ func makeZstdChunkedWriter (out io.Writer , metadata map [string ]string , createZstdWriter minimal. CreateZstdWriterFunc ) (io.WriteCloser , error ) {
466
466
ch := make (chan error , 1 )
467
467
r , w := io .Pipe ()
468
468
469
469
go func () {
470
- ch <- writeZstdChunkedStream (out , metadata , r , level )
470
+ ch <- writeZstdChunkedStream (out , metadata , r , createZstdWriter )
471
471
_ , _ = io .Copy (io .Discard , r ) // Ordinarily writeZstdChunkedStream consumes all of r. If it fails, ensure the write end never blocks and eventually terminates.
472
472
r .Close ()
473
473
close (ch )
@@ -486,5 +486,40 @@ func ZstdCompressor(r io.Writer, metadata map[string]string, level *int) (io.Wri
486
486
level = & l
487
487
}
488
488
489
- return zstdChunkedWriterWithLevel (r , metadata , * level )
489
+ createZstdWriter := func (dest io.Writer ) (minimal.ZstdWriter , error ) {
490
+ return minimal .ZstdWriterWithLevel (dest , * level )
491
+ }
492
+
493
+ return makeZstdChunkedWriter (r , metadata , createZstdWriter )
494
+ }
495
+
496
+ type noCompression struct {
497
+ dest io.Writer
498
+ }
499
+
500
+ func (n * noCompression ) Write (p []byte ) (int , error ) {
501
+ return n .dest .Write (p )
502
+ }
503
+
504
+ func (n * noCompression ) Close () error {
505
+ return nil
506
+ }
507
+
508
+ func (n * noCompression ) Flush () error {
509
+ return nil
510
+ }
511
+
512
+ func (n * noCompression ) Reset (dest io.Writer ) {
513
+ n .dest = dest
514
+ }
515
+
516
+ // NoCompression writes directly to the output file without any compression
517
+ //
518
+ // Such an output does not follow the zstd:chunked spec and cannot be generally consumed; this function
519
+ // only exists for internal purposes and should not be called from outside c/storage.
520
+ func NoCompression (r io.Writer , metadata map [string ]string ) (io.WriteCloser , error ) {
521
+ createZstdWriter := func (dest io.Writer ) (minimal.ZstdWriter , error ) {
522
+ return & noCompression {dest : dest }, nil
523
+ }
524
+ return makeZstdChunkedWriter (r , metadata , createZstdWriter )
490
525
}
0 commit comments