summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/common_test.go1
-rw-r--r--libpod/container.go8
-rw-r--r--libpod/logs/log.go88
-rw-r--r--libpod/logs/reversereader/reversereader.go66
-rw-r--r--libpod/options.go3
-rw-r--r--libpod/runtime_pod_infra_linux.go2
-rw-r--r--libpod/util_test.go3
7 files changed, 136 insertions, 35 deletions
diff --git a/libpod/common_test.go b/libpod/common_test.go
index 83b162c8a..63ea4f41b 100644
--- a/libpod/common_test.go
+++ b/libpod/common_test.go
@@ -23,7 +23,6 @@ func getTestContainer(id, name string, manager lock.Manager) (*Container, error)
Name: name,
RootfsImageID: id,
RootfsImageName: "testimg",
- ImageVolumes: true,
StaticDir: "/does/not/exist/",
LogPath: "/does/not/exist/",
Stdin: true,
diff --git a/libpod/container.go b/libpod/container.go
index 5e5c8ab26..dbd15e55f 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -249,8 +249,6 @@ type ContainerConfig struct {
RootfsImageName string `json:"rootfsImageName,omitempty"`
// Rootfs to use for the container, this conflicts with RootfsImageID
Rootfs string `json:"rootfs,omitempty"`
- // Whether to mount volumes specified in the image.
- ImageVolumes bool `json:"imageVolumes"`
// Src path to be mounted on /dev/shm in container.
ShmDir string `json:"ShmDir,omitempty"`
// Size of the container's SHM.
@@ -510,12 +508,6 @@ func (c *Container) Image() (string, string) {
return c.config.RootfsImageID, c.config.RootfsImageName
}
-// ImageVolumes returns whether the container is configured to create
-// persistent volumes requested by the image
-func (c *Container) ImageVolumes() bool {
- return c.config.ImageVolumes
-}
-
// ShmDir returns the sources path to be mounted on /dev/shm in container
func (c *Container) ShmDir() string {
return c.config.ShmDir
diff --git a/libpod/logs/log.go b/libpod/logs/log.go
index 9a7bcb5be..bd918abae 100644
--- a/libpod/logs/log.go
+++ b/libpod/logs/log.go
@@ -2,13 +2,16 @@ package logs
import (
"fmt"
- "io/ioutil"
+ "io"
+ "os"
"strings"
"sync"
"time"
+ "github.com/containers/libpod/libpod/logs/reversereader"
"github.com/hpcloud/tail"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
const (
@@ -74,43 +77,84 @@ func GetLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error
func getTailLog(path string, tail int) ([]*LogLine, error) {
var (
- tailLog []*LogLine
- nlls []*LogLine
- tailCounter int
- partial string
+ nlls []*LogLine
+ nllCounter int
+ leftover string
+ partial string
+ tailLog []*LogLine
)
- content, err := ioutil.ReadFile(path)
+ f, err := os.Open(path)
if err != nil {
return nil, err
}
- splitContent := strings.Split(string(content), "\n")
- // We read the content in reverse and add each nll until we have the same
- // number of F type messages as the desired tail
- for i := len(splitContent) - 1; i >= 0; i-- {
- if len(splitContent[i]) == 0 {
- continue
- }
- nll, err := NewLogLine(splitContent[i])
- if err != nil {
- return nil, err
+ rr, err := reversereader.NewReverseReader(f)
+ if err != nil {
+ return nil, err
+ }
+
+ inputs := make(chan []string)
+ go func() {
+ for {
+ s, err := rr.Read()
+ if err != nil {
+ if errors.Cause(err) == io.EOF {
+ inputs <- []string{leftover}
+ close(inputs)
+ break
+ }
+ logrus.Error(err)
+ close(inputs)
+ }
+ line := strings.Split(s+leftover, "\n")
+ if len(line) > 1 {
+ inputs <- line[1:]
+ }
+ leftover = line[0]
}
- nlls = append(nlls, nll)
- if !nll.Partial() {
- tailCounter++
+ }()
+
+ for i := range inputs {
+ // the incoming array is FIFO; we want FIFO so
+ // reverse the slice read order
+ for j := len(i) - 1; j >= 0; j-- {
+ // lines that are "" are junk
+ if len(i[j]) < 1 {
+ continue
+ }
+ // read the content in reverse and add each nll until we have the same
+ // number of F type messages as the desired tail
+ nll, err := NewLogLine(i[j])
+ if err != nil {
+ return nil, err
+ }
+ nlls = append(nlls, nll)
+ if !nll.Partial() {
+ nllCounter++
+ }
}
- if tailCounter == tail {
+ // if we have enough loglines, we can hangup
+ if nllCounter >= tail {
+ if err := f.Close(); err != nil {
+ logrus.Error(err)
+ }
break
}
}
- // Now we iterate the results and assemble partial messages to become full messages
+
+ // re-assemble the log lines and trim (if needed) to the
+ // tail length
for _, nll := range nlls {
if nll.Partial() {
partial += nll.Msg
} else {
nll.Msg += partial
- tailLog = append(tailLog, nll)
+ // prepend because we need to reverse the order again to FIFO
+ tailLog = append([]*LogLine{nll}, tailLog...)
partial = ""
}
+ if len(tailLog) == tail {
+ break
+ }
}
return tailLog, nil
}
diff --git a/libpod/logs/reversereader/reversereader.go b/libpod/logs/reversereader/reversereader.go
new file mode 100644
index 000000000..72d9ad975
--- /dev/null
+++ b/libpod/logs/reversereader/reversereader.go
@@ -0,0 +1,66 @@
+package reversereader
+
+import (
+ "io"
+ "os"
+
+ "github.com/pkg/errors"
+)
+
+// ReverseReader structure for reading a file backwards
+type ReverseReader struct {
+ reader *os.File
+ offset int64
+ readSize int64
+}
+
+// NewReverseReader returns a reader that reads from the end of a file
+// rather than the beginning. It sets the readsize to pagesize and determines
+// the first offset using using modulus.
+func NewReverseReader(reader *os.File) (*ReverseReader, error) {
+ // pagesize should be safe for memory use and file reads should be on page
+ // boundaries as well
+ pageSize := int64(os.Getpagesize())
+ stat, err := reader.Stat()
+ if err != nil {
+ return nil, err
+ }
+ // figure out the last page boundary
+ remainder := stat.Size() % pageSize
+ end, err := reader.Seek(0, 2)
+ if err != nil {
+ return nil, err
+ }
+ // set offset (starting position) to the last page boundary or
+ // zero if fits in one page
+ startOffset := end - remainder
+ if startOffset < 0 {
+ startOffset = 0
+ }
+ rr := ReverseReader{
+ reader: reader,
+ offset: startOffset,
+ readSize: pageSize,
+ }
+ return &rr, nil
+}
+
+// ReverseReader reads from a given offset to the previous offset and
+// then sets the newoff set one pagesize less than the previous read.
+func (r *ReverseReader) Read() (string, error) {
+ if r.offset < 0 {
+ return "", errors.Wrap(io.EOF, "at beginning of file")
+ }
+ // Read from given offset
+ b := make([]byte, r.readSize)
+ n, err := r.reader.ReadAt(b, r.offset)
+ if err != nil && errors.Cause(err) != io.EOF {
+ return "", err
+ }
+ if int64(n) < r.readSize {
+ b = b[0:n]
+ }
+ // Set to the next page boundary
+ r.offset = -r.readSize
+ return string(b), nil
+}
diff --git a/libpod/options.go b/libpod/options.go
index 1fd588867..d01e8a85f 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -593,7 +593,7 @@ func WithUser(user string) CtrCreateOption {
// other configuration from the image will be added to the config.
// TODO: Replace image name and ID with a libpod.Image struct when that is
// finished.
-func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool) CtrCreateOption {
+func WithRootFSFromImage(imageID string, imageName string) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return define.ErrCtrFinalized
@@ -608,7 +608,6 @@ func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool)
ctr.config.RootfsImageID = imageID
ctr.config.RootfsImageName = imageName
- ctr.config.ImageVolumes = useImageVolumes
return nil
}
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index a6cac2b72..da46f03e8 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -127,7 +127,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
containerName := p.ID()[:IDTruncLength] + "-infra"
options = append(options, r.WithPod(p))
- options = append(options, WithRootFSFromImage(imgID, imgName, false))
+ options = append(options, WithRootFSFromImage(imgID, imgName))
options = append(options, WithName(containerName))
options = append(options, withIsInfra())
diff --git a/libpod/util_test.go b/libpod/util_test.go
index 70e989e1a..227686c2b 100644
--- a/libpod/util_test.go
+++ b/libpod/util_test.go
@@ -1,8 +1,9 @@
package libpod
import (
- "github.com/stretchr/testify/assert"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func TestRemoveScientificNotationFromFloat(t *testing.T) {