Skip to content

Commit

Permalink
WIP: VMSplice/STDOUT consumer
Browse files Browse the repository at this point in the history
  • Loading branch information
tempusfrangit committed Feb 19, 2024
1 parent c87fb67 commit 7e83587
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ builds:
archives:
- format: binary
name_template: >-
{{ .ProjectName }}_{{ title .Os }}_
{{ .ProjectName }}_{{ tolower .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{end -}}
Expand Down
6 changes: 6 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const (
ConsumerFile = "file"
ConsumerTarExtractor = "tar-extractor"
ConsumerNull = "null"
ConsumerVMSplice = "vmsplice"
ConsumerSTDOut = "stdout"
)

var (
Expand Down Expand Up @@ -162,6 +164,10 @@ func GetConsumer() (consumer.Consumer, error) {
return &consumer.TarExtractor{}, nil
case ConsumerNull:
return &consumer.NullWriter{}, nil
case ConsumerVMSplice:
return &consumer.VMSpliceConsumer{}, nil
case ConsumerSTDOut:
return &consumer.StdoutConsumer{}, nil
default:
return nil, fmt.Errorf("invalid consumer specified: %s", consumerName)
}
Expand Down
21 changes: 21 additions & 0 deletions pkg/consumer/darwin_vmsplice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build darwin

package consumer

import (
"io"

"github.com/replicate/pget/pkg/logging"
)

var _ Consumer = &VMSpliceConsumer{}

type VMSpliceConsumer struct {
}

func (v VMSpliceConsumer) Consume(reader io.Reader, destPath string) error {
logger := logging.GetLogger()
logger.Warn().Msg("'vmsplice' is not supported on darwin, falling back to StdoutConsumer")
return StdoutConsumer{}.Consume(reader, destPath)

}
44 changes: 44 additions & 0 deletions pkg/consumer/linux_vmsplice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//go:build linux

package consumer

import (
"fmt"
"io"
"os"
"syscall"
"unsafe"

"github.com/dustin/go-humanize"
)

var _ Consumer = &VMSpliceConsumer{}

type VMSpliceConsumer struct{}

func (v VMSpliceConsumer) Consume(reader io.Reader, destPath string) error {
// Create the buffer once and reuse it, this is zero additional allocations
buffer := make([]byte, humanize.MiByte)
for {
length, err := reader.Read(buffer)
if err != nil {
if err == io.EOF {
return nil
}
return fmt.Errorf("error reading from reader: %w", err)
}
if length > 0 {
_, _, err := syscall.Syscall6(
syscall.SYS_VMSPLICE,
os.Stdout.Fd(),
uintptr(unsafe.Pointer(
&syscall.Iovec{
Base: &buffer[0],
Len: uint64(length),
})), 1, 0, 0, 0)
if err != 0 {
return fmt.Errorf("error splicing %s to stdout: %w", buffer, err)
}
}
}
}
20 changes: 20 additions & 0 deletions pkg/consumer/stdout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package consumer

import (
"fmt"
"io"
"os"
)

var _ Consumer = &StdoutConsumer{}

type StdoutConsumer struct {
}

func (s StdoutConsumer) Consume(reader io.Reader, destPath string) error {
_, err := io.Copy(os.Stdout, reader)
if err != nil {
return fmt.Errorf("error writing to stdout: %w", err)
}
return nil
}

0 comments on commit 7e83587

Please sign in to comment.