Add max_container_log_size

Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
Lantao Liu
2018-05-04 23:09:43 -07:00
parent b39546ce2b
commit 405f57f8e0
9 changed files with 390 additions and 86 deletions

View File

@@ -16,7 +16,10 @@ limitations under the License.
package ioutil
import "io"
import (
"io"
"sync"
)
// writeCloseInformer wraps passed in write closer with a close channel.
// Caller could wait on the close channel for the write closer to be
@@ -66,3 +69,34 @@ func (n *nopWriteCloser) Write(p []byte) (int, error) {
func (n *nopWriteCloser) Close() error {
return nil
}
// serialWriteCloser wraps a write closer and makes sure all writes
// are done in serial.
// Parallel write won't intersect with each other. Use case:
// 1) Pipe: Write content longer than PIPE_BUF.
// See http://man7.org/linux/man-pages/man7/pipe.7.html
// 2) <3.14 Linux Kernel: write is not atomic
// See http://man7.org/linux/man-pages/man2/write.2.html
type serialWriteCloser struct {
mu sync.Mutex
wc io.WriteCloser
}
// NewSerialWriteCloser creates a SerialWriteCloser from a write closer.
func NewSerialWriteCloser(wc io.WriteCloser) io.WriteCloser {
return &serialWriteCloser{wc: wc}
}
// Write writes a group of byte arrays in order atomically.
func (s *serialWriteCloser) Write(data []byte) (int, error) {
s.mu.Lock()
defer s.mu.Unlock()
return s.wc.Write(data)
}
// Close closes the write closer.
func (s *serialWriteCloser) Close() error {
s.mu.Lock()
defer s.mu.Unlock()
return s.wc.Close()
}

View File

@@ -17,9 +17,16 @@ limitations under the License.
package ioutil
import (
"io/ioutil"
"os"
"sort"
"strconv"
"strings"
"sync"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestWriteCloseInformer(t *testing.T) {
@@ -47,3 +54,55 @@ func TestWriteCloseInformer(t *testing.T) {
assert.Fail(t, "write closer not closed")
}
}
func TestSerialWriteCloser(t *testing.T) {
const (
// Test 10 times to make sure it always pass.
testCount = 10
goroutine = 10
dataLen = 100000
)
for n := 0; n < testCount; n++ {
testData := make([][]byte, goroutine)
for i := 0; i < goroutine; i++ {
testData[i] = []byte(repeatNumber(i, dataLen) + "\n")
}
f, err := ioutil.TempFile("/tmp", "serial-write-closer")
require.NoError(t, err)
defer os.RemoveAll(f.Name())
defer f.Close()
wc := NewSerialWriteCloser(f)
defer wc.Close()
// Write data in parallel
var wg sync.WaitGroup
wg.Add(goroutine)
for i := 0; i < goroutine; i++ {
go func(id int) {
n, err := wc.Write(testData[id])
assert.NoError(t, err)
assert.Equal(t, dataLen+1, n)
wg.Done()
}(i)
}
wg.Wait()
wc.Close()
// Check test result
content, err := ioutil.ReadFile(f.Name())
require.NoError(t, err)
resultData := strings.Split(strings.TrimSpace(string(content)), "\n")
require.Len(t, resultData, goroutine)
sort.Strings(resultData)
for i := 0; i < goroutine; i++ {
expected := repeatNumber(i, dataLen)
assert.Equal(t, expected, resultData[i])
}
}
}
func repeatNumber(num, count int) string {
return strings.Repeat(strconv.Itoa(num), count)
}