fix race cond in translate_test

implements locked Reader method on test.TranslateFile. This race condition is
only present in tests, and is due to a replica referring directly to a primary
instead of through an http.TranslateStore as it would in production. This patch
requires the replica to obtain a lock while accessing the primary, and requires
test.Reopen to obtain a lock when swapping out the pilosa.TranslateStore.

I was able to reproduce the race by running: "go test
-run=TestTranslateFile_PrimaryTranslateStore -race -count=10", and could not
reproduce it after this patch.

Somewhat unrelated, I came across a "fatal error: fault" triggered by trying to
print an open pilosa.TranslateFile. This seems to be related to the mmapped
".data" field. I wrote the test to document the issue, but I don't think it's
easily fixable.
This commit is contained in:
Matt Jaffee 2018-07-19 12:06:31 -05:00
parent 9be45bcd60
commit 68f341ea9f
No known key found for this signature in database
GPG key ID: 08A3DFFF987B11BF

View file

@ -4,11 +4,13 @@ import (
"bufio"
"context"
"fmt"
"io"
"io/ioutil"
"math/rand"
"os"
"reflect"
"strconv"
"sync"
"testing"
"time"
@ -356,6 +358,24 @@ func TestTranslateFile_Reader(t *testing.T) {
})
}
func TestPrintTranslateFile(t *testing.T) {
// I think this is related to the mmap in s.Open.
t.Skip("causes fatal error: fault")
f, err := ioutil.TempFile("", "")
if err != nil {
panic(err)
}
f.Close()
s := pilosa.NewTranslateFile()
s.Path = f.Name()
err = s.Open()
if err != nil {
t.Fatalf("opening : %v", err)
}
fmt.Println("blah ", s)
}
func TestTranslateFile_PrimaryTranslateStore(t *testing.T) {
// Create a primary store that accepts writes.
primary := MustOpenTranslateFile()
@ -495,6 +515,7 @@ func BenchmarkTranslateFile_TranslateColumnToString(b *testing.B) {
}
type TranslateFile struct {
lock sync.Mutex
*pilosa.TranslateFile
}
@ -510,6 +531,12 @@ func NewTranslateFile() *TranslateFile {
return s
}
func (t *TranslateFile) Reader(ctx context.Context, offset int64) (io.ReadCloser, error) {
t.lock.Lock()
defer t.lock.Unlock()
return t.TranslateFile.Reader(ctx, offset)
}
func MustOpenTranslateFile() *TranslateFile {
s := NewTranslateFile()
if err := s.Open(); err != nil {
@ -536,7 +563,9 @@ func (s *TranslateFile) Reopen() error {
return err
}
s.lock.Lock()
s.TranslateFile = pilosa.NewTranslateFile()
s.lock.Unlock()
s.Path = prev.Path
s.PrimaryTranslateStore = prev.PrimaryTranslateStore
if err := s.Open(); err != nil {