summaryrefslogtreecommitdiff
path: root/libpod/logs/reversereader/reversereader.go
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-02-21 13:12:21 -0500
committerGitHub <noreply@github.com>2020-02-21 13:12:21 -0500
commit5bdf5aeb71981a4951c039b1c795b24ca31ca705 (patch)
tree86c62589838a4fb836b4d27c94fbcc0772361485 /libpod/logs/reversereader/reversereader.go
parenta554e97adcd565bd378a7041589b3b4979489ead (diff)
parente3b31a3ab80c5f681fb157f0e10eb2d3819ef18b (diff)
downloadpodman-5bdf5aeb71981a4951c039b1c795b24ca31ca705.tar.gz
podman-5bdf5aeb71981a4951c039b1c795b24ca31ca705.tar.bz2
podman-5bdf5aeb71981a4951c039b1c795b24ca31ca705.zip
Merge pull request #5263 from baude/logsize
implement reverse reader for log reads
Diffstat (limited to 'libpod/logs/reversereader/reversereader.go')
-rw-r--r--libpod/logs/reversereader/reversereader.go66
1 files changed, 66 insertions, 0 deletions
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
+}