From f39285313417a713fd0a5230ddd51ccc9d2bf77a Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Tue, 16 May 2017 11:11:11 -0500 Subject: [PATCH 1/2] update sliceMaxByIndex by view --- client.go | 9 ++++++++- cmd/backup.go | 6 +++--- ctl/export.go | 8 +++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/client.go b/client.go index 058d6d836..6a4e29641 100644 --- a/client.go +++ b/client.go @@ -474,7 +474,14 @@ func (c *Client) BackupTo(ctx context.Context, w io.Writer, index, frame, view s tw := tar.NewWriter(w) // Find the maximum number of slices. - maxSlices, err := c.MaxSliceByIndex(ctx) + var maxSlices map[string]uint64 + var err error + if view == ViewStandard { + maxSlices, err = c.MaxSliceByIndex(ctx) + } else if view == ViewInverse { + maxSlices, err = c.MaxInverseSliceByIndex(ctx) + } + if err != nil { return fmt.Errorf("slice n: %s", err) } diff --git a/cmd/backup.go b/cmd/backup.go index 548781ca6..1dd3a50d6 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -43,9 +43,9 @@ Backs up the view from across the cluster into a single file. } flags := backupCmd.Flags() flags.StringVarP(&Backuper.Host, "host", "", "localhost:10101", "host:port of Pilosa.") - flags.StringVarP(&Backuper.Index, "index", "i", "", "Pilosa index to backup into.") - flags.StringVarP(&Backuper.Frame, "frame", "f", "", "Frame to backup into.") - flags.StringVarP(&Backuper.View, "view", "v", "", "View to backup into.") + flags.StringVarP(&Backuper.Index, "index", "i", "", "Pilosa index to backup.") + flags.StringVarP(&Backuper.Frame, "frame", "f", "", "Frame to backup.") + flags.StringVarP(&Backuper.View, "view", "v", "", "View to backup.") flags.StringVarP(&Backuper.Path, "output-file", "o", "", "File to write backup to - default stdout") return backupCmd diff --git a/ctl/export.go b/ctl/export.go index 7da310623..fa6277f16 100644 --- a/ctl/export.go +++ b/ctl/export.go @@ -79,7 +79,13 @@ func (cmd *ExportCommand) Run(ctx context.Context) error { } // Determine slice count. - maxSlices, err := client.MaxSliceByIndex(ctx) + var maxSlices map[string]uint64 + if cmd.View == pilosa.ViewStandard { + maxSlices, err = client.MaxSliceByIndex(ctx) + } else if cmd.View == pilosa.ViewInverse { + maxSlices, err = client.MaxInverseSliceByIndex(ctx) + } + if err != nil { return err } From 81621e07b20855e31c9caebb65afba3e321b2702 Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Tue, 16 May 2017 13:12:08 -0500 Subject: [PATCH 2/2] add tests --- client.go | 2 ++ client_test.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/client.go b/client.go index 6a4e29641..161a2ac2f 100644 --- a/client.go +++ b/client.go @@ -480,6 +480,8 @@ func (c *Client) BackupTo(ctx context.Context, w io.Writer, index, frame, view s maxSlices, err = c.MaxSliceByIndex(ctx) } else if view == ViewInverse { maxSlices, err = c.MaxInverseSliceByIndex(ctx) + } else { + return ErrInvalidView } if err != nil { diff --git a/client_test.go b/client_test.go index 6b5f43195..d2716c711 100644 --- a/client_test.go +++ b/client_test.go @@ -333,6 +333,87 @@ func TestClient_BackupRestore(t *testing.T) { } } +// Ensure client backup and restore a frame with inverse view. +func TestClient_BackupInverseView(t *testing.T) { + hldr := MustOpenHolder() + defer hldr.Close() + + idx := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{}) + frameOpts := pilosa.FrameOptions{ + InverseEnabled: true, + } + frame, err := idx.CreateFrameIfNotExists("f", frameOpts) + if err != nil { + panic(err) + } + v, err := frame.CreateViewIfNotExists(pilosa.ViewInverse) + if err != nil { + panic(err) + } + f, err := v.CreateFragmentIfNotExists(0) + if err != nil { + panic(err) + } + + f.SetBit(100, 1) + f.SetBit(100, 2) + f.SetBit(100, 3) + f.SetBit(100, SliceWidth-1) + + s := NewServer() + defer s.Close() + s.Handler.Host = s.Host() + s.Handler.Cluster = NewCluster(1) + s.Handler.Cluster.Nodes[0].Host = s.Host() + s.Handler.Holder = hldr.Holder + + c := MustNewClient(s.Host()) + + // Backup from frame. + var buf bytes.Buffer + if err := c.BackupTo(context.Background(), &buf, "i", "f", pilosa.ViewInverse); err != nil { + t.Fatal(err) + } + + // Restore to a different frame. + if _, err := hldr.MustCreateIndexIfNotExists("x", pilosa.IndexOptions{}).CreateFrameIfNotExists("y", pilosa.FrameOptions{InverseEnabled: true}); err != nil { + t.Fatal(err) + } + if err := c.RestoreFrom(context.Background(), &buf, "x", "y", pilosa.ViewInverse); err != nil { + t.Fatal(err) + } + + // Verify data. + if a := hldr.Fragment("x", "y", pilosa.ViewInverse, 0).Row(100).Bits(); !reflect.DeepEqual(a, []uint64{1, 2, 3, SliceWidth - 1}) { + t.Fatalf("unexpected bits(0): %+v", a) + } + +} + +// backup returns error with invalid view +func TestClient_BackupInvalidView(t *testing.T) { + hldr := MustOpenHolder() + defer hldr.Close() + + hldr.MustCreateFragmentIfNotExists("i", "f", pilosa.ViewStandard, 0).MustSetBits(100, 1, 2, 3, SliceWidth-1) + + s := NewServer() + defer s.Close() + s.Handler.Host = s.Host() + s.Handler.Cluster = NewCluster(1) + s.Handler.Cluster.Nodes[0].Host = s.Host() + s.Handler.Holder = hldr.Holder + + c := MustNewClient(s.Host()) + + // Backup from frame. + var buf bytes.Buffer + err := c.BackupTo(context.Background(), &buf, "i", "f", "invalid_view") + if err != pilosa.ErrInvalidView { + t.Fatal(err) + } +} + // Ensure client can retrieve a list of all checksums for blocks in a fragment. func TestClient_FragmentBlocks(t *testing.T) { hldr := MustOpenHolder()