fixed crashing issue that was not handling container removal/recycling correctly

This commit is contained in:
Todd Gruben 2018-06-21 18:39:06 -05:00
parent eb43707d19
commit 643e5e575a
6 changed files with 100 additions and 2 deletions

1
api.go
View file

@ -658,7 +658,6 @@ func (api *API) ImportValue(ctx context.Context, req internal.ImportValueRequest
if err != nil {
return errors.Wrap(err, "getting field")
}
// Import into fragment.
err = field.ImportValue(req.ColumnIDs, req.Values)
if err != nil {

View file

@ -197,3 +197,55 @@ func GetIO(buf bytes.Buffer) (io.Reader, io.Writer, io.Writer) {
stderr := bufio.NewWriter(&buf)
return stdin, stdout, stderr
}
func TestImportCommand_BugOverwriteValue(t *testing.T) {
buf := bytes.Buffer{}
stdin, stdout, stderr := GetIO(buf)
cm := NewImportCommand(stdin, stdout, stderr)
file, err := ioutil.TempFile("", "import-value.csv")
file.Write([]byte("0,17\n"))
ctx := context.Background()
if err != nil {
t.Fatal(err)
}
hldr := test.MustOpenHolder()
defer hldr.Close()
s := test.NewServer()
defer s.Close()
s.Handler.API.Cluster = test.NewCluster(1)
s.Handler.API.Cluster.Nodes[0].URI = s.HostURI()
s.Handler.API.Holder = hldr.Holder
cm.Host = s.Host()
http.DefaultClient.Do(MustNewHTTPRequest("POST", s.URL+"/index/i", strings.NewReader("")))
http.DefaultClient.Do(MustNewHTTPRequest("POST", s.URL+"/index/i/field/f", strings.NewReader(`{"options":{"type": "int", "min": 0, "max":2147483648 }}`)))
cm.Index = "i"
cm.Field = "f"
cm.Paths = []string{file.Name()}
err = cm.Run(ctx)
if err != nil {
t.Fatalf("Import Run with values doesn't work: %s", err)
}
file.Close()
file, err = ioutil.TempFile("", "import-value2.csv")
file.Write([]byte("0,16\n"))
cm.Paths = []string{file.Name()}
err = cm.Run(ctx)
if err != nil {
t.Fatalf("Import Run with values doesn't work: %s", err)
}
file.Close()
file, err = ioutil.TempFile("", "import-value3.csv")
file.Write([]byte("0,19\n"))
cm.Paths = []string{file.Name()}
err = cm.Run(ctx)
if err != nil {
t.Fatalf("Import Run with values doesn't work: %s", err)
}
}

View file

@ -160,6 +160,10 @@ func (btc *BTreeContainers) Size() int {
return btc.tree.Len()
}
func (btc *BTreeContainers) Reset() {
btc.tree = TreeNew(cmp)
}
func (btc *BTreeContainers) Iterator(key uint64) (citer roaring.ContainerIterator, found bool) {
e, ok := btc.tree.Seek(key)
if ok {

View file

@ -213,6 +213,39 @@ func TestFragment_SetValue(t *testing.T) {
t.Fatal(err)
}
})
t.Run("Crash", func(t *testing.T) {
f := mustOpenFragment("i", "f", ViewStandard, 0, "")
defer f.Close()
// Set value.
if changed, err := f.setValue(0, 32, 17); err != nil {
t.Fatal(err)
} else if !changed {
t.Fatal("expected change")
}
if changed, err := f.setValue(0, 32, 16); err != nil {
t.Fatal(err)
} else if !changed {
t.Fatal("expected change")
}
if changed, err := f.setValue(0, 32, 19); err != nil {
t.Fatal(err)
} else if !changed {
t.Fatal("expected change")
}
// Read value.
if value, exists, err := f.value(0, 32); err != nil {
t.Fatal(err)
} else if value != 19 {
t.Fatalf("unexpected value: %d", value)
} else if !exists {
t.Fatal("expected to exist")
}
})
}
// Ensure a fragment can sum values.

View file

@ -132,6 +132,13 @@ func (sc *SliceContainers) Count() uint64 {
return n
}
func (sc *SliceContainers) Reset() {
sc.keys = sc.keys[:0]
sc.containers = sc.containers[:0]
sc.lastContainer = nil
sc.lastKey = 0
}
func (sc *SliceContainers) seek(key uint64) (int, bool) {
i := search64(sc.keys, key)
found := true

View file

@ -94,6 +94,8 @@ type Containers interface {
// container is found at key.
Iterator(key uint64) (citer ContainerIterator, found bool)
Count() uint64
//Reset will clear the containers collection to allow for recycling during snapshot
Reset()
}
type ContainerIterator interface {
@ -631,7 +633,7 @@ func (b *Bitmap) UnmarshalBinary(data []byte) error {
keyN := binary.LittleEndian.Uint32(data[4:8])
headerSize := headerBaseSize
b.Containers.Reset()
// Descriptive header section: Read container keys and cardinalities.
for i, buf := 0, data[headerSize:]; i < int(keyN); i, buf = i+1, buf[12:] {
b.Containers.PutContainerValues(
@ -688,6 +690,7 @@ func (b *Bitmap) UnmarshalBinary(data []byte) error {
// FIXME(benbjohnson): return error with position so file can be trimmed.
return err
}
opr.apply(b)
// Increase the op count.