From 59035883f432887ddb517977f35299222aab1fc4 Mon Sep 17 00:00:00 2001 From: Michael Baird Date: Fri, 10 Nov 2017 15:03:23 -0600 Subject: [PATCH 01/14] group the write operations in syncBlock by MaxWritesPerRequest --- cluster.go | 10 +++++++--- fragment.go | 45 +++++++++++++++++++++++++++------------------ server.go | 1 + 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/cluster.go b/cluster.go index 820349ded..cdcf50b26 100644 --- a/cluster.go +++ b/cluster.go @@ -144,14 +144,18 @@ type Cluster struct { // Threshold for logging long-running queries LongQueryTime time.Duration + + // Maximum number of SetBit() or ClearBit() commands per request. + MaxWritesPerRequest int } // NewCluster returns a new instance of Cluster with defaults. func NewCluster() *Cluster { return &Cluster{ - Hasher: &jmphasher{}, - PartitionN: DefaultPartitionN, - ReplicaN: DefaultReplicaN, + Hasher: &jmphasher{}, + PartitionN: DefaultPartitionN, + ReplicaN: DefaultReplicaN, + MaxWritesPerRequest: DefaultMaxWritesPerRequest, } } diff --git a/fragment.go b/fragment.go index e5fbb7988..401faf17c 100644 --- a/fragment.go +++ b/fragment.go @@ -492,7 +492,7 @@ func (f *Fragment) FieldValue(columnID uint64, bitDepth uint) (value uint64, exi f.mu.Lock() defer f.mu.Unlock() - // If existance bit is unset then ignore remaining bits. + // If existence bit is unset then ignore remaining bits. if v, err := f.bit(uint64(bitDepth), columnID); err != nil { return 0, false, err } else if !v { @@ -586,7 +586,7 @@ func (f *Fragment) importSetFieldValue(columnID uint64, bitDepth uint, value uin // FieldSum returns the sum of a given field as well as the number of columns involved. // A bitmap can be passed in to optionally filter the computed columns. func (f *Fragment) FieldSum(filter *Bitmap, bitDepth uint) (sum, count uint64, err error) { - // Compute count based on the existance bit. + // Compute count based on the existence bit. row := f.Row(uint64(bitDepth)) if filter != nil { count = row.IntersectionCount(filter) @@ -615,6 +615,7 @@ func (f *Fragment) FieldSum(filter *Bitmap, bitDepth uint) (sum, count uint64, e return sum, count, nil } +// FieldRange returns bitmaps with a field value encoding matching the predicate. func (f *Fragment) FieldRange(op pql.Token, bitDepth uint, predicate uint64) (*Bitmap, error) { switch op { case pql.EQ: @@ -753,6 +754,7 @@ func (f *Fragment) FieldNotNull(bitDepth uint) (*Bitmap, error) { return f.Row(uint64(bitDepth)), nil } +// FieldRangeBetween returns bitmaps with a field value encoding matching any value between predicateMin and predicateMax. func (f *Fragment) FieldRangeBetween(bitDepth uint, predicateMin, predicateMax uint64) (*Bitmap, error) { b := f.Row(uint64(bitDepth)) keep1 := NewBitmap() // GTE @@ -1825,36 +1827,43 @@ func (s *FragmentSyncer) syncBlock(id int) error { // Write updates to remote blocks. for i := 0; i < len(clients); i++ { set, clear := sets[i], clears[i] + count := 0 // Ignore if there are no differences. if len(set.ColumnIDs) == 0 && len(clear.ColumnIDs) == 0 { continue } - // Generate query with sets & clears. - var buf bytes.Buffer + // Generate query with sets & clears, and group the requests to not exceed MaxWritesPerRequest. + total := len(set.ColumnIDs) + len(clear.ColumnIDs) + buffers := make([]bytes.Buffer, int(math.Ceil(float64(total)/float64(s.Cluster.MaxWritesPerRequest)))) // Only sync the standard block. for j := 0; j < len(set.ColumnIDs); j++ { - fmt.Fprintf(&buf, "SetBit(frame=%q, rowID=%d, columnID=%d)\n", f.Frame(), set.RowIDs[j], (f.Slice()*SliceWidth)+set.ColumnIDs[j]) + fmt.Fprintf(&(buffers[count/s.Cluster.MaxWritesPerRequest]), "SetBit(frame=%q, rowID=%d, columnID=%d)\n", f.Frame(), set.RowIDs[j], (f.Slice()*SliceWidth)+set.ColumnIDs[j]) + count++ } for j := 0; j < len(clear.ColumnIDs); j++ { - fmt.Fprintf(&buf, "ClearBit(frame=%q, rowID=%d, columnID=%d)\n", f.Frame(), clear.RowIDs[j], (f.Slice()*SliceWidth)+clear.ColumnIDs[j]) + fmt.Fprintf(&(buffers[count/s.Cluster.MaxWritesPerRequest]), "ClearBit(frame=%q, rowID=%d, columnID=%d)\n", f.Frame(), clear.RowIDs[j], (f.Slice()*SliceWidth)+clear.ColumnIDs[j]) + count++ } - // Verify sync is not prematurely closing. - if s.isClosing() { - return nil - } + // Iterate over the buffers. + for k := 0; k < len(buffers); k++ { + // Verify sync is not prematurely closing. + if s.isClosing() { + return nil + } - // Execute query. - queryRequest := &internal.QueryRequest{ - Query: buf.String(), - Remote: true, - } - _, err := clients[i].ExecuteQuery(context.Background(), f.Index(), queryRequest) - if err != nil { - return err + // Execute query. + queryRequest := &internal.QueryRequest{ + Query: buffers[k].String(), + Remote: true, + } + _, err := clients[i].ExecuteQuery(context.Background(), f.Index(), queryRequest) + if err != nil { + return err + } } } diff --git a/server.go b/server.go index 0d55e7c47..e2769a0be 100644 --- a/server.go +++ b/server.go @@ -176,6 +176,7 @@ func (s *Server) Open() error { e.Host = s.URI.HostPort() e.Cluster = s.Cluster e.MaxWritesPerRequest = s.MaxWritesPerRequest + s.Cluster.MaxWritesPerRequest = s.MaxWritesPerRequest // Initialize HTTP handler. s.Handler.Broadcaster = s.Broadcaster From a595d80fd464e4877517047b0b964f49fba44c4c Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Wed, 15 Nov 2017 16:03:40 -0600 Subject: [PATCH 02/14] Release v0.8.1 --- CHANGELOG.md | 9 +++++++++ docs/installation.md | 12 ++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a54a5b73..b43d73c04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.8.1] - 2017-11-15 + +This version contains 2 contributions from 2 contributors. There are 4 files changed, 27 insertions, and 14 deletions. + +### Fixed + +- Fix CountOpenFiles() fatal crash ([#969](https://github.com/pilosa/pilosa/pull/969)) +- Fix version check when local is greater than pilosa.com ([#968](https://github.com/pilosa/pilosa/pull/968)) + ## [0.8.0] - 2017-11-15 This version contains 31 contributions from 8 contributors. There are 84 files changed, 3,732 insertions, and 1,428 deletions. diff --git a/docs/installation.md b/docs/installation.md index 33528f969..991634a77 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -74,19 +74,19 @@ There are four ways to install Pilosa on MacOS: Use [Homebrew](https://brew.sh/) 1. Download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.0/pilosa-v0.8.0-darwin-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.1/pilosa-v0.8.1-darwin-amd64.tar.gz ``` Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.0-darwin-amd64.tar.gz + tar xfz pilosa-v0.8.1-darwin-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.0-darwin-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.1-darwin-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: @@ -228,19 +228,19 @@ There are three ways to install Pilosa on Linux: download the binary (recommende 1. To install the latest version of Pilosa, download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.0/pilosa-v0.8.0-linux-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.1/pilosa-v0.8.1-linux-amd64.tar.gz ``` Note: This assumes you are using an `amd64` compatible architecture. Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.0-linux-amd64.tar.gz + tar xfz pilosa-v0.8.1-linux-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.0-linux-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.1-linux-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: From 073938622b43674deca5d125ab38fdb316f5d525 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Fri, 1 Dec 2017 16:00:12 -0600 Subject: [PATCH 03/14] refactored httpclient handling --- client.go | 30 ++++-------------------------- client_test.go | 34 +++++++++++++++++++++------------- ctl/common.go | 8 ++++---- executor.go | 24 +++++++++++------------- fragment.go | 11 ++++++----- handler.go | 8 ++++---- holder.go | 21 +++++++++++---------- holder_test.go | 11 ++++++----- server.go | 34 +++++++++++++++++++++++++--------- server/server.go | 13 +++++++++++-- server/server_test.go | 6 +++--- test/client.go | 6 ++++-- test/executor.go | 2 +- 13 files changed, 111 insertions(+), 97 deletions(-) diff --git a/client.go b/client.go index 666447586..e44d9c5de 100644 --- a/client.go +++ b/client.go @@ -25,7 +25,6 @@ import ( "io/ioutil" "log" "math/rand" - "net" "net/http" "net/url" "sort" @@ -46,14 +45,13 @@ type ClientOptions struct { // InternalHTTPClient represents a client to the Pilosa cluster. type InternalHTTPClient struct { defaultURI *URI - options *ClientOptions // The client to use for HTTP communication. HTTPClient *http.Client } // NewInternalHTTPClient returns a new instance of InternalHTTPClient to connect to host. -func NewInternalHTTPClient(host string, options *ClientOptions) (*InternalHTTPClient, error) { +func NewInternalHTTPClient(host string, remoteClient *http.Client) (*InternalHTTPClient, error) { if host == "" { return nil, ErrHostRequired } @@ -63,34 +61,14 @@ func NewInternalHTTPClient(host string, options *ClientOptions) (*InternalHTTPCl return nil, err } - client := NewInternalHTTPClientFromURI(uri, options) + client := NewInternalHTTPClientFromURI(uri, remoteClient) return client, nil } -func NewInternalHTTPClientFromURI(defaultURI *URI, options *ClientOptions) *InternalHTTPClient { - if options == nil { - options = &ClientOptions{} - } - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).DialContext, - MaxIdleConns: 1000, - MaxIdleConnsPerHost: 200, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - } - if options.TLS != nil { - transport.TLSClientConfig = options.TLS - } - client := &http.Client{Transport: transport} +func NewInternalHTTPClientFromURI(defaultURI *URI, remoteClient *http.Client) *InternalHTTPClient { return &InternalHTTPClient{ defaultURI: defaultURI, - HTTPClient: client, + HTTPClient: remoteClient, } } diff --git a/client_test.go b/client_test.go index 613d37659..8feec09ea 100644 --- a/client_test.go +++ b/client_test.go @@ -18,6 +18,7 @@ import ( "bytes" "context" "fmt" + "net/http" "reflect" "testing" @@ -43,6 +44,13 @@ func createCluster(c *pilosa.Cluster) ([]*test.Server, []*test.Holder) { return server, hldr } +var defaultClient *http.Client + +func init() { + defaultClient = pilosa.GetHTTPClient(nil) + +} + // Test distributed TopN Row count across 3 nodes. func TestClient_MultiNode(t *testing.T) { cluster := test.NewCluster(3) @@ -54,7 +62,7 @@ func TestClient_MultiNode(t *testing.T) { } s[0].Handler.Executor.ExecuteFn = func(ctx context.Context, index string, query *pql.Query, slices []uint64, opt *pilosa.ExecOptions) ([]interface{}, error) { - e := pilosa.NewExecutor(nil) + e := pilosa.NewExecutor(defaultClient) e.Holder = hldr[0].Holder e.Scheme = cluster.Nodes[0].Scheme e.Host = cluster.Nodes[0].Host @@ -62,7 +70,7 @@ func TestClient_MultiNode(t *testing.T) { return e.Execute(ctx, index, query, slices, opt) } s[1].Handler.Executor.ExecuteFn = func(ctx context.Context, index string, query *pql.Query, slices []uint64, opt *pilosa.ExecOptions) ([]interface{}, error) { - e := pilosa.NewExecutor(nil) + e := pilosa.NewExecutor(defaultClient) e.Holder = hldr[1].Holder e.Scheme = cluster.Nodes[1].Scheme e.Host = cluster.Nodes[1].Host @@ -70,7 +78,7 @@ func TestClient_MultiNode(t *testing.T) { return e.Execute(ctx, index, query, slices, opt) } s[2].Handler.Executor.ExecuteFn = func(ctx context.Context, index string, query *pql.Query, slices []uint64, opt *pilosa.ExecOptions) ([]interface{}, error) { - e := pilosa.NewExecutor(nil) + e := pilosa.NewExecutor(defaultClient) e.Holder = hldr[2].Holder e.Scheme = cluster.Nodes[2].Scheme e.Host = cluster.Nodes[2].Host @@ -135,9 +143,9 @@ func TestClient_MultiNode(t *testing.T) { // Connect to each node to compare results. client := make([]*test.Client, 3) - client[0] = test.MustNewClient(s[0].Host()) - client[1] = test.MustNewClient(s[1].Host()) - client[2] = test.MustNewClient(s[2].Host()) + client[0] = test.MustNewClient(s[0].Host(), defaultClient) + client[1] = test.MustNewClient(s[1].Host(), defaultClient) + client[2] = test.MustNewClient(s[2].Host(), defaultClient) topN := 4 queryRequest := &internal.QueryRequest{ @@ -218,7 +226,7 @@ func TestClient_Import(t *testing.T) { s.Handler.Holder = hldr.Holder // Send import request. - c := test.MustNewClient(s.Host()) + c := test.MustNewClient(s.Host(), defaultClient) if err := c.Import(context.Background(), "i", "f", 0, []pilosa.Bit{ {RowID: 0, ColumnID: 1}, {RowID: 0, ColumnID: 5}, @@ -269,7 +277,7 @@ func TestClient_ImportInverseEnabled(t *testing.T) { s.Handler.Holder = hldr.Holder // Send import request. - c := test.MustNewClient(s.Host()) + c := test.MustNewClient(s.Host(), defaultClient) if err := c.Import(context.Background(), "i", "f", 0, []pilosa.Bit{ {RowID: 0, ColumnID: 1}, {RowID: 0, ColumnID: 5}, @@ -318,7 +326,7 @@ func TestClient_ImportValue(t *testing.T) { s.Handler.Holder = hldr.Holder // Send import request. - c := test.MustNewClient(s.Host()) + c := test.MustNewClient(s.Host(), defaultClient) if err := c.ImportValue(context.Background(), "i", "f", fld.Name, 0, []pilosa.FieldValue{ {ColumnID: 1, Value: -10}, {ColumnID: 2, Value: 20}, @@ -355,7 +363,7 @@ func TestClient_BackupRestore(t *testing.T) { s.Handler.Cluster.Nodes[0].Host = s.Host() s.Handler.Holder = hldr.Holder - c := test.MustNewClient(s.Host()) + c := test.MustNewClient(s.Host(), defaultClient) // Backup from frame. var buf bytes.Buffer @@ -420,7 +428,7 @@ func TestClient_BackupInverseView(t *testing.T) { s.Handler.Cluster.Nodes[0].Host = s.Host() s.Handler.Holder = hldr.Holder - c := test.MustNewClient(s.Host()) + c := test.MustNewClient(s.Host(), defaultClient) // Backup from frame. var buf bytes.Buffer @@ -457,7 +465,7 @@ func TestClient_BackupInvalidView(t *testing.T) { s.Handler.Cluster.Nodes[0].Host = s.Host() s.Handler.Holder = hldr.Holder - c := test.MustNewClient(s.Host()) + c := test.MustNewClient(s.Host(), defaultClient) // Backup from frame. var buf bytes.Buffer @@ -487,7 +495,7 @@ func TestClient_FragmentBlocks(t *testing.T) { s.Handler.Holder = hldr.Holder // Retrieve blocks. - c := test.MustNewClient(s.Host()) + c := test.MustNewClient(s.Host(), defaultClient) blocks, err := c.FragmentBlocks(context.Background(), "i", "f", pilosa.ViewStandard, 0) if err != nil { t.Fatal(err) diff --git a/ctl/common.go b/ctl/common.go index dc64c0bee..826462b8c 100644 --- a/ctl/common.go +++ b/ctl/common.go @@ -2,6 +2,7 @@ package ctl import ( "crypto/tls" + "github.com/pilosa/pilosa" "github.com/spf13/pflag" ) @@ -22,19 +23,18 @@ func SetTLSConfig(flags *pflag.FlagSet, certificatePath *string, certificateKeyP // CommandClient returns a pilosa.InternalHTTPClient for the command func CommandClient(cmd CommandWithTLSSupport) (*pilosa.InternalHTTPClient, error) { tlsConfig := cmd.TLSConfiguration() - var clientOptions *pilosa.ClientOptions + var TLSConfig *tls.Config if tlsConfig.CertificatePath != "" && tlsConfig.CertificateKeyPath != "" { cert, err := tls.LoadX509KeyPair(tlsConfig.CertificatePath, tlsConfig.CertificateKeyPath) if err != nil { return nil, err } - TLSConfig := &tls.Config{ + TLSConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, InsecureSkipVerify: tlsConfig.SkipVerify, } - clientOptions = &pilosa.ClientOptions{TLS: TLSConfig} } - client, err := pilosa.NewInternalHTTPClient(cmd.TLSHost(), clientOptions) + client, err := pilosa.NewInternalHTTPClient(cmd.TLSHost(), pilosa.GetHTTPClient(TLSConfig)) if err != nil { return nil, err } diff --git a/executor.go b/executor.go index 2f5acf3c0..a617eb184 100644 --- a/executor.go +++ b/executor.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "net/http" "sort" "time" @@ -51,12 +52,9 @@ type Executor struct { } // NewExecutor returns a new instance of Executor. -func NewExecutor(clientOptions *ClientOptions) *Executor { - if clientOptions == nil { - clientOptions = &ClientOptions{} - } +func NewExecutor(remoteClient *http.Client) *Executor { return &Executor{ - client: NewInternalHTTPClientFromURI(nil, clientOptions), + client: NewInternalHTTPClientFromURI(nil, remoteClient), } } @@ -968,7 +966,7 @@ func (e *Executor) executeClearBitView(ctx context.Context, index string, c *pql } // Forward call to remote node otherwise. - if res, err := e.exec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt); err != nil { + if res, err := e.remoteExec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt); err != nil { return false, err } else { ret = res[0].(bool) @@ -1074,7 +1072,7 @@ func (e *Executor) executeSetBitView(ctx context.Context, index string, c *pql.C } // Forward call to remote node otherwise. - if res, err := e.exec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt); err != nil { + if res, err := e.remoteExec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt); err != nil { return false, err } else { ret = res[0].(bool) @@ -1141,7 +1139,7 @@ func (e *Executor) executeSetFieldValue(ctx context.Context, index string, c *pq resp := make(chan error, len(nodes)) for _, node := range nodes { go func(node *Node) { - _, err := e.exec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt) + _, err := e.remoteExec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt) resp <- err }(node) } @@ -1199,7 +1197,7 @@ func (e *Executor) executeSetRowAttrs(ctx context.Context, index string, c *pql. resp := make(chan error, len(nodes)) for _, node := range nodes { go func(node *Node) { - _, err := e.exec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt) + _, err := e.remoteExec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt) resp <- err }(node) } @@ -1286,7 +1284,7 @@ func (e *Executor) executeBulkSetRowAttrs(ctx context.Context, index string, cal resp := make(chan error, len(nodes)) for _, node := range nodes { go func(node *Node) { - _, err := e.exec(ctx, node, index, &pql.Query{Calls: calls}, nil, opt) + _, err := e.remoteExec(ctx, node, index, &pql.Query{Calls: calls}, nil, opt) resp <- err }(node) } @@ -1345,7 +1343,7 @@ func (e *Executor) executeSetColumnAttrs(ctx context.Context, index string, c *p resp := make(chan error, len(nodes)) for _, node := range nodes { go func(node *Node) { - _, err := e.exec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt) + _, err := e.remoteExec(ctx, node, index, &pql.Query{Calls: []*pql.Call{c}}, nil, opt) resp <- err }(node) } @@ -1361,7 +1359,7 @@ func (e *Executor) executeSetColumnAttrs(ctx context.Context, index string, c *p } // exec executes a PQL query remotely for a set of slices on a node. -func (e *Executor) exec(ctx context.Context, node *Node, index string, q *pql.Query, slices []uint64, opt *ExecOptions) (results []interface{}, err error) { +func (e *Executor) remoteExec(ctx context.Context, node *Node, index string, q *pql.Query, slices []uint64, opt *ExecOptions) (results []interface{}, err error) { // Encode request object. pbreq := &internal.QueryRequest{ Query: q.String(), @@ -1511,7 +1509,7 @@ func (e *Executor) mapper(ctx context.Context, ch chan mapResponse, nodes []*Nod if n.Host == e.Host { resp.result, resp.err = e.mapperLocal(ctx, nodeSlices, mapFn, reduceFn) } else if !opt.Remote { - results, err := e.exec(ctx, n, index, &pql.Query{Calls: []*pql.Call{c}}, nodeSlices, opt) + results, err := e.remoteExec(ctx, n, index, &pql.Query{Calls: []*pql.Call{c}}, nodeSlices, opt) if len(results) > 0 { resp.result = results[0] } diff --git a/fragment.go b/fragment.go index e5fbb7988..073bdfa84 100644 --- a/fragment.go +++ b/fragment.go @@ -28,6 +28,7 @@ import ( "io" "io/ioutil" "log" + "net/http" "os" "sort" "sync" @@ -1677,9 +1678,9 @@ func (h *blockHasher) WriteValue(v uint64) { type FragmentSyncer struct { Fragment *Fragment - Host string - Cluster *Cluster - ClientOptions *ClientOptions + Host string + Cluster *Cluster + RemoteClient *http.Client Closing <-chan struct{} } @@ -1714,7 +1715,7 @@ func (s *FragmentSyncer) SyncFragment() error { } // Retrieve remote blocks. - client, err := NewInternalHTTPClient(node.Host, s.ClientOptions) + client, err := NewInternalHTTPClient(node.Host, s.RemoteClient) if err != nil { return err } @@ -1793,7 +1794,7 @@ func (s *FragmentSyncer) syncBlock(id int) error { return nil } - client, err := NewInternalHTTPClient(node.Host, s.ClientOptions) + client, err := NewInternalHTTPClient(node.Host, s.RemoteClient) if err != nil { return err } diff --git a/handler.go b/handler.go index f3d9fe9d3..ad9e02e2e 100644 --- a/handler.go +++ b/handler.go @@ -56,9 +56,9 @@ type Handler struct { StatusHandler StatusHandler // Local hostname & cluster configuration. - URI *URI - Cluster *Cluster - ClientOptions *ClientOptions + URI *URI + Cluster *Cluster + RemoteClient *http.Client Router *mux.Router @@ -1506,7 +1506,7 @@ func (h *Handler) handlePostFrameRestore(w http.ResponseWriter, r *http.Request) } // Create a client for the remote cluster. - client := NewInternalHTTPClientFromURI(host, h.ClientOptions) + client := NewInternalHTTPClientFromURI(host, h.RemoteClient) // Determine the maximum number of slices. maxSlices, err := client.MaxSliceByIndex(r.Context()) diff --git a/holder.go b/holder.go index 4241dcd85..7cbb8ca42 100644 --- a/holder.go +++ b/holder.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "log" + "net/http" "os" "path/filepath" "sort" @@ -430,9 +431,9 @@ func (h *Holder) logger() *log.Logger { return log.New(h.LogOutput, "", log.Lstd type HolderSyncer struct { Holder *Holder - URI *URI - Cluster *Cluster - ClientOptions *ClientOptions + URI *URI + Cluster *Cluster + RemoteClient *http.Client // Signals that the sync should stop. Closing <-chan struct{} @@ -518,7 +519,7 @@ func (s *HolderSyncer) syncIndex(index string) error { // Sync with every other host. for _, node := range Nodes(s.Cluster.Nodes).FilterHost(s.URI.HostPort()) { - client, err := NewInternalHTTPClient(node.Host, s.ClientOptions) + client, err := NewInternalHTTPClient(node.Host, s.RemoteClient) if err != nil { return err } @@ -563,7 +564,7 @@ func (s *HolderSyncer) syncFrame(index, name string) error { // Sync with every other host. for _, node := range Nodes(s.Cluster.Nodes).FilterHost(s.URI.HostPort()) { - client, err := NewInternalHTTPClient(node.Host, s.ClientOptions) + client, err := NewInternalHTTPClient(node.Host, s.RemoteClient) if err != nil { return err } @@ -616,11 +617,11 @@ func (s *HolderSyncer) syncFragment(index, frame, view string, slice uint64) err // Sync fragments together. fs := FragmentSyncer{ - Fragment: frag, - Host: s.URI.HostPort(), - Cluster: s.Cluster, - Closing: s.Closing, - ClientOptions: s.ClientOptions, + Fragment: frag, + Host: s.URI.HostPort(), + Cluster: s.Cluster, + Closing: s.Closing, + RemoteClient: s.RemoteClient, } if err := fs.SyncFragment(); err != nil { return err diff --git a/holder_test.go b/holder_test.go index 7020a1b8c..6cbfdf150 100644 --- a/holder_test.go +++ b/holder_test.go @@ -320,7 +320,7 @@ func TestHolder_DeleteIndex(t *testing.T) { // Ensure holder can sync with a remote holder. func TestHolderSyncer_SyncHolder(t *testing.T) { cluster := test.NewCluster(2) - + client := pilosa.GetHTTPClient(nil) // Create a local holder. hldr0 := test.MustOpenHolder() defer hldr0.Close() @@ -332,7 +332,7 @@ func TestHolderSyncer_SyncHolder(t *testing.T) { defer s.Close() s.Handler.Holder = hldr1.Holder s.Handler.Executor.ExecuteFn = func(ctx context.Context, index string, query *pql.Query, slices []uint64, opt *pilosa.ExecOptions) ([]interface{}, error) { - e := pilosa.NewExecutor(nil) + e := pilosa.NewExecutor(client) e.Holder = hldr1.Holder e.Scheme = cluster.Nodes[1].Scheme e.Host = cluster.Nodes[1].Host @@ -400,9 +400,10 @@ func TestHolderSyncer_SyncHolder(t *testing.T) { t.Fatal(err) } syncer := pilosa.HolderSyncer{ - Holder: hldr0.Holder, - URI: uri, - Cluster: cluster, + Holder: hldr0.Holder, + URI: uri, + Cluster: cluster, + RemoteClient: pilosa.GetHTTPClient(nil), } if err := syncer.SyncHolder(); err != nil { diff --git a/server.go b/server.go index a21b408c3..ffaad0b71 100644 --- a/server.go +++ b/server.go @@ -58,6 +58,7 @@ type Server struct { Handler *Handler Broadcaster Broadcaster BroadcastReceiver BroadcastReceiver + RemoteClient *http.Client // Cluster configuration. // Host is replaced with actual host after opening if port is ":0". @@ -167,10 +168,10 @@ func (s *Server) Open() error { } // Create default HTTP client - s.createDefaultClient() + s.createDefaultClient(s.RemoteClient) // Create executor for executing queries. - e := NewExecutor(&ClientOptions{TLS: s.TLS}) + e := NewExecutor(s.RemoteClient) e.Holder = s.Holder e.Scheme = s.URI.Scheme() e.Host = s.URI.HostPort() @@ -229,6 +230,25 @@ func (s *Server) Addr() net.Addr { } return s.ln.Addr() } +func GetHTTPClient(t *tls.Config) *http.Client { + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + MaxIdleConns: 1000, + MaxIdleConnsPerHost: 200, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + } + if t != nil { + transport.TLSClientConfig = t + } + return &http.Client{Transport: transport} +} // Logger returns a logger that writes to LogOutput func (s *Server) Logger() *log.Logger { return log.New(s.LogOutput, "", log.LstdFlags) } @@ -256,7 +276,7 @@ func (s *Server) monitorAntiEntropy() { syncer.URI = s.URI syncer.Cluster = s.Cluster syncer.Closing = s.closing - syncer.ClientOptions = &ClientOptions{TLS: s.TLS} + syncer.RemoteClient = s.RemoteClient // Sync holders. if err := syncer.SyncHolder(); err != nil { @@ -603,12 +623,8 @@ func (s *Server) monitorRuntime() { } } -func (s *Server) createDefaultClient() { - transport := &http.Transport{} - if s.TLS != nil { - transport.TLSClientConfig = s.TLS - } - s.defaultClient = NewInternalHTTPClientFromURI(nil, &ClientOptions{TLS: s.TLS}) +func (s *Server) createDefaultClient(remoteClient *http.Client) { + s.defaultClient = NewInternalHTTPClientFromURI(nil, remoteClient) } // CountOpenFiles on operating systems that support lsof. diff --git a/server/server.go b/server/server.go index 7cc8c5dec..a5f17f6d7 100644 --- a/server/server.go +++ b/server/server.go @@ -31,10 +31,11 @@ import ( "crypto/tls" + "io/ioutil" + "github.com/pilosa/pilosa" "github.com/pilosa/pilosa/gossip" "github.com/pilosa/pilosa/statsd" - "io/ioutil" ) func init() { @@ -161,6 +162,7 @@ func (m *Command) SetupServer() error { m.Server.MaxWritesPerRequest = m.Config.MaxWritesPerRequest // Setup TLS + var TLSConfig *tls.Config if uri.Scheme() == "https" { if m.Config.TLS.CertificatePath == "" { return errors.New("certificate path is required for TLS sockets") @@ -176,8 +178,15 @@ func (m *Command) SetupServer() error { Certificates: []tls.Certificate{cert}, InsecureSkipVerify: m.Config.TLS.SkipVerify, } - m.Server.Handler.ClientOptions = &pilosa.ClientOptions{TLS: m.Server.TLS} + + // TODO Review this location + + TLSConfig = m.Server.TLS + } + c := pilosa.GetHTTPClient(TLSConfig) + m.Server.RemoteClient = c + m.Server.Handler.RemoteClient = c // Set internal port (string). gossipPortStr := pilosa.DefaultGossipPort diff --git a/server/server_test.go b/server/server_test.go index d22abbd1b..28886bc67 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -50,7 +50,7 @@ func TestMain_Set_Quick(t *testing.T) { defer m.Close() // Create client. - client, err := pilosa.NewInternalHTTPClient(m.Server.URI.HostPort(), nil) + client, err := pilosa.NewInternalHTTPClient(m.Server.URI.HostPort(), pilosa.GetHTTPClient(nil)) if err != nil { t.Fatal(err) } @@ -323,7 +323,7 @@ func TestMain_FrameRestore(t *testing.T) { defer m2.Close() // Import from first cluster. - client, err := pilosa.NewInternalHTTPClient(m2.Server.URI.HostPort(), nil) + client, err := pilosa.NewInternalHTTPClient(m2.Server.URI.HostPort(), pilosa.GetHTTPClient(nil)) if err != nil { t.Fatal(err) } else if err := m2.Client().CreateIndex(context.Background(), "i", pilosa.IndexOptions{}); err != nil && err != pilosa.ErrIndexExists { @@ -672,7 +672,7 @@ func (m *Main) URL() string { return "http://" + m.Server.Addr().String() } // Client returns a client to connect to the program. func (m *Main) Client() *pilosa.InternalHTTPClient { - client, err := pilosa.NewInternalHTTPClient(m.Server.URI.HostPort(), nil) + client, err := pilosa.NewInternalHTTPClient(m.Server.URI.HostPort(), pilosa.GetHTTPClient(nil)) if err != nil { panic(err) } diff --git a/test/client.go b/test/client.go index 4ea2fbbad..5eac8cb79 100644 --- a/test/client.go +++ b/test/client.go @@ -1,6 +1,8 @@ package test import ( + "net/http" + "github.com/pilosa/pilosa" ) @@ -10,8 +12,8 @@ type Client struct { } // MustNewClient returns a new instance of Client. Panic on error. -func MustNewClient(host string) *Client { - c, err := pilosa.NewInternalHTTPClient(host, nil) +func MustNewClient(host string, h *http.Client) *Client { + c, err := pilosa.NewInternalHTTPClient(host, h) if err != nil { panic(err) } diff --git a/test/executor.go b/test/executor.go index be370908d..1cddfd521 100644 --- a/test/executor.go +++ b/test/executor.go @@ -15,7 +15,7 @@ type Executor struct { // NewExecutor returns a new instance of Executor. // The executor always matches the hostname of the first cluster node. func NewExecutor(holder *pilosa.Holder, cluster *pilosa.Cluster) *Executor { - executor := pilosa.NewExecutor(nil) + executor := pilosa.NewExecutor(pilosa.GetHTTPClient(nil)) e := &Executor{Executor: executor} e.Holder = holder e.Cluster = cluster From caede44346cec4b8d3a6e90791620b368c342c83 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Mon, 4 Dec 2017 12:17:41 -0600 Subject: [PATCH 04/14] limit httpclient instances on executor tests --- test/executor.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/executor.go b/test/executor.go index 1cddfd521..f00692361 100644 --- a/test/executor.go +++ b/test/executor.go @@ -1,6 +1,7 @@ package test import ( + "net/http" "strings" "github.com/pilosa/pilosa" @@ -12,10 +13,16 @@ type Executor struct { *pilosa.Executor } +var remoteClient *http.Client + +func init() { + remoteClient = pilosa.GetHTTPClient(nil) +} + // NewExecutor returns a new instance of Executor. // The executor always matches the hostname of the first cluster node. func NewExecutor(holder *pilosa.Holder, cluster *pilosa.Cluster) *Executor { - executor := pilosa.NewExecutor(pilosa.GetHTTPClient(nil)) + executor := pilosa.NewExecutor(remoteClient) e := &Executor{Executor: executor} e.Holder = holder e.Cluster = cluster From 25056e301533cc8aa8fdac9bd326a94b2f28b7f2 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Tue, 5 Dec 2017 14:41:08 -0600 Subject: [PATCH 05/14] Release v0.8.2 --- CHANGELOG.md | 8 ++++++++ docs/installation.md | 12 ++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b43d73c04..bad4e0914 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.8.2] - 2017-12-05 + +This version contains 1 contribution from 1 contributor. There are 15 files changed, 127 insertions, and 98 deletions. + +### Fixed + +- Modify initialization of HTTP client so only one instance is created ([#994](https://github.com/pilosa/pilosa/pull/994)) + ## [0.8.1] - 2017-11-15 This version contains 2 contributions from 2 contributors. There are 4 files changed, 27 insertions, and 14 deletions. diff --git a/docs/installation.md b/docs/installation.md index 991634a77..5664fa3b3 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -74,19 +74,19 @@ There are four ways to install Pilosa on MacOS: Use [Homebrew](https://brew.sh/) 1. Download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.1/pilosa-v0.8.1-darwin-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.2/pilosa-v0.8.2-darwin-amd64.tar.gz ``` Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.1-darwin-amd64.tar.gz + tar xfz pilosa-v0.8.2-darwin-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.1-darwin-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.2-darwin-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: @@ -228,19 +228,19 @@ There are three ways to install Pilosa on Linux: download the binary (recommende 1. To install the latest version of Pilosa, download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.1/pilosa-v0.8.1-linux-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.2/pilosa-v0.8.2-linux-amd64.tar.gz ``` Note: This assumes you are using an `amd64` compatible architecture. Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.1-linux-amd64.tar.gz + tar xfz pilosa-v0.8.2-linux-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.1-linux-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.2-linux-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: From 8fa965df37d906d88f977b1245e7453218ad4855 Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Thu, 7 Dec 2017 14:02:25 -0600 Subject: [PATCH 06/14] protect against accessing pointers to memory which was unmapped --- roaring/roaring.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/roaring/roaring.go b/roaring/roaring.go index 97994c37a..ad7b33bc4 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -665,13 +665,19 @@ func (b *Bitmap) UnmarshalBinary(data []byte) error { c := b.containers[i] switch c.container_type { case ContainerRun: + c.array = nil + c.bitmap = nil runCount := binary.LittleEndian.Uint16(data[offset : offset+runCountHeaderSize]) c.runs = (*[0xFFFFFFF]interval16)(unsafe.Pointer(&data[offset+runCountHeaderSize]))[:runCount] opsOffset = int(offset) + runCountHeaderSize + len(c.runs)*interval16Size case ContainerArray: + c.runs = nil + c.bitmap = nil c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[offset]))[:c.n] opsOffset = int(offset) + len(c.array)*2 // sizeof(uint32) case ContainerBitmap: + c.array = nil + c.runs = nil c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[offset]))[:bitmapN] opsOffset = int(offset) + len(c.bitmap)*8 // sizeof(uint64) } @@ -1019,17 +1025,16 @@ func (c *container) unmap() { return } - if c.array != nil { + switch c.container_type { + case ContainerArray: tmp := make([]uint16, len(c.array)) copy(tmp, c.array) c.array = tmp - } - if c.bitmap != nil { + case ContainerBitmap: tmp := make([]uint64, len(c.bitmap)) copy(tmp, c.bitmap) c.bitmap = tmp - } - if c.runs != nil { + case ContainerRun: tmp := make([]interval16, len(c.runs)) copy(tmp, c.runs) c.runs = tmp @@ -1614,21 +1619,17 @@ func (c *container) runToArray() { func (c *container) clone() *container { other := &container{n: c.n, container_type: c.container_type} - if c.array != nil { + switch c.container_type { + case ContainerArray: other.array = make([]uint16, len(c.array)) copy(other.array, c.array) - } - - if c.bitmap != nil { + case ContainerBitmap: other.bitmap = make([]uint64, len(c.bitmap)) copy(other.bitmap, c.bitmap) - } - - if c.runs != nil { + case ContainerRun: other.runs = make([]interval16, len(c.runs)) copy(other.runs, c.runs) } - return other } From 9d9eb98fa591f33b622c1e0944c9db0e0529eefe Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Thu, 7 Dec 2017 14:58:11 -0600 Subject: [PATCH 07/14] add container types and set c.n to get tests working --- roaring/roaring_internal_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index b36723b26..aae6f9b22 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -1267,8 +1267,8 @@ func TestBitmapZeroRange(t *testing.T) { } func TestUnionBitmapRun(t *testing.T) { - a := &container{bitmap: make([]uint64, bitmapN)} - b := &container{} + a := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)} + b := &container{container_type: ContainerRun} tests := []struct { bitmap []uint64 runs []interval16 @@ -1288,6 +1288,7 @@ func TestUnionBitmapRun(t *testing.T) { } a.n = a.bitmapCountRange(0, 65535) b.runs = test.runs + b.n = b.runCountRange(0, 65535) ret := unionBitmapRun(a, b) if ret.isArray() { ret.arrayToBitmap() @@ -1556,8 +1557,8 @@ func TestDifferenceRunBitmap(t *testing.T) { } func TestDifferenceBitmapRun(t *testing.T) { - a := &container{bitmap: make([]uint64, bitmapN)} - b := &container{} + a := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)} + b := &container{container_type: ContainerRun} tests := []struct { bitmap []uint64 runs []interval16 From 256b736dc0e68cacf72bfd875a9ec9ab030842a6 Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Thu, 7 Dec 2017 15:20:53 -0600 Subject: [PATCH 08/14] add container types to other tests (though they were passing already) --- roaring/roaring_internal_test.go | 65 ++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/roaring/roaring_internal_test.go b/roaring/roaring_internal_test.go index aae6f9b22..f5c12aa83 100644 --- a/roaring/roaring_internal_test.go +++ b/roaring/roaring_internal_test.go @@ -347,8 +347,8 @@ func TestRunMax(t *testing.T) { } func TestIntersectionCountArrayRun(t *testing.T) { - a := &container{array: []uint16{1, 5, 10, 11, 12}} - b := &container{runs: []interval16{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}} + a := &container{container_type: ContainerArray, array: []uint16{1, 5, 10, 11, 12}} + b := &container{container_type: ContainerRun, runs: []interval16{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}} ret := intersectionCountArrayRun(a, b) if ret != 3 { @@ -357,16 +357,16 @@ func TestIntersectionCountArrayRun(t *testing.T) { } func TestIntersectionCountBitmapRun(t *testing.T) { - a := &container{bitmap: []uint64{0x8000000000000000}} - b := &container{runs: []interval16{{start: 63, last: 64}}} + a := &container{container_type: ContainerBitmap, bitmap: []uint64{0x8000000000000000}} + b := &container{container_type: ContainerRun, runs: []interval16{{start: 63, last: 64}}} ret := intersectionCountBitmapRun(a, b) if ret != 1 { t.Fatalf("count of %v with %v should be 1, but got %v", a.bitmap, b.runs, ret) } - a = &container{bitmap: []uint64{0xF0000001, 0xFF00000000000000, 0xFF000000000000F0, 0x0F0000}} - b = &container{runs: []interval16{{start: 29, last: 31}, {start: 125, last: 134}, {start: 191, last: 197}, {start: 200, last: 300}}} + a = &container{container_type: ContainerBitmap, bitmap: []uint64{0xF0000001, 0xFF00000000000000, 0xFF000000000000F0, 0x0F0000}} + b = &container{container_type: ContainerRun, runs: []interval16{{start: 29, last: 31}, {start: 125, last: 134}, {start: 191, last: 197}, {start: 200, last: 300}}} ret = intersectionCountBitmapRun(a, b) if ret != 14 { @@ -414,6 +414,8 @@ func TestIntersectionCountRunRun(t *testing.T) { bruns: []interval16{{start: 9, last: 9}, {start: 11, last: 17}}, exp: 6}, } for i, test := range tests { + a.container_type = ContainerRun + b.container_type = ContainerRun a.runs = test.aruns b.runs = test.bruns ret := intersectionCountRunRun(a, b) @@ -454,6 +456,8 @@ func TestIntersectArrayRun(t *testing.T) { } for i, test := range tests { + a.container_type = ContainerArray + b.container_type = ContainerRun a.array = test.array b.runs = test.runs ret := intersectArrayRun(a, b) @@ -510,6 +514,8 @@ func TestIntersectRunRun(t *testing.T) { }, } for i, test := range tests { + a.container_type = ContainerRun + b.container_type = ContainerRun a.runs = test.aruns b.runs = test.bruns ret := intersectRunRun(a, b) @@ -573,6 +579,8 @@ func TestIntersectBitmapRunBitmap(t *testing.T) { for i, v := range test.exp { exp[i] = v } + a.container_type = ContainerBitmap + b.container_type = ContainerRun ret := intersectBitmapRun(a, b) if ret.isArray() { ret.arrayToBitmap() @@ -632,6 +640,8 @@ func TestIntersectBitmapRunArray(t *testing.T) { a.bitmap[i] = v } b.runs = test.runs + a.container_type = ContainerBitmap + b.container_type = ContainerRun ret := intersectBitmapRun(a, b) if !reflect.DeepEqual(ret.array, test.exp) { t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array) @@ -873,6 +883,8 @@ func TestUnionRunRun(t *testing.T) { for i, test := range tests { a.runs = test.aruns b.runs = test.bruns + a.container_type = ContainerRun + b.container_type = ContainerRun ret := unionRunRun(a, b) if !reflect.DeepEqual(ret.runs, test.exp) { t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs) @@ -913,6 +925,8 @@ func TestUnionArrayRun(t *testing.T) { for i, test := range tests { a.array = test.array b.runs = test.runs + a.container_type = ContainerArray + b.container_type = ContainerRun ret := unionArrayRun(a, b) if !reflect.DeepEqual(ret.array, test.exp) { t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array) @@ -921,7 +935,7 @@ func TestUnionArrayRun(t *testing.T) { } func TestBitmapSetRange(t *testing.T) { - c := &container{bitmap: make([]uint64, bitmapN)} + c := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)} tests := []struct { bitmap []uint64 start uint64 @@ -961,7 +975,7 @@ func TestBitmapSetRange(t *testing.T) { } func TestArrayToBitmap(t *testing.T) { - a := &container{} + a := &container{container_type: ContainerArray} tests := []struct { array []uint16 exp []uint64 @@ -992,7 +1006,7 @@ func TestArrayToBitmap(t *testing.T) { } func TestBitmapToArray(t *testing.T) { - a := &container{} + a := &container{container_type: ContainerBitmap} tests := []struct { bitmap []uint64 exp []uint16 @@ -1023,7 +1037,7 @@ func TestBitmapToArray(t *testing.T) { } func TestRunToBitmap(t *testing.T) { - a := &container{} + a := &container{container_type: ContainerRun} tests := []struct { runs []interval16 exp []uint64 @@ -1077,7 +1091,7 @@ func getFullBitmap() []uint64 { } func TestBitmapToRun(t *testing.T) { - a := &container{} + a := &container{container_type: ContainerBitmap} tests := []struct { bitmap []uint64 exp []interval16 @@ -1155,7 +1169,7 @@ func TestBitmapToRun(t *testing.T) { } func TestArrayToRun(t *testing.T) { - a := &container{} + a := &container{container_type: ContainerArray} tests := []struct { array []uint16 exp []interval16 @@ -1189,7 +1203,7 @@ func TestArrayToRun(t *testing.T) { } func TestRunToArray(t *testing.T) { - a := &container{} + a := &container{container_type: ContainerRun} tests := []struct { runs []interval16 exp []uint16 @@ -1223,7 +1237,7 @@ func TestRunToArray(t *testing.T) { } func TestBitmapZeroRange(t *testing.T) { - c := &container{bitmap: make([]uint64, bitmapN)} + c := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)} tests := []struct { bitmap []uint64 start uint64 @@ -1306,7 +1320,7 @@ func TestUnionBitmapRun(t *testing.T) { } func TestBitmapCountRuns(t *testing.T) { - c := &container{bitmap: make([]uint64, bitmapN)} + c := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)} tests := []struct { bitmap []uint64 exp int @@ -1356,7 +1370,7 @@ func TestBitmapCountRuns(t *testing.T) { } func TestArrayCountRuns(t *testing.T) { - c := &container{} + c := &container{container_type: ContainerArray} tests := []struct { array []uint16 exp int @@ -1397,8 +1411,8 @@ func TestArrayCountRuns(t *testing.T) { } func TestDifferenceArrayRun(t *testing.T) { - a := &container{} - b := &container{} + a := &container{container_type: ContainerArray} + b := &container{container_type: ContainerRun} tests := []struct { array []uint16 runs []interval16 @@ -1423,8 +1437,8 @@ func TestDifferenceArrayRun(t *testing.T) { } func TestDifferenceRunArray(t *testing.T) { - a := &container{} - b := &container{} + a := &container{container_type: ContainerRun} + b := &container{container_type: ContainerArray} tests := []struct { runs []interval16 array []uint16 @@ -1494,8 +1508,8 @@ func MakeLastBitSet() []uint64 { } func TestDifferenceRunBitmap(t *testing.T) { - a := &container{} - b := &container{bitmap: make([]uint64, bitmapN)} + a := &container{container_type: ContainerRun} + b := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)} tests := []struct { runs []interval16 bitmap []uint64 @@ -1585,7 +1599,7 @@ func TestDifferenceBitmapRun(t *testing.T) { } func TestDifferenceBitmapArray(t *testing.T) { - b := &container{bitmap: make([]uint64, bitmapN), container_type: ContainerBitmap} + b := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)} a := &container{container_type: ContainerArray} tests := []struct { bitmap []uint64 @@ -2514,8 +2528,9 @@ func TestSearc64(t *testing.T) { } func TestIntersectArrayBitmap(t *testing.T) { - a, b := &container{}, &container{ - bitmap: make([]uint64, bitmapN), + a, b := &container{container_type: ContainerArray}, &container{ + container_type: ContainerBitmap, + bitmap: make([]uint64, bitmapN), } tests := []struct { array []uint16 From acf73194cda1b7becd2054a0a1ff2780e6ec5d34 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Tue, 12 Dec 2017 16:37:56 -0600 Subject: [PATCH 09/14] Release v0.8.3 --- CHANGELOG.md | 8 ++++++++ docs/installation.md | 12 ++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bad4e0914..9676b4f89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.8.3] - 2017-12-12 + +This version contains 1 contribution from 1 contributor. There are 2 files changed, 59 insertions, and 42 deletions. + +### Fixed + +- Protect against accessing pointers to memory which was unmapped ([#1000](https://github.com/pilosa/pilosa/pull/1000)) + ## [0.8.2] - 2017-12-05 This version contains 1 contribution from 1 contributor. There are 15 files changed, 127 insertions, and 98 deletions. diff --git a/docs/installation.md b/docs/installation.md index 5664fa3b3..5a0ea3086 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -74,19 +74,19 @@ There are four ways to install Pilosa on MacOS: Use [Homebrew](https://brew.sh/) 1. Download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.2/pilosa-v0.8.2-darwin-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.3/pilosa-v0.8.3-darwin-amd64.tar.gz ``` Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.2-darwin-amd64.tar.gz + tar xfz pilosa-v0.8.3-darwin-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.2-darwin-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.3-darwin-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: @@ -228,19 +228,19 @@ There are three ways to install Pilosa on Linux: download the binary (recommende 1. To install the latest version of Pilosa, download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.2/pilosa-v0.8.2-linux-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.3/pilosa-v0.8.3-linux-amd64.tar.gz ``` Note: This assumes you are using an `amd64` compatible architecture. Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.2-linux-amd64.tar.gz + tar xfz pilosa-v0.8.3-linux-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.2-linux-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.3-linux-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: From 7d26cc468e7d51f02c4158a49875164a188a0f8d Mon Sep 17 00:00:00 2001 From: Travis Turner Date: Fri, 22 Dec 2017 17:06:24 -0600 Subject: [PATCH 10/14] change gossip config from memberlist.DefaultLocalConfig to memberlist.DefaultWANConfig --- gossip/gossip.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gossip/gossip.go b/gossip/gossip.go index 7085710b3..24e802254 100644 --- a/gossip/gossip.go +++ b/gossip/gossip.go @@ -130,7 +130,7 @@ func NewGossipNodeSet(name string, gossipHost string, gossipPort int, gossipSeed //TODO: pull memberlist config from pilosa.cfg file g.config = &gossipConfig{ - memberlistConfig: memberlist.DefaultLocalConfig(), + memberlistConfig: memberlist.DefaultWANConfig(), gossipSeed: gossipSeed, } g.config.memberlistConfig.Name = name From 42032584b59d14550e099867f289344bce0f149c Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 9 Jan 2018 12:42:27 -0600 Subject: [PATCH 11/14] fix a number of data races datadog statsd client contained a race condition - was fixed in master Server.Logger contained a race where multiple loggers could write to the same output io.Writer TestMain_FrameRestore contained a race where it tried to change a cluster's nodes while it was running (which conflicted with antiEntropy reading that state). --- Gopkg.lock | 10 +++++----- Gopkg.toml | 8 ++++++++ server.go | 5 +++-- server/server_test.go | 35 ++++++++++++++--------------------- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index ed772ef39..96a72b8f2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -14,10 +14,10 @@ revision = "39b0596a2da3c92787b3319c6b5425a474b4e0da" [[projects]] + branch = "master" name = "github.com/DataDog/datadog-go" packages = ["statsd"] - revision = "0ddda6bee21174ef6c4873647cb0d6ec9cba996f" - version = "1.1.0" + revision = "4d2e5696ebe914940bd7459d2266fb7d555ea1b7" [[projects]] branch = "master" @@ -46,8 +46,8 @@ [[projects]] name = "github.com/gogo/protobuf" packages = ["proto"] - revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02" - version = "v0.5" + revision = "100ba4e885062801d56799d78530b73b178a78f3" + version = "v0.4" [[projects]] branch = "master" @@ -238,6 +238,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "75badb0bcc3bb356b04af17979e0af61b4b66c5e0a483f09e39cf1f9b5e5de2c" + inputs-digest = "d7c279ee1c617ec26e329979b5f92021287ede9701ff41e57c1fecad92ec6b51" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 7ffa67a2f..50eddac23 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,3 +1,11 @@ # This file intentionally left blank as all needed dependencies are imported by # the project and thus tracked by `dep`. # See https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md for details. + + +[[constraint]] + # Required: the root import path of the project being constrained. + name = "github.com/DataDog/datadog-go" + # Recommended: the version constraint to enforce for the project. + # Only one of "branch", "version" or "revision" can be specified. + branch = "master" diff --git a/server.go b/server.go index ffaad0b71..cb4cab7bd 100644 --- a/server.go +++ b/server.go @@ -80,6 +80,7 @@ type Server struct { MaxWritesPerRequest int LogOutput io.Writer + logger *log.Logger defaultClient InternalClient } @@ -104,9 +105,9 @@ func NewServer() *Server { LogOutput: os.Stderr, } + s.logger = log.New(s.LogOutput, "", log.LstdFlags) s.Handler.Holder = s.Holder - return s } @@ -251,7 +252,7 @@ func GetHTTPClient(t *tls.Config) *http.Client { } // Logger returns a logger that writes to LogOutput -func (s *Server) Logger() *log.Logger { return log.New(s.LogOutput, "", log.LstdFlags) } +func (s *Server) Logger() *log.Logger { return s.logger } func (s *Server) monitorAntiEntropy() { ticker := time.NewTicker(s.AntiEntropyInterval) diff --git a/server/server_test.go b/server/server_test.go index 28886bc67..ba3d66108 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -278,24 +278,17 @@ func TestMain_SetColumnAttrsWithColumnOption(t *testing.T) { // Ensure program can set bits on one cluster and then restore to a second cluster. func TestMain_FrameRestore(t *testing.T) { m0 := MustRunMain() - defer m0.Close() - - m1 := MustRunMain() - defer m1.Close() - - // Update cluster config. - m0.Server.Cluster.Nodes = []*pilosa.Node{ - {Scheme: "http", Host: m0.Server.URI.HostPort()}, - {Scheme: "http", Host: m1.Server.URI.HostPort()}, - } - m1.Server.Cluster.Nodes = m0.Server.Cluster.Nodes + // TODO: this test used to start a two node cluster, but there was a race + // condition with anti-entropy. We need some general code for starting up + // arbitrarily sized Pilosa clusters for testing, and then we should + // re-instate the multi-node nature of this test. // Create frames. client := m0.Client() if err := client.CreateIndex(context.Background(), "i", pilosa.IndexOptions{}); err != nil && err != pilosa.ErrIndexExists { - t.Fatal(err) + t.Fatal("create index:", err) } else if err := client.CreateFrame(context.Background(), "i", "f", pilosa.FrameOptions{}); err != nil { - t.Fatal(err) + t.Fatal("create frame:", err) } // Write data on first cluster. @@ -308,12 +301,12 @@ func TestMain_FrameRestore(t *testing.T) { SetBit(rowID=1, frame="f", columnID=600000) SetBit(rowID=1, frame="f", columnID=800000) `); err != nil { - t.Fatal(err) + t.Fatal("setting bits:", err) } // Query row on first cluster. if res, err := m0.Query("i", "", `Bitmap(rowID=1, frame="f")`); err != nil { - t.Fatal(err) + t.Fatal("bitmap query:", err) } else if res != `{"results":[{"attrs":{},"bits":[100,1000,100000,200000,400000,600000,800000]}]}`+"\n" { t.Fatalf("unexpected result: %s", res) } @@ -325,20 +318,20 @@ func TestMain_FrameRestore(t *testing.T) { // Import from first cluster. client, err := pilosa.NewInternalHTTPClient(m2.Server.URI.HostPort(), pilosa.GetHTTPClient(nil)) if err != nil { - t.Fatal(err) + t.Fatal("new client:", err) } else if err := m2.Client().CreateIndex(context.Background(), "i", pilosa.IndexOptions{}); err != nil && err != pilosa.ErrIndexExists { - t.Fatal(err) + t.Fatal("create new index:", err) } else if err := m2.Client().CreateFrame(context.Background(), "i", "f", pilosa.FrameOptions{}); err != nil { - t.Fatal(err) + t.Fatal("create new frame:", err) } else if err := client.RestoreFrame(context.Background(), m0.Server.URI.HostPort(), "i", "f"); err != nil { - t.Fatal(err) + t.Fatal("restore frame:", err) } // Query row on second cluster. if res, err := m2.Query("i", "", `Bitmap(rowID=1, frame="f")`); err != nil { - t.Fatal(err) + t.Fatal("another bitmap query:", err) } else if res != `{"results":[{"attrs":{},"bits":[100,1000,100000,200000,400000,600000,800000]}]}`+"\n" { - t.Fatalf("unexpected result: %s", res) + t.Fatalf("2unexpected result: %s", res) } } From 55de0402d250845cda454b842aed24caf0b00796 Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 9 Jan 2018 13:50:40 -0600 Subject: [PATCH 12/14] convert some locks to rlocks --- frame.go | 4 ++-- holder.go | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/frame.go b/frame.go index 3da55cc93..e6792f4c0 100644 --- a/frame.go +++ b/frame.go @@ -533,8 +533,8 @@ func (f *Frame) view(name string) *View { return f.views[name] } // Views returns a list of all views in the frame. func (f *Frame) Views() []*View { - f.mu.Lock() - defer f.mu.Unlock() + f.mu.RLock() + defer f.mu.RUnlock() other := make([]*View, 0, len(f.views)) for _, view := range f.views { diff --git a/holder.go b/holder.go index 7cbb8ca42..416ddc232 100644 --- a/holder.go +++ b/holder.go @@ -196,15 +196,14 @@ func (h *Holder) index(name string) *Index { return h.indexes[name] } // Indexes returns a list of all indexes in the holder. func (h *Holder) Indexes() []*Index { - h.mu.Lock() - defer h.mu.Unlock() - + h.mu.RLock() a := make([]*Index, 0, len(h.indexes)) for _, index := range h.indexes { a = append(a, index) } - sort.Sort(indexSlice(a)) + h.mu.RUnlock() + sort.Sort(indexSlice(a)) return a } From 298d8ea866ead305abcdc5f0d176a50777b8ecd9 Mon Sep 17 00:00:00 2001 From: Travis Turner Date: Tue, 9 Jan 2018 14:30:05 -0600 Subject: [PATCH 13/14] change AttrBlock handler calls to support protobuf instead of json --- attr.go | 48 +++++ client.go | 54 +++-- handler.go | 94 +++++---- handler_test.go | 91 +++++++-- internal/private.pb.go | 435 +++++++++++++++++++++++++++++++++++------ internal/private.proto | 10 + internal/public.pb.go | 332 +++++++++++++++++++++++++++---- internal/public.proto | 4 + 8 files changed, 903 insertions(+), 165 deletions(-) diff --git a/attr.go b/attr.go index ab29fc9c0..86b179f27 100644 --- a/attr.go +++ b/attr.go @@ -348,6 +348,22 @@ func txUpdateAttrs(tx *bolt.Tx, id uint64, m map[string]interface{}) (map[string return attr, nil } +func encodeAttrsMap(m map[uint64]map[string]interface{}) map[uint64]*internal.AttrMap { + r := make(map[uint64]*internal.AttrMap, len(m)) + for k, v := range m { + r[k] = &internal.AttrMap{Attrs: encodeAttrs(v)} + } + return r +} + +func DecodeAttrsMap(m map[uint64]*internal.AttrMap) map[uint64]map[string]interface{} { + r := make(map[uint64]map[string]interface{}, len(m)) + for k, v := range m { + r[k] = decodeAttrs(v.Attrs) + } + return r +} + func encodeAttrs(m map[string]interface{}) []*internal.Attr { keys := make([]string, 0, len(m)) for k := range m { @@ -438,6 +454,38 @@ type AttrBlock struct { Checksum []byte `json:"checksum"` } +// EncodeAttrBlocks converts a into its internal representation. +func EncodeAttrBlocks(a []AttrBlock) []*internal.AttrBlock { + other := make([]*internal.AttrBlock, len(a)) + for i := range a { + other[i] = encodeAttrBlock(&a[i]) + } + return other +} + +// encodeAttrBlock converts b into its internal representation. +func encodeAttrBlock(b *AttrBlock) *internal.AttrBlock { + return &internal.AttrBlock{ + ID: b.ID, + Checksum: b.Checksum, + } +} + +func decodeAttrBlocks(a []*internal.AttrBlock) []AttrBlock { + other := make([]AttrBlock, len(a)) + for i := range a { + other[i] = decodeAttrBlock(a[i]) + } + return other +} + +func decodeAttrBlock(b *internal.AttrBlock) AttrBlock { + return AttrBlock{ + ID: b.ID, + Checksum: b.Checksum, + } +} + // AttrBlocks represents a list of blocks. type AttrBlocks []AttrBlock diff --git a/client.go b/client.go index e44d9c5de..9b2465b88 100644 --- a/client.go +++ b/client.go @@ -966,10 +966,12 @@ func (c *InternalHTTPClient) BlockData(ctx context.Context, index, frame, view s func (c *InternalHTTPClient) ColumnAttrDiff(ctx context.Context, index string, blks []AttrBlock) (map[uint64]map[string]interface{}, error) { u := uriPathToURL(c.defaultURI, fmt.Sprintf("/index/%s/attr/diff", index)) - // Encode request. - buf, err := json.Marshal(postIndexAttrDiffRequest{Blocks: blks}) + // Encode request object. + buf, err := proto.Marshal(&internal.AttrBlockRequest{ + Blocks: EncodeAttrBlocks(blks), + }) if err != nil { - return nil, err + return nil, fmt.Errorf("marshal column attr block request: %s", err) } // Build request. @@ -977,7 +979,9 @@ func (c *InternalHTTPClient) ColumnAttrDiff(ctx context.Context, index string, b if err != nil { return nil, err } - req.Header.Set("Content-Type", "application/json") + req.Header.Set("Content-Length", strconv.Itoa(len(buf))) + req.Header.Set("Content-Type", "application/x-protobuf") + req.Header.Set("Accept", "application/x-protobuf") req.Header.Set("User-Agent", "pilosa/"+Version) // Execute request. @@ -994,22 +998,31 @@ func (c *InternalHTTPClient) ColumnAttrDiff(ctx context.Context, index string, b return nil, fmt.Errorf("unexpected status: code=%d", resp.StatusCode) } - // Decode response object. - var rsp postIndexAttrDiffResponse - if err := json.NewDecoder(resp.Body).Decode(&rsp); err != nil { + // Read body. + body, err := ioutil.ReadAll(resp.Body) + if err != nil { return nil, err } - return rsp.Attrs, nil + + // Decode response object. + abresp := &internal.AttrBlockResponse{} + if err := proto.Unmarshal(body, abresp); err != nil { + return nil, fmt.Errorf("unmarshal attribute block response: %s", err) + } + + return DecodeAttrsMap(abresp.Attrs), nil } // RowAttrDiff returns data from differing blocks on a remote host. func (c *InternalHTTPClient) RowAttrDiff(ctx context.Context, index, frame string, blks []AttrBlock) (map[uint64]map[string]interface{}, error) { u := uriPathToURL(c.defaultURI, fmt.Sprintf("/index/%s/frame/%s/attr/diff", index, frame)) - // Encode request. - buf, err := json.Marshal(postFrameAttrDiffRequest{Blocks: blks}) + // Encode request object. + buf, err := proto.Marshal(&internal.AttrBlockRequest{ + Blocks: EncodeAttrBlocks(blks), + }) if err != nil { - return nil, err + return nil, fmt.Errorf("marshal row attr block request: %s", err) } // Build request. @@ -1017,7 +1030,9 @@ func (c *InternalHTTPClient) RowAttrDiff(ctx context.Context, index, frame strin if err != nil { return nil, err } - req.Header.Set("Content-Type", "application/json") + req.Header.Set("Content-Length", strconv.Itoa(len(buf))) + req.Header.Set("Content-Type", "application/x-protobuf") + req.Header.Set("Accept", "application/x-protobuf") req.Header.Set("User-Agent", "pilosa/"+Version) // Execute request. @@ -1036,12 +1051,19 @@ func (c *InternalHTTPClient) RowAttrDiff(ctx context.Context, index, frame strin return nil, fmt.Errorf("unexpected status: code=%d", resp.StatusCode) } - // Decode response object. - var rsp postFrameAttrDiffResponse - if err := json.NewDecoder(resp.Body).Decode(&rsp); err != nil { + // Read body. + body, err := ioutil.ReadAll(resp.Body) + if err != nil { return nil, err } - return rsp.Attrs, nil + + // Decode response object. + abresp := &internal.AttrBlockResponse{} + if err := proto.Unmarshal(body, abresp); err != nil { + return nil, fmt.Errorf("unmarshal attribute block response: %s", err) + } + + return DecodeAttrsMap(abresp.Attrs), nil } func (c *InternalHTTPClient) clientURI(ctx context.Context) *URI { diff --git a/handler.go b/handler.go index ad9e02e2e..0efe512fa 100644 --- a/handler.go +++ b/handler.go @@ -538,11 +538,27 @@ type patchIndexTimeQuantumResponse struct{} // handlePostIndexAttrDiff handles POST /index/attr/diff requests. func (h *Handler) handlePostIndexAttrDiff(w http.ResponseWriter, r *http.Request) { + // Verify that request is only communicating over protobufs. + if r.Header.Get("Content-Type") != "application/x-protobuf" { + http.Error(w, "Unsupported media type", http.StatusUnsupportedMediaType) + return + } else if r.Header.Get("Accept") != "application/x-protobuf" { + http.Error(w, "Not acceptable", http.StatusNotAcceptable) + return + } + indexName := mux.Vars(r)["index"] - // Decode request. - var req postIndexAttrDiffRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + // Read entire body. + body, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // Marshal into request object. + var req internal.AttrBlockRequest + if err := proto.Unmarshal(body, &req); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -563,7 +579,7 @@ func (h *Handler) handlePostIndexAttrDiff(w http.ResponseWriter, r *http.Request // Read all attributes from all mismatched blocks. attrs := make(map[uint64]map[string]interface{}) - for _, blockID := range AttrBlocks(blks).Diff(req.Blocks) { + for _, blockID := range AttrBlocks(blks).Diff(decodeAttrBlocks(req.Blocks)) { // Retrieve block data. m, err := index.ColumnAttrStore().BlockData(blockID) if err != nil { @@ -577,20 +593,17 @@ func (h *Handler) handlePostIndexAttrDiff(w http.ResponseWriter, r *http.Request } } - // Encode response. - if err := json.NewEncoder(w).Encode(postIndexAttrDiffResponse{ - Attrs: attrs, - }); err != nil { - h.logger().Printf("response encoding error: %s", err) + // Marshal response object. + buf, err := proto.Marshal(&internal.AttrBlockResponse{ + Attrs: encodeAttrsMap(attrs), + }) + + // Write response. + if err != nil { + h.logger().Printf("row attr response encoding error: %s", err) + w.WriteHeader(http.StatusInternalServerError) } -} - -type postIndexAttrDiffRequest struct { - Blocks []AttrBlock `json:"blocks"` -} - -type postIndexAttrDiffResponse struct { - Attrs map[uint64]map[string]interface{} `json:"attrs"` + w.Write(buf) } // handlePostFrame handles POST /frame request. @@ -956,12 +969,28 @@ type getFrameViewsResponse struct { // handlePostFrameAttrDiff handles POST /frame/attr/diff requests. func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request) { + // Verify that request is only communicating over protobufs. + if r.Header.Get("Content-Type") != "application/x-protobuf" { + http.Error(w, "Unsupported media type", http.StatusUnsupportedMediaType) + return + } else if r.Header.Get("Accept") != "application/x-protobuf" { + http.Error(w, "Not acceptable", http.StatusNotAcceptable) + return + } + indexName := mux.Vars(r)["index"] frameName := mux.Vars(r)["frame"] - // Decode request. - var req postFrameAttrDiffRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + // Read entire body. + body, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // Marshal into request object. + var req internal.AttrBlockRequest + if err := proto.Unmarshal(body, &req); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -982,7 +1011,7 @@ func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request // Read all attributes from all mismatched blocks. attrs := make(map[uint64]map[string]interface{}) - for _, blockID := range AttrBlocks(blks).Diff(req.Blocks) { + for _, blockID := range AttrBlocks(blks).Diff(decodeAttrBlocks(req.Blocks)) { // Retrieve block data. m, err := f.RowAttrStore().BlockData(blockID) if err != nil { @@ -996,20 +1025,17 @@ func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request } } - // Encode response. - if err := json.NewEncoder(w).Encode(postFrameAttrDiffResponse{ - Attrs: attrs, - }); err != nil { - h.logger().Printf("response encoding error: %s", err) + // Marshal response object. + buf, err := proto.Marshal(&internal.AttrBlockResponse{ + Attrs: encodeAttrsMap(attrs), + }) + + // Write response. + if err != nil { + h.logger().Printf("row attr response encoding error: %s", err) + w.WriteHeader(http.StatusInternalServerError) } -} - -type postFrameAttrDiffRequest struct { - Blocks []AttrBlock `json:"blocks"` -} - -type postFrameAttrDiffResponse struct { - Attrs map[uint64]map[string]interface{} `json:"attrs"` + w.Write(buf) } // readColumnAttrSets returns a list of column attribute objects by id. diff --git a/handler_test.go b/handler_test.go index 796782402..469a87c70 100644 --- a/handler_test.go +++ b/handler_test.go @@ -24,6 +24,7 @@ import ( "net/http" "net/http/httptest" "reflect" + "strconv" "strings" "testing" @@ -793,20 +794,53 @@ func TestHandler_Index_AttrStore_Diff(t *testing.T) { blks = blks[1:] blks[1].Checksum = []byte("MISMATCHED_CHECKSUM") + // Encode request object. + buf, err := proto.Marshal(&internal.AttrBlockRequest{ + Blocks: pilosa.EncodeAttrBlocks(blks), + }) + if err != nil { + t.Fatal(err) + } + // Send block checksums to determine diff. - resp, err := http.Post( + client := &http.Client{} + req, err := http.NewRequest( + "POST", s.URL+"/index/i/attr/diff", - "application/json", - strings.NewReader(`{"blocks":`+string(test.MustMarshalJSON(blks))+`}`), + bytes.NewReader(buf), ) if err != nil { t.Fatal(err) } + req.Header.Set("Content-Length", strconv.Itoa(len(buf))) + req.Header.Set("Content-Type", "application/x-protobuf") + req.Header.Set("Accept", "application/x-protobuf") + resp, err := client.Do(req) + if err != nil { + t.Fatal(err) + } defer resp.Body.Close() - // Read and validate body. - if body := string(test.MustReadAll(resp.Body)); body != `{"attrs":{"1":{"bar":2,"foo":1},"200":{"snowman":"☃"}}}`+"\n" { - t.Fatalf("unexpected body: %s", body) + // Read body. + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + // Decode response object. + abresp := &internal.AttrBlockResponse{} + if err := proto.Unmarshal(body, abresp); err != nil { + t.Fatal(err) + } + + rec := pilosa.DecodeAttrsMap(abresp.Attrs) + + exp := make(map[uint64]map[string]interface{}) + exp[1] = map[string]interface{}{"bar": int64(2), "foo": int64(1)} + exp[200] = map[string]interface{}{"snowman": "☃"} + + if !reflect.DeepEqual(rec, exp) { + t.Fatalf("\nexpected: %s\n\ngot: %s\n", exp, rec) } } @@ -843,20 +877,53 @@ func TestHandler_Frame_AttrStore_Diff(t *testing.T) { blks = blks[1:] blks[1].Checksum = []byte("MISMATCHED_CHECKSUM") + // Encode request object. + buf, err := proto.Marshal(&internal.AttrBlockRequest{ + Blocks: pilosa.EncodeAttrBlocks(blks), + }) + if err != nil { + t.Fatal(err) + } + // Send block checksums to determine diff. - resp, err := http.Post( + client := &http.Client{} + req, err := http.NewRequest( + "POST", s.URL+"/index/i/frame/meta/attr/diff", - "application/json", - strings.NewReader(`{"blocks":`+string(test.MustMarshalJSON(blks))+`}`), + bytes.NewReader(buf), ) if err != nil { t.Fatal(err) } + req.Header.Set("Content-Length", strconv.Itoa(len(buf))) + req.Header.Set("Content-Type", "application/x-protobuf") + req.Header.Set("Accept", "application/x-protobuf") + resp, err := client.Do(req) + if err != nil { + t.Fatal(err) + } defer resp.Body.Close() - // Read and validate body. - if body := string(test.MustReadAll(resp.Body)); body != `{"attrs":{"1":{"bar":2,"foo":1},"200":{"snowman":"☃"}}}`+"\n" { - t.Fatalf("unexpected body: %s", body) + // Read body. + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + // Decode response object. + abresp := &internal.AttrBlockResponse{} + if err := proto.Unmarshal(body, abresp); err != nil { + t.Fatal(err) + } + + rec := pilosa.DecodeAttrsMap(abresp.Attrs) + + exp := make(map[uint64]map[string]interface{}) + exp[1] = map[string]interface{}{"bar": int64(2), "foo": int64(1)} + exp[200] = map[string]interface{}{"snowman": "☃"} + + if !reflect.DeepEqual(rec, exp) { + t.Fatalf("\nexpected: %s\n\ngot: %s\n", exp, rec) } } diff --git a/internal/private.pb.go b/internal/private.pb.go index e5cc6516f..ce4a1838b 100644 --- a/internal/private.pb.go +++ b/internal/private.pb.go @@ -32,6 +32,8 @@ FrameSchema Field DeleteViewMessage + AttrBlock + AttrBlockRequest */ package internal @@ -768,6 +770,47 @@ func (m *DeleteViewMessage) GetView() string { return "" } +// AttrBlock represents a checksummed block of the attribute store. +type AttrBlock struct { + ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Checksum []byte `protobuf:"bytes,2,opt,name=Checksum,proto3" json:"Checksum,omitempty"` +} + +func (m *AttrBlock) Reset() { *m = AttrBlock{} } +func (m *AttrBlock) String() string { return proto.CompactTextString(m) } +func (*AttrBlock) ProtoMessage() {} +func (*AttrBlock) Descriptor() ([]byte, []int) { return fileDescriptorPrivate, []int{24} } + +func (m *AttrBlock) GetID() uint64 { + if m != nil { + return m.ID + } + return 0 +} + +func (m *AttrBlock) GetChecksum() []byte { + if m != nil { + return m.Checksum + } + return nil +} + +type AttrBlockRequest struct { + Blocks []*AttrBlock `protobuf:"bytes,1,rep,name=Blocks" json:"Blocks,omitempty"` +} + +func (m *AttrBlockRequest) Reset() { *m = AttrBlockRequest{} } +func (m *AttrBlockRequest) String() string { return proto.CompactTextString(m) } +func (*AttrBlockRequest) ProtoMessage() {} +func (*AttrBlockRequest) Descriptor() ([]byte, []int) { return fileDescriptorPrivate, []int{25} } + +func (m *AttrBlockRequest) GetBlocks() []*AttrBlock { + if m != nil { + return m.Blocks + } + return nil +} + func init() { proto.RegisterType((*IndexMeta)(nil), "internal.IndexMeta") proto.RegisterType((*FrameMeta)(nil), "internal.FrameMeta") @@ -793,6 +836,8 @@ func init() { proto.RegisterType((*FrameSchema)(nil), "internal.FrameSchema") proto.RegisterType((*Field)(nil), "internal.Field") proto.RegisterType((*DeleteViewMessage)(nil), "internal.DeleteViewMessage") + proto.RegisterType((*AttrBlock)(nil), "internal.AttrBlock") + proto.RegisterType((*AttrBlockRequest)(nil), "internal.AttrBlockRequest") } func (m *IndexMeta) Marshal() (dAtA []byte, err error) { size := m.Size() @@ -1762,6 +1807,65 @@ func (m *DeleteViewMessage) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *AttrBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AttrBlock) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.ID != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintPrivate(dAtA, i, uint64(m.ID)) + } + if len(m.Checksum) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintPrivate(dAtA, i, uint64(len(m.Checksum))) + i += copy(dAtA[i:], m.Checksum) + } + return i, nil +} + +func (m *AttrBlockRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AttrBlockRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Blocks) > 0 { + for _, msg := range m.Blocks { + dAtA[i] = 0xa + i++ + i = encodeVarintPrivate(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + func encodeVarintPrivate(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -2201,6 +2305,31 @@ func (m *DeleteViewMessage) Size() (n int) { return n } +func (m *AttrBlock) Size() (n int) { + var l int + _ = l + if m.ID != 0 { + n += 1 + sovPrivate(uint64(m.ID)) + } + l = len(m.Checksum) + if l > 0 { + n += 1 + l + sovPrivate(uint64(l)) + } + return n +} + +func (m *AttrBlockRequest) Size() (n int) { + var l int + _ = l + if len(m.Blocks) > 0 { + for _, e := range m.Blocks { + l = e.Size() + n += 1 + l + sovPrivate(uint64(l)) + } + } + return n +} + func sovPrivate(x uint64) (n int) { for { n++ @@ -5509,6 +5638,187 @@ func (m *DeleteViewMessage) Unmarshal(dAtA []byte) error { } return nil } +func (m *AttrBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPrivate + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AttrBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AttrBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPrivate + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ID |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Checksum", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPrivate + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPrivate + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Checksum = append(m.Checksum[:0], dAtA[iNdEx:postIndex]...) + if m.Checksum == nil { + m.Checksum = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPrivate(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPrivate + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AttrBlockRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPrivate + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AttrBlockRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AttrBlockRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blocks", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPrivate + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPrivate + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Blocks = append(m.Blocks, &AttrBlock{}) + if err := m.Blocks[len(m.Blocks)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPrivate(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPrivate + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipPrivate(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 @@ -5617,65 +5927,68 @@ var ( func init() { proto.RegisterFile("private.proto", fileDescriptorPrivate) } var fileDescriptorPrivate = []byte{ - // 948 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xc1, 0x6e, 0x23, 0x45, - 0x10, 0x65, 0x3c, 0x63, 0xaf, 0x5d, 0x26, 0x1b, 0xa7, 0x09, 0x2b, 0x6f, 0x14, 0x19, 0xab, 0x0f, - 0x6c, 0x88, 0x44, 0x0e, 0x41, 0x5a, 0x01, 0xcb, 0x01, 0x36, 0xce, 0x2a, 0x16, 0x78, 0x81, 0xf6, - 0x6a, 0xb9, 0x21, 0x75, 0x9c, 0x62, 0x77, 0x94, 0xf1, 0x8c, 0x99, 0x69, 0x27, 0x31, 0x07, 0x8e, - 0x7c, 0x03, 0x12, 0x47, 0x7e, 0x86, 0x23, 0x9f, 0x80, 0xc2, 0x85, 0x3f, 0x40, 0xe2, 0x84, 0xba, - 0xba, 0x7b, 0x66, 0x6c, 0xc7, 0x8e, 0xb2, 0xb7, 0xae, 0x57, 0xd5, 0x55, 0xaf, 0xab, 0xab, 0xaa, - 0x1b, 0x36, 0x26, 0x69, 0x78, 0x21, 0x15, 0x1e, 0x4c, 0xd2, 0x44, 0x25, 0xac, 0x1e, 0xc6, 0x0a, - 0xd3, 0x58, 0x46, 0xfc, 0x6b, 0x68, 0xf4, 0xe3, 0x33, 0xbc, 0x1a, 0xa0, 0x92, 0xac, 0x0b, 0xcd, - 0xa3, 0x24, 0x9a, 0x8e, 0xe3, 0xaf, 0xe4, 0x29, 0x46, 0x6d, 0xaf, 0xeb, 0xed, 0x35, 0x44, 0x19, - 0xd2, 0x16, 0x2f, 0xc2, 0x31, 0x7e, 0x3b, 0x95, 0xb1, 0x9a, 0x8e, 0xdb, 0x15, 0x63, 0x51, 0x82, - 0xf8, 0x7f, 0x1e, 0x34, 0x9e, 0xa5, 0x72, 0x8c, 0xe4, 0x71, 0x07, 0xea, 0x22, 0xb9, 0x2c, 0xbb, - 0xcb, 0x65, 0xf6, 0x3e, 0xdc, 0xef, 0xc7, 0x17, 0x98, 0x66, 0x78, 0x1c, 0xcb, 0xd3, 0x08, 0xcf, - 0xc8, 0x5d, 0x5d, 0x2c, 0xa0, 0x6c, 0x17, 0x1a, 0x47, 0x72, 0xf4, 0x1a, 0x5f, 0xcc, 0x26, 0xd8, - 0xf6, 0xc9, 0x49, 0x01, 0xe4, 0xda, 0x61, 0xf8, 0x13, 0xb6, 0x83, 0xae, 0xb7, 0xb7, 0x21, 0x0a, - 0x60, 0x91, 0x6f, 0x75, 0x89, 0x2f, 0xe3, 0xf0, 0xb6, 0x90, 0xf1, 0xab, 0x9c, 0x43, 0x8d, 0x38, - 0xcc, 0x61, 0xec, 0x11, 0xd4, 0x9e, 0x85, 0x18, 0x9d, 0x65, 0xed, 0x7b, 0x5d, 0x7f, 0xaf, 0x79, - 0xb8, 0x79, 0xe0, 0xf2, 0x77, 0x40, 0xb8, 0xb0, 0x6a, 0xce, 0xe1, 0x7e, 0x7f, 0x3c, 0x49, 0x52, - 0x25, 0x30, 0x9b, 0x24, 0x71, 0x86, 0xac, 0x05, 0xfe, 0x71, 0x9a, 0xda, 0xb3, 0xeb, 0x25, 0xff, - 0x19, 0x5a, 0x4f, 0xa3, 0x64, 0x74, 0xde, 0x93, 0x4a, 0x0a, 0xfc, 0x71, 0x8a, 0x99, 0x62, 0xdb, - 0x50, 0xa5, 0x5b, 0xb0, 0x76, 0x46, 0xd0, 0x28, 0x65, 0xd2, 0xa6, 0xd9, 0x08, 0x1a, 0xa5, 0xfd, - 0x94, 0x8a, 0x40, 0x18, 0x41, 0xa3, 0xc3, 0x28, 0x1c, 0x99, 0x14, 0x04, 0xc2, 0x08, 0x8c, 0x41, - 0xf0, 0x32, 0xc4, 0x4b, 0x7b, 0x6e, 0x5a, 0xf3, 0x3e, 0x6c, 0x95, 0xe2, 0x5b, 0x9a, 0x0f, 0xa0, - 0x26, 0x92, 0xcb, 0x7e, 0x2f, 0x6b, 0x7b, 0x5d, 0x7f, 0x2f, 0x10, 0x56, 0xa2, 0xec, 0xd2, 0xf5, - 0x6b, 0x55, 0x85, 0x54, 0x05, 0xc0, 0x1f, 0x42, 0x95, 0x52, 0xad, 0x4f, 0x59, 0xec, 0xd5, 0x4b, - 0xfe, 0x9b, 0x07, 0x5b, 0x03, 0x79, 0x45, 0x34, 0xb2, 0x3c, 0xcc, 0x09, 0x34, 0x72, 0x90, 0xac, - 0x9b, 0x87, 0xfb, 0x45, 0x2e, 0x97, 0xec, 0x0b, 0xe4, 0x38, 0x56, 0xe9, 0x4c, 0x14, 0x9b, 0x77, - 0x3e, 0x83, 0xfb, 0xf3, 0x4a, 0xcd, 0xe1, 0x1c, 0x67, 0x2e, 0xd3, 0xe7, 0x38, 0xd3, 0x39, 0xb9, - 0x90, 0xd1, 0xd4, 0xe4, 0x2f, 0x10, 0x46, 0xf8, 0xb4, 0xf2, 0xb1, 0xc7, 0xbf, 0x07, 0x76, 0x94, - 0xa2, 0x54, 0x48, 0x0e, 0x06, 0x98, 0x65, 0xf2, 0x15, 0xae, 0xbe, 0x05, 0x93, 0xd9, 0x4a, 0x39, - 0xb3, 0xbb, 0xd0, 0xe8, 0x67, 0xb6, 0x50, 0xe9, 0x26, 0xea, 0xa2, 0x00, 0xf8, 0x3e, 0xb0, 0x1e, - 0x46, 0xa8, 0xd0, 0xf6, 0xd6, 0x1a, 0xff, 0x7c, 0xe8, 0xb8, 0xdc, 0x6e, 0xcb, 0x1e, 0x41, 0xa0, - 0xdb, 0x8a, 0xa8, 0x34, 0x0f, 0xdf, 0x29, 0x52, 0x97, 0xf7, 0xb0, 0x20, 0x03, 0x1e, 0x3a, 0xa7, - 0xb6, 0x15, 0x6f, 0x39, 0xe0, 0x0d, 0x65, 0xe6, 0x42, 0xf9, 0x8b, 0xa1, 0xf2, 0xe6, 0xb6, 0xa1, - 0x3e, 0x77, 0x67, 0x7d, 0xd3, 0x50, 0xbc, 0x67, 0x51, 0x5d, 0xae, 0xcf, 0xb5, 0xd6, 0xec, 0xa1, - 0xf5, 0xea, 0x23, 0x2f, 0xf2, 0xf8, 0xc7, 0xb3, 0x21, 0xef, 0xe6, 0x66, 0x21, 0x73, 0x7a, 0x62, - 0xb9, 0xc2, 0xb2, 0x1d, 0x96, 0xcb, 0x34, 0x07, 0x74, 0xd4, 0xac, 0x1d, 0x2c, 0xcd, 0x01, 0x8d, - 0x0b, 0xab, 0xd6, 0xed, 0x64, 0x8b, 0xbc, 0x6a, 0xda, 0xc9, 0x48, 0xec, 0x18, 0x5a, 0xfd, 0x78, - 0x32, 0x55, 0x3d, 0xfc, 0x21, 0x8c, 0x43, 0x15, 0x26, 0x71, 0xd6, 0xae, 0x91, 0xab, 0x87, 0x65, - 0x46, 0x73, 0x16, 0x62, 0x69, 0x0b, 0xff, 0xc5, 0x83, 0xcd, 0x05, 0x70, 0xc5, 0xa1, 0x1d, 0xdf, - 0xca, 0x7a, 0xbe, 0x8f, 0xf3, 0x01, 0xe7, 0x93, 0x61, 0x67, 0x25, 0x9b, 0xf9, 0x79, 0xf7, 0xbb, - 0x07, 0xdb, 0x37, 0x19, 0xdc, 0xc8, 0xa6, 0x03, 0xf0, 0x4d, 0x1a, 0x8e, 0x65, 0x3a, 0xfb, 0x12, - 0x67, 0x76, 0xd6, 0x97, 0x10, 0xf6, 0x1d, 0x3c, 0x58, 0xf0, 0xf5, 0xc5, 0xc8, 0xa4, 0xc8, 0x90, - 0x7a, 0x6f, 0x25, 0x29, 0x63, 0x27, 0x56, 0x6c, 0xe7, 0xff, 0x7a, 0xf0, 0xee, 0x8d, 0xaa, 0xa2, - 0x1e, 0xbd, 0x72, 0xe9, 0xef, 0x43, 0xeb, 0xa5, 0x1e, 0x15, 0x3d, 0xcc, 0x54, 0x18, 0x4b, 0x6d, - 0x69, 0x0b, 0x76, 0x09, 0x67, 0x7d, 0xa8, 0x13, 0x36, 0x90, 0x13, 0x4b, 0xf3, 0xc3, 0x5b, 0x68, - 0x1e, 0x38, 0x7b, 0x33, 0xd3, 0xf2, 0xed, 0x9a, 0x0c, 0x4d, 0x5d, 0x37, 0xc2, 0x49, 0xd8, 0x79, - 0x02, 0x1b, 0x73, 0x1b, 0xee, 0x34, 0xe7, 0x12, 0xd8, 0x75, 0xb3, 0x65, 0x8e, 0xc9, 0xfa, 0x2e, - 0xfd, 0x04, 0xa0, 0x30, 0xb5, 0x03, 0x60, 0x4d, 0x7d, 0x96, 0x8c, 0xf9, 0x09, 0xec, 0xba, 0xc1, - 0x77, 0x87, 0x80, 0xae, 0x5a, 0x2a, 0x45, 0xb5, 0xf0, 0x19, 0xc0, 0xf3, 0xe4, 0x0c, 0x87, 0x4a, - 0xaa, 0x69, 0xa6, 0x2d, 0x4e, 0x92, 0x4c, 0xb9, 0x7a, 0xd2, 0x6b, 0x1a, 0xcc, 0x4a, 0xaa, 0x7c, - 0x98, 0x90, 0xc0, 0x3e, 0x80, 0x7b, 0xe4, 0x14, 0x5d, 0xd9, 0x6c, 0x2e, 0xf4, 0xba, 0x70, 0x7a, - 0xea, 0xd2, 0xd1, 0x6b, 0x1c, 0x9b, 0x47, 0xb3, 0x21, 0xac, 0xc4, 0x9f, 0xc0, 0xc6, 0x51, 0x34, - 0xcd, 0x14, 0xa6, 0x36, 0xfa, 0x3e, 0x54, 0x35, 0x17, 0xf7, 0x64, 0x6d, 0x17, 0x1e, 0x0b, 0x8a, - 0xc2, 0x98, 0xf0, 0xc7, 0xd0, 0xa4, 0x2a, 0x22, 0x5f, 0xb2, 0xf4, 0x75, 0xf0, 0xd6, 0x7f, 0x1d, - 0x86, 0x50, 0x5d, 0xdd, 0x3a, 0x0c, 0x02, 0xfa, 0xfd, 0xd8, 0x04, 0xd1, 0xc7, 0xa7, 0x05, 0xfe, - 0x20, 0x34, 0xd7, 0xe3, 0x0b, 0xbd, 0x24, 0x44, 0x5e, 0xd1, 0x61, 0x34, 0x22, 0xf5, 0xdb, 0xb2, - 0x65, 0xae, 0x43, 0xbf, 0xfc, 0x6f, 0xf2, 0x0a, 0xb8, 0x0f, 0x84, 0x5f, 0x7c, 0x20, 0x9e, 0xb6, - 0xfe, 0xb8, 0xee, 0x78, 0x7f, 0x5e, 0x77, 0xbc, 0xbf, 0xae, 0x3b, 0xde, 0xaf, 0x7f, 0x77, 0xde, - 0x3a, 0xad, 0xd1, 0xaf, 0xf2, 0xa3, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x47, 0xdd, 0xdd, 0x8e, - 0x66, 0x0a, 0x00, 0x00, + // 999 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcd, 0x6e, 0x23, 0x45, + 0x10, 0x66, 0xec, 0xb1, 0xd7, 0x2e, 0x6f, 0x12, 0x67, 0x08, 0x2b, 0x6f, 0x14, 0x19, 0xab, 0x0f, + 0x6c, 0x08, 0x22, 0x87, 0x20, 0x2d, 0x3f, 0x8b, 0x04, 0xbb, 0x76, 0x56, 0x19, 0x81, 0x17, 0x68, + 0xaf, 0x96, 0x1b, 0x52, 0xc7, 0x29, 0x36, 0xa3, 0x8c, 0x67, 0xcc, 0x4c, 0x3b, 0x89, 0x39, 0x70, + 0xe4, 0x19, 0x90, 0x38, 0xf2, 0x32, 0x1c, 0x79, 0x04, 0x14, 0x2e, 0xbc, 0x01, 0x12, 0xa7, 0x55, + 0x57, 0x77, 0xcf, 0x8c, 0xed, 0xd8, 0x51, 0x72, 0xeb, 0xfa, 0xba, 0xba, 0xea, 0xeb, 0xea, 0xaa, + 0xea, 0x82, 0xb5, 0x71, 0x12, 0x9c, 0x0b, 0x89, 0xfb, 0xe3, 0x24, 0x96, 0xb1, 0x57, 0x0b, 0x22, + 0x89, 0x49, 0x24, 0x42, 0xf6, 0x0d, 0xd4, 0xfd, 0xe8, 0x04, 0x2f, 0xfb, 0x28, 0x85, 0xd7, 0x81, + 0x46, 0x37, 0x0e, 0x27, 0xa3, 0xe8, 0x6b, 0x71, 0x8c, 0x61, 0xcb, 0xe9, 0x38, 0xbb, 0x75, 0x5e, + 0x84, 0x94, 0xc6, 0xcb, 0x60, 0x84, 0xdf, 0x4d, 0x44, 0x24, 0x27, 0xa3, 0x56, 0x49, 0x6b, 0x14, + 0x20, 0xf6, 0xbf, 0x03, 0xf5, 0xe7, 0x89, 0x18, 0x21, 0x59, 0xdc, 0x86, 0x1a, 0x8f, 0x2f, 0x8a, + 0xe6, 0x32, 0xd9, 0x7b, 0x0f, 0xd6, 0xfd, 0xe8, 0x1c, 0x93, 0x14, 0x0f, 0x23, 0x71, 0x1c, 0xe2, + 0x09, 0x99, 0xab, 0xf1, 0x39, 0xd4, 0xdb, 0x81, 0x7a, 0x57, 0x0c, 0x4f, 0xf1, 0xe5, 0x74, 0x8c, + 0xad, 0x32, 0x19, 0xc9, 0x81, 0x6c, 0x77, 0x10, 0xfc, 0x8c, 0x2d, 0xb7, 0xe3, 0xec, 0xae, 0xf1, + 0x1c, 0x98, 0xe7, 0x5b, 0x59, 0xe0, 0xeb, 0x31, 0xb8, 0xcf, 0x45, 0xf4, 0x3a, 0xe3, 0x50, 0x25, + 0x0e, 0x33, 0x98, 0xf7, 0x08, 0xaa, 0xcf, 0x03, 0x0c, 0x4f, 0xd2, 0xd6, 0xbd, 0x4e, 0x79, 0xb7, + 0x71, 0xb0, 0xb1, 0x6f, 0xe3, 0xb7, 0x4f, 0x38, 0x37, 0xdb, 0x8c, 0xc1, 0xba, 0x3f, 0x1a, 0xc7, + 0x89, 0xe4, 0x98, 0x8e, 0xe3, 0x28, 0x45, 0xaf, 0x09, 0xe5, 0xc3, 0x24, 0x31, 0x77, 0x57, 0x4b, + 0xf6, 0x0b, 0x34, 0x9f, 0x85, 0xf1, 0xf0, 0xac, 0x27, 0xa4, 0xe0, 0xf8, 0xd3, 0x04, 0x53, 0xe9, + 0x6d, 0x41, 0x85, 0x5e, 0xc1, 0xe8, 0x69, 0x41, 0xa1, 0x14, 0x49, 0x13, 0x66, 0x2d, 0x28, 0x94, + 0xce, 0x53, 0x28, 0x5c, 0xae, 0x05, 0x85, 0x0e, 0xc2, 0x60, 0xa8, 0x43, 0xe0, 0x72, 0x2d, 0x78, + 0x1e, 0xb8, 0xaf, 0x02, 0xbc, 0x30, 0xf7, 0xa6, 0x35, 0xf3, 0x61, 0xb3, 0xe0, 0xdf, 0xd0, 0x7c, + 0x00, 0x55, 0x1e, 0x5f, 0xf8, 0xbd, 0xb4, 0xe5, 0x74, 0xca, 0xbb, 0x2e, 0x37, 0x12, 0x45, 0x97, + 0x9e, 0x5f, 0x6d, 0x95, 0x68, 0x2b, 0x07, 0xd8, 0x43, 0xa8, 0x50, 0xa8, 0xd5, 0x2d, 0xf3, 0xb3, + 0x6a, 0xc9, 0x7e, 0x77, 0x60, 0xb3, 0x2f, 0x2e, 0x89, 0x46, 0x9a, 0xb9, 0x39, 0x82, 0x7a, 0x06, + 0x92, 0x76, 0xe3, 0x60, 0x2f, 0x8f, 0xe5, 0x82, 0x7e, 0x8e, 0x1c, 0x46, 0x32, 0x99, 0xf2, 0xfc, + 0xf0, 0xf6, 0xe7, 0xb0, 0x3e, 0xbb, 0xa9, 0x38, 0x9c, 0xe1, 0xd4, 0x46, 0xfa, 0x0c, 0xa7, 0x2a, + 0x26, 0xe7, 0x22, 0x9c, 0xe8, 0xf8, 0xb9, 0x5c, 0x0b, 0x9f, 0x95, 0x3e, 0x71, 0xd8, 0x0f, 0xe0, + 0x75, 0x13, 0x14, 0x12, 0xc9, 0x40, 0x1f, 0xd3, 0x54, 0xbc, 0xc6, 0xe5, 0xaf, 0xa0, 0x23, 0x5b, + 0x2a, 0x46, 0x76, 0x07, 0xea, 0x7e, 0x6a, 0x12, 0x95, 0x5e, 0xa2, 0xc6, 0x73, 0x80, 0xed, 0x81, + 0xd7, 0xc3, 0x10, 0x25, 0x9a, 0xda, 0x5a, 0x61, 0x9f, 0x0d, 0x2c, 0x97, 0x9b, 0x75, 0xbd, 0x47, + 0xe0, 0xaa, 0xb2, 0x22, 0x2a, 0x8d, 0x83, 0xb7, 0xf3, 0xd0, 0x65, 0x35, 0xcc, 0x49, 0x81, 0x05, + 0xd6, 0xa8, 0x29, 0xc5, 0x1b, 0x2e, 0x78, 0x4d, 0x9a, 0x59, 0x57, 0xe5, 0x79, 0x57, 0x59, 0x71, + 0x1b, 0x57, 0x5f, 0xda, 0xbb, 0xde, 0xd5, 0x15, 0xeb, 0x19, 0x54, 0xa5, 0xeb, 0x0b, 0xb5, 0xab, + 0xcf, 0xd0, 0x7a, 0xf9, 0x95, 0xe7, 0x79, 0xfc, 0xeb, 0x18, 0x97, 0xb7, 0x33, 0x33, 0x17, 0x39, + 0xd5, 0xb1, 0x6c, 0x62, 0x99, 0x0a, 0xcb, 0x64, 0xea, 0x03, 0xca, 0x6b, 0xda, 0x72, 0x17, 0xfa, + 0x80, 0xc2, 0xb9, 0xd9, 0x56, 0xe5, 0x64, 0x92, 0xbc, 0xa2, 0xcb, 0x49, 0x4b, 0xde, 0x21, 0x34, + 0xfd, 0x68, 0x3c, 0x91, 0x3d, 0xfc, 0x31, 0x88, 0x02, 0x19, 0xc4, 0x51, 0xda, 0xaa, 0x92, 0xa9, + 0x87, 0x45, 0x46, 0x33, 0x1a, 0x7c, 0xe1, 0x08, 0xfb, 0xd5, 0x81, 0x8d, 0x39, 0x70, 0xc9, 0xa5, + 0x2d, 0xdf, 0xd2, 0x6a, 0xbe, 0x8f, 0xb3, 0x06, 0x57, 0x26, 0xc5, 0xf6, 0x52, 0x36, 0xb3, 0xfd, + 0xee, 0x0f, 0x07, 0xb6, 0xae, 0x53, 0xb8, 0x96, 0x4d, 0x1b, 0xe0, 0xdb, 0x24, 0x18, 0x89, 0x64, + 0xfa, 0x15, 0x4e, 0x4d, 0xaf, 0x2f, 0x20, 0xde, 0xf7, 0xf0, 0x60, 0xce, 0xd6, 0xd3, 0xa1, 0x0e, + 0x91, 0x26, 0xf5, 0xee, 0x52, 0x52, 0x5a, 0x8f, 0x2f, 0x39, 0xce, 0xfe, 0x73, 0xe0, 0x9d, 0x6b, + 0xb7, 0xf2, 0x7c, 0x74, 0x8a, 0xa9, 0xbf, 0x07, 0xcd, 0x57, 0xaa, 0x55, 0xf4, 0x30, 0x95, 0x41, + 0x24, 0x94, 0xa6, 0x49, 0xd8, 0x05, 0xdc, 0xf3, 0xa1, 0x46, 0x58, 0x5f, 0x8c, 0x0d, 0xcd, 0x0f, + 0x6f, 0xa0, 0xb9, 0x6f, 0xf5, 0x75, 0x4f, 0xcb, 0x8e, 0x2b, 0x32, 0xd4, 0x75, 0x6d, 0x0b, 0x27, + 0x61, 0xfb, 0x09, 0xac, 0xcd, 0x1c, 0xb8, 0x55, 0x9f, 0x8b, 0x61, 0xc7, 0xf6, 0x96, 0x19, 0x26, + 0xab, 0xab, 0xf4, 0x53, 0x80, 0x5c, 0xd5, 0x34, 0x80, 0x15, 0xf9, 0x59, 0x50, 0x66, 0x47, 0xb0, + 0x63, 0x1b, 0xdf, 0x2d, 0x1c, 0xda, 0x6c, 0x29, 0xe5, 0xd9, 0xc2, 0xa6, 0x00, 0x2f, 0xe2, 0x13, + 0x1c, 0x48, 0x21, 0x27, 0xa9, 0xd2, 0x38, 0x8a, 0x53, 0x69, 0xf3, 0x49, 0xad, 0xa9, 0x31, 0x4b, + 0x21, 0xb3, 0x66, 0x42, 0x82, 0xf7, 0x3e, 0xdc, 0x23, 0xa3, 0x68, 0xd3, 0x66, 0x63, 0xae, 0xd6, + 0xb9, 0xdd, 0xa7, 0x2a, 0x1d, 0x9e, 0xe2, 0x48, 0x7f, 0x9a, 0x75, 0x6e, 0x24, 0xf6, 0x04, 0xd6, + 0xba, 0xe1, 0x24, 0x95, 0x98, 0x18, 0xef, 0x7b, 0x50, 0x51, 0x5c, 0xec, 0x97, 0xb5, 0x95, 0x5b, + 0xcc, 0x29, 0x72, 0xad, 0xc2, 0x1e, 0x43, 0x83, 0xb2, 0x88, 0x6c, 0x89, 0xc2, 0xe8, 0xe0, 0xac, + 0x1e, 0x1d, 0x06, 0x50, 0x59, 0x5e, 0x3a, 0x1e, 0xb8, 0x34, 0xfd, 0x98, 0x00, 0xd1, 0xe0, 0xd3, + 0x84, 0x72, 0x3f, 0xd0, 0xcf, 0x53, 0xe6, 0x6a, 0x49, 0x88, 0xb8, 0xa4, 0xcb, 0x28, 0x44, 0xa8, + 0xbf, 0x65, 0x53, 0x3f, 0x87, 0xfa, 0xf9, 0xef, 0xf2, 0x0b, 0xd8, 0x01, 0xa2, 0x5c, 0x18, 0x20, + 0x3e, 0x86, 0xfa, 0x53, 0x29, 0x13, 0x3d, 0x77, 0xac, 0x43, 0xc9, 0xef, 0x91, 0x25, 0x97, 0x97, + 0xfc, 0x9e, 0x6a, 0x9f, 0xdd, 0x53, 0x1c, 0x9e, 0xa5, 0x66, 0x3a, 0xbc, 0xcf, 0x33, 0x99, 0x7d, + 0x01, 0xcd, 0xec, 0xa0, 0x9d, 0x7c, 0x3e, 0x80, 0x2a, 0xc9, 0x36, 0x3e, 0x85, 0xce, 0x9c, 0xeb, + 0x1a, 0x95, 0x67, 0xcd, 0x3f, 0xaf, 0xda, 0xce, 0x5f, 0x57, 0x6d, 0xe7, 0xef, 0xab, 0xb6, 0xf3, + 0xdb, 0x3f, 0xed, 0xb7, 0x8e, 0xab, 0x34, 0xcf, 0x7e, 0xf4, 0x26, 0x00, 0x00, 0xff, 0xff, 0x13, + 0x56, 0xc4, 0x2f, 0xe0, 0x0a, 0x00, 0x00, } diff --git a/internal/private.proto b/internal/private.proto index 083316ddd..c70f90f9f 100644 --- a/internal/private.proto +++ b/internal/private.proto @@ -139,3 +139,13 @@ message DeleteViewMessage { string Frame = 2; string View = 3; } + +// AttrBlock represents a checksummed block of the attribute store. +message AttrBlock { + uint64 ID = 1; + bytes Checksum = 2; +} + +message AttrBlockRequest { + repeated AttrBlock Blocks = 1; +} diff --git a/internal/public.pb.go b/internal/public.pb.go index 2b39cf4fb..30178f993 100644 --- a/internal/public.pb.go +++ b/internal/public.pb.go @@ -20,6 +20,7 @@ QueryResult ImportRequest ImportValueRequest + AttrBlockResponse */ package internal @@ -490,6 +491,22 @@ func (m *ImportValueRequest) GetValues() []int64 { return nil } +type AttrBlockResponse struct { + Attrs map[uint64]*AttrMap `protobuf:"bytes,1,rep,name=Attrs" json:"Attrs,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *AttrBlockResponse) Reset() { *m = AttrBlockResponse{} } +func (m *AttrBlockResponse) String() string { return proto.CompactTextString(m) } +func (*AttrBlockResponse) ProtoMessage() {} +func (*AttrBlockResponse) Descriptor() ([]byte, []int) { return fileDescriptorPublic, []int{12} } + +func (m *AttrBlockResponse) GetAttrs() map[uint64]*AttrMap { + if m != nil { + return m.Attrs + } + return nil +} + func init() { proto.RegisterType((*Bitmap)(nil), "internal.Bitmap") proto.RegisterType((*Pair)(nil), "internal.Pair") @@ -503,6 +520,7 @@ func init() { proto.RegisterType((*QueryResult)(nil), "internal.QueryResult") proto.RegisterType((*ImportRequest)(nil), "internal.ImportRequest") proto.RegisterType((*ImportValueRequest)(nil), "internal.ImportValueRequest") + proto.RegisterType((*AttrBlockResponse)(nil), "internal.AttrBlockResponse") } func (m *Bitmap) Marshal() (dAtA []byte, err error) { size := m.Size() @@ -1118,6 +1136,51 @@ func (m *ImportValueRequest) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *AttrBlockResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AttrBlockResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Attrs) > 0 { + for k, _ := range m.Attrs { + dAtA[i] = 0xa + i++ + v := m.Attrs[k] + msgSize := 0 + if v != nil { + msgSize = v.Size() + msgSize += 1 + sovPublic(uint64(msgSize)) + } + mapSize := 1 + sovPublic(uint64(k)) + msgSize + i = encodeVarintPublic(dAtA, i, uint64(mapSize)) + dAtA[i] = 0x8 + i++ + i = encodeVarintPublic(dAtA, i, uint64(k)) + if v != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintPublic(dAtA, i, uint64(v.Size())) + n17, err := v.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n17 + } + } + } + return i, nil +} + func encodeVarintPublic(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -1388,6 +1451,25 @@ func (m *ImportValueRequest) Size() (n int) { return n } +func (m *AttrBlockResponse) Size() (n int) { + var l int + _ = l + if len(m.Attrs) > 0 { + for k, v := range m.Attrs { + _ = k + _ = v + l = 0 + if v != nil { + l = v.Size() + l += 1 + sovPublic(uint64(l)) + } + mapEntrySize := 1 + sovPublic(uint64(k)) + l + n += mapEntrySize + 1 + sovPublic(uint64(mapEntrySize)) + } + } + return n +} + func sovPublic(x uint64) (n int) { for { n++ @@ -3326,6 +3408,168 @@ func (m *ImportValueRequest) Unmarshal(dAtA []byte) error { } return nil } +func (m *AttrBlockResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPublic + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AttrBlockResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AttrBlockResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attrs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPublic + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPublic + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Attrs == nil { + m.Attrs = make(map[uint64]*AttrMap) + } + var mapkey uint64 + var mapvalue *AttrMap + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPublic + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPublic + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPublic + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthPublic + } + postmsgIndex := iNdEx + mapmsglen + if mapmsglen < 0 { + return ErrInvalidLengthPublic + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &AttrMap{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := skipPublic(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPublic + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Attrs[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPublic(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPublic + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipPublic(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 @@ -3434,46 +3678,50 @@ var ( func init() { proto.RegisterFile("public.proto", fileDescriptorPublic) } var fileDescriptorPublic = []byte{ - // 651 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcb, 0x6e, 0xd3, 0x40, - 0x14, 0x65, 0x62, 0xe7, 0x75, 0x93, 0x56, 0xd5, 0x08, 0x8a, 0x85, 0x50, 0x14, 0x59, 0x2c, 0xbc, - 0x4a, 0xa5, 0xf0, 0x01, 0x08, 0xb7, 0xa9, 0x64, 0x21, 0x2a, 0x98, 0x14, 0xf6, 0x6e, 0x3b, 0x2a, - 0x96, 0xfc, 0x62, 0x3c, 0x16, 0xed, 0x77, 0xb0, 0x61, 0xcd, 0x06, 0x7e, 0x80, 0x1d, 0x1f, 0xc0, - 0x92, 0x4f, 0x40, 0xe1, 0x47, 0xd0, 0xbd, 0xe3, 0x89, 0x1d, 0x16, 0xc0, 0x82, 0xdd, 0x9c, 0x73, - 0x1f, 0xbe, 0x8f, 0x73, 0x0d, 0xd3, 0xb2, 0xbe, 0x48, 0x93, 0xcb, 0x45, 0xa9, 0x0a, 0x5d, 0xf0, - 0x51, 0x92, 0x6b, 0xa9, 0xf2, 0x38, 0xf5, 0x43, 0x18, 0x84, 0x89, 0xce, 0xe2, 0x92, 0x73, 0x70, - 0xc3, 0x44, 0x57, 0x1e, 0x9b, 0x3b, 0x81, 0x2b, 0xe8, 0xcd, 0x1f, 0x41, 0xff, 0xa9, 0xd6, 0xaa, - 0xf2, 0x7a, 0x73, 0x27, 0x98, 0x2c, 0xf7, 0x17, 0x36, 0x6e, 0x81, 0xb4, 0x30, 0x46, 0x7f, 0x01, - 0xee, 0x8b, 0x38, 0x51, 0xfc, 0x00, 0x9c, 0x67, 0xf2, 0xd6, 0x63, 0x73, 0x16, 0xb8, 0x02, 0x9f, - 0xfc, 0x2e, 0xf4, 0x8f, 0x8b, 0x3a, 0xd7, 0x5e, 0x8f, 0x38, 0x03, 0xfc, 0x25, 0x8c, 0xd6, 0x75, - 0x46, 0x6f, 0x8c, 0x59, 0xd7, 0x19, 0xc5, 0x38, 0x02, 0x9f, 0xbb, 0x31, 0x8e, 0x8d, 0x79, 0x05, - 0x4e, 0x98, 0x68, 0x34, 0x8a, 0xe2, 0x5d, 0x74, 0xd2, 0x7c, 0xc4, 0x00, 0xfe, 0x00, 0x46, 0xc7, - 0x45, 0x5a, 0x67, 0x79, 0x74, 0xd2, 0x7c, 0x69, 0x8b, 0xf9, 0x43, 0x18, 0x9f, 0x27, 0x99, 0xac, - 0x74, 0x9c, 0x95, 0x9e, 0x43, 0x29, 0x5b, 0xc2, 0x5f, 0xc1, 0x9e, 0xf1, 0xc4, 0x4e, 0xd6, 0x52, - 0xf3, 0x7d, 0xe8, 0x6d, 0xb3, 0xf7, 0xa2, 0x93, 0x7f, 0x9c, 0xc0, 0x67, 0x06, 0x2e, 0xbe, 0xba, - 0x23, 0x18, 0x9b, 0x11, 0x70, 0x70, 0xcf, 0x6f, 0x4b, 0xd9, 0xd4, 0x45, 0x6f, 0x3e, 0x87, 0xc9, - 0x5a, 0xab, 0x24, 0xbf, 0x7e, 0x1d, 0xa7, 0xb5, 0xa4, 0xaa, 0xc6, 0xa2, 0x4b, 0x61, 0x47, 0x51, - 0xae, 0x8d, 0xd9, 0xa5, 0xa2, 0xb7, 0x18, 0x3b, 0x0a, 0x8b, 0x22, 0x35, 0xc6, 0xfe, 0x9c, 0x05, - 0x23, 0xd1, 0x12, 0x7c, 0x06, 0x70, 0x9a, 0x16, 0x71, 0x13, 0x3b, 0x98, 0xb3, 0x80, 0x89, 0x0e, - 0xe3, 0x1f, 0xc1, 0x10, 0x2b, 0x7d, 0x1e, 0x97, 0x6d, 0x6f, 0xec, 0x4f, 0xbd, 0x7d, 0x65, 0x30, - 0x7d, 0x59, 0x4b, 0x75, 0x2b, 0xe4, 0xdb, 0x5a, 0x56, 0xb4, 0x03, 0xc2, 0x4d, 0x97, 0x06, 0xf0, - 0x43, 0x18, 0xac, 0xd3, 0xe4, 0x52, 0x9a, 0x49, 0xb9, 0xa2, 0x41, 0xd8, 0x6b, 0x3b, 0xe1, 0x8a, - 0x7a, 0x1d, 0x89, 0x2e, 0x85, 0x91, 0x42, 0x66, 0x85, 0xb6, 0xcd, 0x34, 0x88, 0xfb, 0x30, 0x5d, - 0xdd, 0x5c, 0xa6, 0xf5, 0x95, 0x34, 0xa1, 0x03, 0xb2, 0xee, 0x70, 0x98, 0xbd, 0xc1, 0xa4, 0xdd, - 0xa1, 0xc9, 0xde, 0xa1, 0xfc, 0xf7, 0x0c, 0xf6, 0x9a, 0xf2, 0xab, 0xb2, 0xc8, 0x2b, 0x89, 0x3b, - 0x5a, 0x29, 0x65, 0x77, 0xb4, 0x52, 0x8a, 0x1f, 0xc1, 0x50, 0xc8, 0xaa, 0x4e, 0xb5, 0x5d, 0xf3, - 0xbd, 0x76, 0x14, 0x36, 0xb6, 0x4e, 0xb5, 0xb0, 0x5e, 0xfc, 0x09, 0xec, 0xef, 0xc8, 0x06, 0xfb, - 0xc2, 0xb8, 0xfb, 0x6d, 0xdc, 0x8e, 0x5d, 0xfc, 0xe6, 0xee, 0x7f, 0x61, 0x30, 0xe9, 0x64, 0xe6, - 0x81, 0x3d, 0x43, 0x2a, 0x6b, 0xb2, 0x3c, 0x68, 0x13, 0x19, 0x5e, 0xd8, 0x33, 0x9d, 0x02, 0x3b, - 0x6b, 0xc4, 0xc4, 0xce, 0x70, 0x85, 0x78, 0x7a, 0xf6, 0xfb, 0x9d, 0x15, 0x22, 0x2d, 0x8c, 0x91, - 0x7b, 0x30, 0x3c, 0x7e, 0x13, 0xe7, 0xd7, 0xf2, 0x8a, 0xc4, 0x34, 0x12, 0x16, 0xf2, 0x45, 0x7b, - 0x8a, 0x34, 0xfd, 0xc9, 0x92, 0xb7, 0x29, 0xac, 0x45, 0x6c, 0x7d, 0xfc, 0x4f, 0x0c, 0xf6, 0xa2, - 0xac, 0x2c, 0x94, 0xee, 0xa8, 0x21, 0xca, 0xaf, 0xe4, 0x8d, 0x55, 0x03, 0x01, 0x64, 0x4f, 0x55, - 0x9c, 0x19, 0xd9, 0x8f, 0x85, 0x01, 0xc8, 0x92, 0x2a, 0x48, 0x05, 0xae, 0x30, 0x80, 0xf6, 0x8f, - 0x67, 0x5c, 0x79, 0xae, 0x51, 0x8e, 0x41, 0xa8, 0x73, 0x7b, 0xc5, 0x95, 0xd7, 0x27, 0x53, 0x4b, - 0xa0, 0xce, 0xb7, 0x67, 0x8c, 0xda, 0x70, 0x02, 0x47, 0x74, 0x18, 0xff, 0x23, 0x03, 0x6e, 0x2a, - 0x25, 0xdd, 0xff, 0xbf, 0x72, 0xd1, 0x37, 0x91, 0xa9, 0x19, 0x25, 0xfa, 0x22, 0xf8, 0x4b, 0xb1, - 0x87, 0x30, 0xa0, 0x2a, 0x6c, 0xa1, 0x0d, 0x0a, 0x0f, 0xbe, 0x6d, 0x66, 0xec, 0xfb, 0x66, 0xc6, - 0x7e, 0x6c, 0x66, 0xec, 0xc3, 0xcf, 0xd9, 0x9d, 0x8b, 0x01, 0xfd, 0xa0, 0x1f, 0xff, 0x0a, 0x00, - 0x00, 0xff, 0xff, 0x4d, 0x1e, 0xdf, 0xba, 0xb0, 0x05, 0x00, 0x00, + // 720 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcb, 0x6e, 0xd3, 0x40, + 0x14, 0x65, 0x62, 0xe7, 0x75, 0x93, 0x56, 0xed, 0x08, 0x8a, 0x55, 0xa1, 0x28, 0xb2, 0x10, 0x64, + 0x95, 0x4a, 0x61, 0x83, 0x10, 0x12, 0x22, 0x6d, 0x2a, 0x45, 0x55, 0x2b, 0x98, 0x14, 0xf6, 0x6e, + 0x3a, 0x2a, 0x56, 0xfd, 0xc2, 0x1e, 0x43, 0xf3, 0x1d, 0x6c, 0x58, 0xb1, 0x60, 0x03, 0x3f, 0xc0, + 0x8e, 0x0f, 0x60, 0xc9, 0x27, 0xa0, 0xf2, 0x23, 0xe8, 0xde, 0xf1, 0xc4, 0x36, 0x0b, 0x60, 0xc1, + 0x6e, 0xce, 0xb9, 0x0f, 0xdf, 0xc7, 0xb9, 0x09, 0xf4, 0x93, 0xfc, 0x2c, 0xf0, 0x97, 0xe3, 0x24, + 0x8d, 0x55, 0xcc, 0x3b, 0x7e, 0xa4, 0x64, 0x1a, 0x79, 0x81, 0x3b, 0x85, 0xd6, 0xd4, 0x57, 0xa1, + 0x97, 0x70, 0x0e, 0xf6, 0xd4, 0x57, 0x99, 0xc3, 0x86, 0xd6, 0xc8, 0x16, 0xf4, 0xe6, 0x77, 0xa1, + 0xf9, 0x54, 0xa9, 0x34, 0x73, 0x1a, 0x43, 0x6b, 0xd4, 0x9b, 0x6c, 0x8e, 0x4d, 0xdc, 0x18, 0x69, + 0xa1, 0x8d, 0xee, 0x18, 0xec, 0x67, 0x9e, 0x9f, 0xf2, 0x2d, 0xb0, 0x8e, 0xe4, 0xca, 0x61, 0x43, + 0x36, 0xb2, 0x05, 0x3e, 0xf9, 0x4d, 0x68, 0xee, 0xc7, 0x79, 0xa4, 0x9c, 0x06, 0x71, 0x1a, 0xb8, + 0x13, 0xe8, 0x2c, 0xf2, 0x90, 0xde, 0x18, 0xb3, 0xc8, 0x43, 0x8a, 0xb1, 0x04, 0x3e, 0xeb, 0x31, + 0x96, 0x89, 0x79, 0x01, 0xd6, 0xd4, 0x57, 0x68, 0x14, 0xf1, 0xdb, 0xf9, 0x41, 0xf1, 0x11, 0x0d, + 0xf8, 0x2e, 0x74, 0xf6, 0xe3, 0x20, 0x0f, 0xa3, 0xf9, 0x41, 0xf1, 0xa5, 0x35, 0xe6, 0x77, 0xa0, + 0x7b, 0xea, 0x87, 0x32, 0x53, 0x5e, 0x98, 0x38, 0x16, 0xa5, 0x2c, 0x09, 0x77, 0x06, 0x1b, 0xda, + 0x13, 0x3b, 0x59, 0x48, 0xc5, 0x37, 0xa1, 0xb1, 0xce, 0xde, 0x98, 0x1f, 0xfc, 0xe3, 0x04, 0x3e, + 0x33, 0xb0, 0xf1, 0x55, 0x1d, 0x41, 0x57, 0x8f, 0x80, 0x83, 0x7d, 0xba, 0x4a, 0x64, 0x51, 0x17, + 0xbd, 0xf9, 0x10, 0x7a, 0x0b, 0x95, 0xfa, 0xd1, 0xc5, 0x4b, 0x2f, 0xc8, 0x25, 0x55, 0xd5, 0x15, + 0x55, 0x0a, 0x3b, 0x9a, 0x47, 0x4a, 0x9b, 0x6d, 0x2a, 0x7a, 0x8d, 0xb1, 0xa3, 0x69, 0x1c, 0x07, + 0xda, 0xd8, 0x1c, 0xb2, 0x51, 0x47, 0x94, 0x04, 0x1f, 0x00, 0x1c, 0x06, 0xb1, 0x57, 0xc4, 0xb6, + 0x86, 0x6c, 0xc4, 0x44, 0x85, 0x71, 0xf7, 0xa0, 0x8d, 0x95, 0x1e, 0x7b, 0x49, 0xd9, 0x1b, 0xfb, + 0x53, 0x6f, 0x5f, 0x19, 0xf4, 0x9f, 0xe7, 0x32, 0x5d, 0x09, 0xf9, 0x3a, 0x97, 0x19, 0xed, 0x80, + 0x70, 0xd1, 0xa5, 0x06, 0x7c, 0x07, 0x5a, 0x8b, 0xc0, 0x5f, 0x4a, 0x3d, 0x29, 0x5b, 0x14, 0x08, + 0x7b, 0x2d, 0x27, 0x9c, 0x51, 0xaf, 0x1d, 0x51, 0xa5, 0x30, 0x52, 0xc8, 0x30, 0x56, 0xa6, 0x99, + 0x02, 0x71, 0x17, 0xfa, 0xb3, 0xab, 0x65, 0x90, 0x9f, 0x4b, 0x1d, 0xda, 0x22, 0x6b, 0x8d, 0xc3, + 0xec, 0x05, 0x26, 0xed, 0xb6, 0x75, 0xf6, 0x0a, 0xe5, 0xbe, 0x63, 0xb0, 0x51, 0x94, 0x9f, 0x25, + 0x71, 0x94, 0x49, 0xdc, 0xd1, 0x2c, 0x4d, 0xcd, 0x8e, 0x66, 0x69, 0xca, 0xf7, 0xa0, 0x2d, 0x64, + 0x96, 0x07, 0xca, 0xac, 0xf9, 0x56, 0x39, 0x0a, 0x13, 0x9b, 0x07, 0x4a, 0x18, 0x2f, 0xfe, 0x04, + 0x36, 0x6b, 0xb2, 0xc1, 0xbe, 0x30, 0xee, 0x76, 0x19, 0x57, 0xb3, 0x8b, 0xdf, 0xdc, 0xdd, 0x2f, + 0x0c, 0x7a, 0x95, 0xcc, 0x7c, 0x64, 0xce, 0x90, 0xca, 0xea, 0x4d, 0xb6, 0xca, 0x44, 0x9a, 0x17, + 0xe6, 0x4c, 0xfb, 0xc0, 0x4e, 0x0a, 0x31, 0xb1, 0x13, 0x5c, 0x21, 0x9e, 0x9e, 0xf9, 0x7e, 0x65, + 0x85, 0x48, 0x0b, 0x6d, 0xe4, 0x0e, 0xb4, 0xf7, 0x5f, 0x79, 0xd1, 0x85, 0x3c, 0x27, 0x31, 0x75, + 0x84, 0x81, 0x7c, 0x5c, 0x9e, 0x22, 0x4d, 0xbf, 0x37, 0xe1, 0x65, 0x0a, 0x63, 0x11, 0x6b, 0x1f, + 0xf7, 0x13, 0x83, 0x8d, 0x79, 0x98, 0xc4, 0xa9, 0xaa, 0xa8, 0x61, 0x1e, 0x9d, 0xcb, 0x2b, 0xa3, + 0x06, 0x02, 0xc8, 0x1e, 0xa6, 0x5e, 0xa8, 0x65, 0xdf, 0x15, 0x1a, 0x20, 0x4b, 0xaa, 0x20, 0x15, + 0xd8, 0x42, 0x03, 0xda, 0x3f, 0x9e, 0x71, 0xe6, 0xd8, 0x5a, 0x39, 0x1a, 0xa1, 0xce, 0xcd, 0x15, + 0x67, 0x4e, 0x93, 0x4c, 0x25, 0x81, 0x3a, 0x5f, 0x9f, 0x31, 0x6a, 0xc3, 0x1a, 0x59, 0xa2, 0xc2, + 0xb8, 0x1f, 0x19, 0x70, 0x5d, 0x29, 0xe9, 0xfe, 0xff, 0x95, 0x8b, 0xbe, 0xbe, 0x0c, 0xf4, 0x28, + 0xd1, 0x17, 0xc1, 0x5f, 0x8a, 0xdd, 0x81, 0x16, 0x55, 0x61, 0x0a, 0x2d, 0x90, 0xfb, 0x81, 0xc1, + 0x36, 0x6a, 0x62, 0x1a, 0xc4, 0xcb, 0xcb, 0xb5, 0x40, 0x1f, 0xd7, 0xef, 0xf2, 0x5e, 0xfd, 0x2e, + 0x6b, 0xbe, 0xc4, 0x64, 0xb3, 0x48, 0xa5, 0xab, 0xe2, 0x5e, 0x77, 0x8f, 0x00, 0x4a, 0x12, 0xc5, + 0x7e, 0x59, 0xfe, 0x26, 0x5f, 0xca, 0x15, 0xbf, 0x0f, 0xcd, 0x37, 0xf4, 0xdb, 0xd0, 0xa0, 0x7d, + 0x6f, 0xd7, 0xb3, 0x1f, 0x7b, 0x89, 0xd0, 0xf6, 0x47, 0x8d, 0x87, 0x6c, 0xba, 0xf5, 0xed, 0x7a, + 0xc0, 0xbe, 0x5f, 0x0f, 0xd8, 0x8f, 0xeb, 0x01, 0x7b, 0xff, 0x73, 0x70, 0xe3, 0xac, 0x45, 0xff, + 0x20, 0x0f, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0xd5, 0xaa, 0x7d, 0x27, 0x51, 0x06, 0x00, 0x00, } diff --git a/internal/public.proto b/internal/public.proto index 47b04d8e7..43faca7dd 100644 --- a/internal/public.proto +++ b/internal/public.proto @@ -81,3 +81,7 @@ message ImportValueRequest { repeated uint64 ColumnIDs = 5; repeated int64 Values = 6; } + +message AttrBlockResponse { + map Attrs = 1; +} From fd70f0896718f9a385a2794bcd27dc90a1f14aa0 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Wed, 10 Jan 2018 10:09:13 -0600 Subject: [PATCH 14/14] Release v0.8.4 --- CHANGELOG.md | 14 ++++++++++++++ docs/installation.md | 12 ++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9676b4f89..654f2a051 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.8.4] - 2018-01-10 + +This version contains 4 contributions from 3 contributors. There are 17 files changed, 974 insertions, and 221 deletions. + +### Fixed + +- Group the write operations in syncBlock by MaxWritesPerRequest ([#1038](https://github.com/pilosa/pilosa/pull/1038)) +- Change gossip config from memberlist.DefaultLocalConfig to memberlist.DefaultWANConfig ([#1033](https://github.com/pilosa/pilosa/pull/1033)) + +### Performance + +- Change AttrBlock handler calls to support protobuf instead of json ([#1046](https://github.com/pilosa/pilosa/pull/1046)) +- Use RLock instead of Lock in a few places ([#1042](https://github.com/pilosa/pilosa/pull/1042)) + ## [0.8.3] - 2017-12-12 This version contains 1 contribution from 1 contributor. There are 2 files changed, 59 insertions, and 42 deletions. diff --git a/docs/installation.md b/docs/installation.md index 5a0ea3086..1ef7d1b23 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -74,19 +74,19 @@ There are four ways to install Pilosa on MacOS: Use [Homebrew](https://brew.sh/) 1. Download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.3/pilosa-v0.8.3-darwin-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.4/pilosa-v0.8.4-darwin-amd64.tar.gz ``` Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.3-darwin-amd64.tar.gz + tar xfz pilosa-v0.8.4-darwin-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.3-darwin-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.4-darwin-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: @@ -228,19 +228,19 @@ There are three ways to install Pilosa on Linux: download the binary (recommende 1. To install the latest version of Pilosa, download the latest release: ``` - curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.3/pilosa-v0.8.3-linux-amd64.tar.gz + curl -L -O https://github.com/pilosa/pilosa/releases/download/v0.8.4/pilosa-v0.8.4-linux-amd64.tar.gz ``` Note: This assumes you are using an `amd64` compatible architecture. Other releases can be downloaded from our Releases page on Github. 2. Extract the binary: ``` - tar xfz pilosa-v0.8.3-linux-amd64.tar.gz + tar xfz pilosa-v0.8.4-linux-amd64.tar.gz ``` 3. Move the binary into your PATH so you can run `pilosa` from any shell: ``` - cp -i pilosa-v0.8.3-linux-amd64/pilosa /usr/local/bin + cp -i pilosa-v0.8.4-linux-amd64/pilosa /usr/local/bin ``` 4. Make sure Pilosa is installed successfully: