mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-10-06 14:07:50 +00:00
This was implemented by containers/netavark #1369; this commit completes the process by wiring it into Podman. We now respect the CLI order for configured networks - if a user passes `--net net1,net2` we guarantee that net1 will be configured before net2. For containers created before this patch, we don't retain enough information to configure networks in CLI order, so we use alphabetical order instead to still guarantee consistency. No breaking API changes have been made, but we do add a new field to supplement the existing map to (optionally) provide ordering information. The Podman CLI will always pass this. Existing applications that do not will, again, receive] deterministic ordering based on an alphabetical sort of network names. This requires the latest version of Netavark to work properly. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
171 lines
4.1 KiB
Go
171 lines
4.1 KiB
Go
package zstd
|
|
|
|
import (
|
|
"fmt"
|
|
"math/bits"
|
|
|
|
"github.com/klauspost/compress/zstd/internal/xxhash"
|
|
)
|
|
|
|
const (
|
|
dictShardBits = 7
|
|
)
|
|
|
|
type fastBase struct {
|
|
// cur is the offset at the start of hist
|
|
cur int32
|
|
// maximum offset. Should be at least 2x block size.
|
|
maxMatchOff int32
|
|
bufferReset int32
|
|
hist []byte
|
|
crc *xxhash.Digest
|
|
tmp [8]byte
|
|
blk *blockEnc
|
|
lastDict *dict
|
|
lowMem bool
|
|
}
|
|
|
|
// CRC returns the underlying CRC writer.
|
|
func (e *fastBase) CRC() *xxhash.Digest {
|
|
return e.crc
|
|
}
|
|
|
|
// AppendCRC will append the CRC to the destination slice and return it.
|
|
func (e *fastBase) AppendCRC(dst []byte) []byte {
|
|
crc := e.crc.Sum(e.tmp[:0])
|
|
dst = append(dst, crc[7], crc[6], crc[5], crc[4])
|
|
return dst
|
|
}
|
|
|
|
// WindowSize returns the window size of the encoder,
|
|
// or a window size small enough to contain the input size, if > 0.
|
|
func (e *fastBase) WindowSize(size int64) int32 {
|
|
if size > 0 && size < int64(e.maxMatchOff) {
|
|
b := max(
|
|
// Keep minimum window.
|
|
int32(1)<<uint(bits.Len(uint(size))), 1024)
|
|
return b
|
|
}
|
|
return e.maxMatchOff
|
|
}
|
|
|
|
// Block returns the current block.
|
|
func (e *fastBase) Block() *blockEnc {
|
|
return e.blk
|
|
}
|
|
|
|
func (e *fastBase) addBlock(src []byte) int32 {
|
|
if debugAsserts && e.cur > e.bufferReset {
|
|
panic(fmt.Sprintf("ecur (%d) > buffer reset (%d)", e.cur, e.bufferReset))
|
|
}
|
|
// check if we have space already
|
|
if len(e.hist)+len(src) > cap(e.hist) {
|
|
if cap(e.hist) == 0 {
|
|
e.ensureHist(len(src))
|
|
} else {
|
|
if cap(e.hist) < int(e.maxMatchOff+maxCompressedBlockSize) {
|
|
panic(fmt.Errorf("unexpected buffer cap %d, want at least %d with window %d", cap(e.hist), e.maxMatchOff+maxCompressedBlockSize, e.maxMatchOff))
|
|
}
|
|
// Move down
|
|
offset := int32(len(e.hist)) - e.maxMatchOff
|
|
copy(e.hist[0:e.maxMatchOff], e.hist[offset:])
|
|
e.cur += offset
|
|
e.hist = e.hist[:e.maxMatchOff]
|
|
}
|
|
}
|
|
s := int32(len(e.hist))
|
|
e.hist = append(e.hist, src...)
|
|
return s
|
|
}
|
|
|
|
// ensureHist will ensure that history can keep at least this many bytes.
|
|
func (e *fastBase) ensureHist(n int) {
|
|
if cap(e.hist) >= n {
|
|
return
|
|
}
|
|
l := e.maxMatchOff
|
|
if (e.lowMem && e.maxMatchOff > maxCompressedBlockSize) || e.maxMatchOff <= maxCompressedBlockSize {
|
|
l += maxCompressedBlockSize
|
|
} else {
|
|
l += e.maxMatchOff
|
|
}
|
|
// Make it at least 1MB.
|
|
if l < 1<<20 && !e.lowMem {
|
|
l = 1 << 20
|
|
}
|
|
// Make it at least the requested size.
|
|
if l < int32(n) {
|
|
l = int32(n)
|
|
}
|
|
e.hist = make([]byte, 0, l)
|
|
}
|
|
|
|
// useBlock will replace the block with the provided one,
|
|
// but transfer recent offsets from the previous.
|
|
func (e *fastBase) UseBlock(enc *blockEnc) {
|
|
enc.reset(e.blk)
|
|
e.blk = enc
|
|
}
|
|
|
|
func (e *fastBase) matchlen(s, t int32, src []byte) int32 {
|
|
if debugAsserts {
|
|
if s < 0 {
|
|
err := fmt.Sprintf("s (%d) < 0", s)
|
|
panic(err)
|
|
}
|
|
if t < 0 {
|
|
err := fmt.Sprintf("t (%d) < 0", t)
|
|
panic(err)
|
|
}
|
|
if s-t > e.maxMatchOff {
|
|
err := fmt.Sprintf("s (%d) - t (%d) > maxMatchOff (%d)", s, t, e.maxMatchOff)
|
|
panic(err)
|
|
}
|
|
if len(src)-int(s) > maxCompressedBlockSize {
|
|
panic(fmt.Sprintf("len(src)-s (%d) > maxCompressedBlockSize (%d)", len(src)-int(s), maxCompressedBlockSize))
|
|
}
|
|
}
|
|
return int32(matchLen(src[s:], src[t:]))
|
|
}
|
|
|
|
// Reset the encoding table.
|
|
func (e *fastBase) resetBase(d *dict, singleBlock bool) {
|
|
if e.blk == nil {
|
|
e.blk = &blockEnc{lowMem: e.lowMem}
|
|
e.blk.init()
|
|
} else {
|
|
e.blk.reset(nil)
|
|
}
|
|
e.blk.initNewEncode()
|
|
if e.crc == nil {
|
|
e.crc = xxhash.New()
|
|
} else {
|
|
e.crc.Reset()
|
|
}
|
|
e.blk.dictLitEnc = nil
|
|
if d != nil {
|
|
low := e.lowMem
|
|
if singleBlock {
|
|
e.lowMem = true
|
|
}
|
|
e.ensureHist(d.ContentSize() + maxCompressedBlockSize)
|
|
e.lowMem = low
|
|
}
|
|
|
|
// We offset current position so everything will be out of reach.
|
|
// If above reset line, history will be purged.
|
|
if e.cur < e.bufferReset {
|
|
e.cur += e.maxMatchOff + int32(len(e.hist))
|
|
}
|
|
e.hist = e.hist[:0]
|
|
if d != nil {
|
|
// Set offsets (currently not used)
|
|
for i, off := range d.offsets {
|
|
e.blk.recentOffsets[i] = uint32(off)
|
|
e.blk.prevRecentOffsets[i] = e.blk.recentOffsets[i]
|
|
}
|
|
// Transfer litenc.
|
|
e.blk.dictLitEnc = d.litEnc
|
|
e.hist = append(e.hist, d.content...)
|
|
}
|
|
}
|