Compare commits

...

36 commits

Author SHA1 Message Date
Matthew Jaffee
3257f34a3c
Merge pull request #1107 from jaffee/release-v0.8.6
update CHANGELOG, docs and Dockerfile for v0.8.6
2018-02-09 12:16:27 -06:00
Matthew Jaffee
27ab03ab84
fix capitalization and consistency in changelog 2018-02-09 12:13:33 -06:00
Matthew Jaffee
8a0bc78ba7
update CHANGELOG, docs and Dockerfile for v0.8.6 2018-02-09 12:03:58 -06:00
Travis Turner
bd3c315044
Merge pull request #1106 from travisturner/fix-diffrunarray-overflow-0.8
avoid overflow bug in differenceRunArray (v0.8)
2018-02-09 11:55:38 -06:00
Travis Turner
0229c9fae9
avoid overflow bug in differenceRunArray which was appending a full run to the container 2018-02-09 11:42:19 -06:00
Matthew Jaffee
6771061581
Merge pull request #1083 from jaffee/1082-count-v-bitmap
fix bug where count and bitmap queries could return different numbers
2018-02-07 08:45:31 -06:00
Matthew Jaffee
62185a27ba
fix bug where a count query and bitmap query could return different numbers
There was a case where the Bitmap iterator logic could skip over a bit in a run
container if 1. the run container was not the first container in the bitmap, and
2. The first run in the run container had only one bit.

The bug was due to how the iterator was initialized with iterator.Seek(0) which
sets up the initial values of itr.i,j,k based on the type of the first
container. It was failing to set itr.k to -1 unless the first container was an
RLE container. itr.k is only used by RLE containers in the iterator, and must be
set to -1 when an RLE container is encountered. When Iterator.Next() encountered
the run container and itr.k was set to 0, it checked to see if itr.k <= run.last
- run.first, and if so it assumes that it was finished with the run and moved to
the next one. run.last - run.first is 0 in the case of a single bit run, so that
bit was skipped. After this, itr.k is set to -1 and all further iteration
proceeds as expected.
2018-02-06 10:21:11 -06:00
Cody Soyland
3be4a9262f
Merge pull request #1062 from codysoyland/release-v0.8.5
Release v0.8.5
2018-01-18 13:25:09 -06:00
Cody Soyland
250922a5e3 Release v0.8.5 2018-01-18 11:18:45 -06:00
Cody Soyland
dac183e5a5
Merge pull request #1061 from codysoyland/977-docker-bind-localhost
977 docker bind localhost
2018-01-18 11:07:30 -06:00
Cody Soyland
176e1f63ca
Merge branch 'v0.8' into 977-docker-bind-localhost 2018-01-18 11:02:05 -06:00
Matthew Jaffee
09f07a646a
Merge pull request #1047 from codysoyland/release-v0.8.4
Release v0.8.4
2018-01-10 10:43:49 -06:00
Cody Soyland
fd70f08967 Release v0.8.4 2018-01-10 10:11:14 -06:00
Travis Turner
da3b98f574
Merge pull request #1046 from travisturner/attr-json-to-proto
change AttrBlock handler calls to support protobuf instead of json
2018-01-09 15:11:45 -06:00
Matthew Jaffee
0c27d86347
Merge pull request #1042 from jaffee/readlocks
Readlocks
2018-01-09 14:57:10 -06:00
Travis Turner
298d8ea866
change AttrBlock handler calls to support protobuf instead of json 2018-01-09 14:30:05 -06:00
Matthew Jaffee
55de0402d2
convert some locks to rlocks 2018-01-09 13:50:40 -06:00
Matthew Jaffee
42032584b5
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).
2018-01-09 12:42:27 -06:00
Matthew Jaffee
2caf01ac08
Merge pull request #1038 from raskle/914-syncblock-maxwrites
group the write operations in syncBlock by MaxWritesPerRequest
2018-01-08 16:07:34 -06:00
Matthew Jaffee
86a166fcc0
Merge pull request #1033 from jaffee/memberlist-wan-0.8
change gossip config from memberlist.DefaultLocalConfig to memberlist…
2017-12-24 10:20:50 -06:00
Travis Turner
7d26cc468e
change gossip config from memberlist.DefaultLocalConfig to memberlist.DefaultWANConfig 2017-12-23 16:26:41 -06:00
Cody Soyland
504fc0105d
Merge pull request #1005 from codysoyland/release-v0.8.3
Release v0.8.3
2017-12-12 16:40:39 -06:00
Cody Soyland
acf73194cd Release v0.8.3 2017-12-12 16:37:56 -06:00
Matthew Jaffee
1c9b1bee37
Merge pull request #1000 from jaffee/unmapped-mem
protect against accessing pointers to memory which was unmapped
2017-12-08 07:42:31 -06:00
Matthew Jaffee
256b736dc0
add container types to other tests (though they were passing already) 2017-12-07 15:20:53 -06:00
Matthew Jaffee
9d9eb98fa5
add container types and set c.n to get tests working 2017-12-07 14:58:11 -06:00
Matthew Jaffee
8fa965df37
protect against accessing pointers to memory which was unmapped 2017-12-07 14:02:25 -06:00
Cody Soyland
623efc8eff
Merge pull request #996 from codysoyland/release-v0.8.2
Release v0.8.2
2017-12-05 15:00:28 -06:00
Cody Soyland
25056e3015 Release v0.8.2 2017-12-05 14:41:08 -06:00
Matthew Jaffee
5d5d9ea57e
Merge pull request #994 from jaffee/single-http-client-0.8
Single http client 0.8
2017-12-05 13:48:44 -06:00
Todd Gruben
caede44346
limit httpclient instances on executor tests 2017-12-04 15:36:57 -06:00
Todd Gruben
073938622b
refactored httpclient handling 2017-12-04 15:36:47 -06:00
Matthew Jaffee
af5f0dd848
Merge pull request #975 from jaffee/fix-typo
language.txt -> languages.txt
2017-11-20 10:00:40 -06:00
Cody Soyland
0d4b79068f
Merge pull request #970 from codysoyland/release-v0.8.1
Release v0.8.1
2017-11-15 16:14:41 -06:00
Cody Soyland
a595d80fd4 Release v0.8.1 2017-11-15 16:03:40 -06:00
Michael Baird
59035883f4 group the write operations in syncBlock by MaxWritesPerRequest 2017-11-10 15:03:23 -06:00
30 changed files with 1385 additions and 373 deletions

View file

@ -5,6 +5,62 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/) The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.8.6] - 2018-02-09
This version contains 2 contributions from 2 contributors. There are 3 files changed, 171 insertions, and 6 deletions.
### Fixed
- Fix overflow bug in differenceRunArray [#1106](https://github.com/pilosa/pilosa/pull/1106)
- Fix bug where count and bitmap queries could return different numbers [#1083](https://github.com/pilosa/pilosa/pull/1083)
## [0.8.5] - 2018-01-18
This version contains 1 contribution from 1 contributor. There is 1 file changed, 1 insertion, and 0 deletions.
### Fixed
- Bind Docker container on all interfaces ([#1061](https://github.com/pilosa/pilosa/pull/1061))
## [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.
### 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.
### 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.
### 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 ## [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. This version contains 31 contributions from 8 contributors. There are 84 files changed, 3,732 insertions, and 1,428 deletions.

View file

@ -1,4 +1,4 @@
FROM golang:1.9.2 as builder FROM golang:1.9.4 as builder
ARG ldflags='' ARG ldflags=''

10
Gopkg.lock generated
View file

@ -14,10 +14,10 @@
revision = "39b0596a2da3c92787b3319c6b5425a474b4e0da" revision = "39b0596a2da3c92787b3319c6b5425a474b4e0da"
[[projects]] [[projects]]
branch = "master"
name = "github.com/DataDog/datadog-go" name = "github.com/DataDog/datadog-go"
packages = ["statsd"] packages = ["statsd"]
revision = "0ddda6bee21174ef6c4873647cb0d6ec9cba996f" revision = "4d2e5696ebe914940bd7459d2266fb7d555ea1b7"
version = "1.1.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -46,8 +46,8 @@
[[projects]] [[projects]]
name = "github.com/gogo/protobuf" name = "github.com/gogo/protobuf"
packages = ["proto"] packages = ["proto"]
revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02" revision = "100ba4e885062801d56799d78530b73b178a78f3"
version = "v0.5" version = "v0.4"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -238,6 +238,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "75badb0bcc3bb356b04af17979e0af61b4b66c5e0a483f09e39cf1f9b5e5de2c" inputs-digest = "d7c279ee1c617ec26e329979b5f92021287ede9701ff41e57c1fecad92ec6b51"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -1,3 +1,11 @@
# This file intentionally left blank as all needed dependencies are imported by # This file intentionally left blank as all needed dependencies are imported by
# the project and thus tracked by `dep`. # the project and thus tracked by `dep`.
# See https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md for details. # 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"

48
attr.go
View file

@ -348,6 +348,22 @@ func txUpdateAttrs(tx *bolt.Tx, id uint64, m map[string]interface{}) (map[string
return attr, nil 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 { func encodeAttrs(m map[string]interface{}) []*internal.Attr {
keys := make([]string, 0, len(m)) keys := make([]string, 0, len(m))
for k := range m { for k := range m {
@ -438,6 +454,38 @@ type AttrBlock struct {
Checksum []byte `json:"checksum"` 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. // AttrBlocks represents a list of blocks.
type AttrBlocks []AttrBlock type AttrBlocks []AttrBlock

View file

@ -15,6 +15,7 @@
package pilosa_test package pilosa_test
import ( import (
"fmt"
"reflect" "reflect"
"testing" "testing"
@ -23,14 +24,34 @@ import (
// Ensure a bitmap can be merged // Ensure a bitmap can be merged
func TestBitmap_Merge(t *testing.T) { func TestBitmap_Merge(t *testing.T) {
bm1 := pilosa.NewBitmap(1, 2, 3, SliceWidth+1, 2*SliceWidth) tests := []struct {
bm2 := pilosa.NewBitmap(3, 4, 5) bm1 *pilosa.Bitmap
bm1.Merge(bm2) bm2 *pilosa.Bitmap
exp uint64
if bm1.Count() != 7 { }{
t.Fatalf("Count after merge %d != 7\n", bm1.Count()) {
bm1: pilosa.NewBitmap(1, 2, 3, SliceWidth+1, 2*SliceWidth),
bm2: pilosa.NewBitmap(3, 4, 5),
exp: 7,
},
{
bm1: pilosa.NewBitmap(),
bm2: pilosa.NewBitmap(2, 66000, 70000, 70001, 70002, 70003, 70004),
exp: 7,
},
} }
for i, test := range tests {
t.Run(fmt.Sprintf("#%d:", i), func(t *testing.T) {
test.bm1.Merge(test.bm2)
if cnt := test.bm1.Count(); cnt != test.exp {
t.Fatalf("merged count %d is not %d", cnt, test.exp)
}
if length := len(test.bm1.Bits()); uint64(length) != test.exp {
t.Fatalf("merged length %d is not %d", length, test.exp)
}
})
}
} }
// Ensure a bitmap can Xor'ed // Ensure a bitmap can Xor'ed

View file

@ -25,7 +25,6 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"math/rand" "math/rand"
"net"
"net/http" "net/http"
"net/url" "net/url"
"sort" "sort"
@ -46,14 +45,13 @@ type ClientOptions struct {
// InternalHTTPClient represents a client to the Pilosa cluster. // InternalHTTPClient represents a client to the Pilosa cluster.
type InternalHTTPClient struct { type InternalHTTPClient struct {
defaultURI *URI defaultURI *URI
options *ClientOptions
// The client to use for HTTP communication. // The client to use for HTTP communication.
HTTPClient *http.Client HTTPClient *http.Client
} }
// NewInternalHTTPClient returns a new instance of InternalHTTPClient to connect to host. // 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 == "" { if host == "" {
return nil, ErrHostRequired return nil, ErrHostRequired
} }
@ -63,34 +61,14 @@ func NewInternalHTTPClient(host string, options *ClientOptions) (*InternalHTTPCl
return nil, err return nil, err
} }
client := NewInternalHTTPClientFromURI(uri, options) client := NewInternalHTTPClientFromURI(uri, remoteClient)
return client, nil return client, nil
} }
func NewInternalHTTPClientFromURI(defaultURI *URI, options *ClientOptions) *InternalHTTPClient { func NewInternalHTTPClientFromURI(defaultURI *URI, remoteClient *http.Client) *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}
return &InternalHTTPClient{ return &InternalHTTPClient{
defaultURI: defaultURI, defaultURI: defaultURI,
HTTPClient: client, HTTPClient: remoteClient,
} }
} }
@ -988,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) { 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)) u := uriPathToURL(c.defaultURI, fmt.Sprintf("/index/%s/attr/diff", index))
// Encode request. // Encode request object.
buf, err := json.Marshal(postIndexAttrDiffRequest{Blocks: blks}) buf, err := proto.Marshal(&internal.AttrBlockRequest{
Blocks: EncodeAttrBlocks(blks),
})
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("marshal column attr block request: %s", err)
} }
// Build request. // Build request.
@ -999,7 +979,9 @@ func (c *InternalHTTPClient) ColumnAttrDiff(ctx context.Context, index string, b
if err != nil { if err != nil {
return nil, err 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) req.Header.Set("User-Agent", "pilosa/"+Version)
// Execute request. // Execute request.
@ -1016,22 +998,31 @@ func (c *InternalHTTPClient) ColumnAttrDiff(ctx context.Context, index string, b
return nil, fmt.Errorf("unexpected status: code=%d", resp.StatusCode) return nil, fmt.Errorf("unexpected status: code=%d", resp.StatusCode)
} }
// Decode response object. // Read body.
var rsp postIndexAttrDiffResponse body, err := ioutil.ReadAll(resp.Body)
if err := json.NewDecoder(resp.Body).Decode(&rsp); err != nil { if err != nil {
return nil, err 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. // 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) { 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)) u := uriPathToURL(c.defaultURI, fmt.Sprintf("/index/%s/frame/%s/attr/diff", index, frame))
// Encode request. // Encode request object.
buf, err := json.Marshal(postFrameAttrDiffRequest{Blocks: blks}) buf, err := proto.Marshal(&internal.AttrBlockRequest{
Blocks: EncodeAttrBlocks(blks),
})
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("marshal row attr block request: %s", err)
} }
// Build request. // Build request.
@ -1039,7 +1030,9 @@ func (c *InternalHTTPClient) RowAttrDiff(ctx context.Context, index, frame strin
if err != nil { if err != nil {
return nil, err 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) req.Header.Set("User-Agent", "pilosa/"+Version)
// Execute request. // Execute request.
@ -1058,12 +1051,19 @@ func (c *InternalHTTPClient) RowAttrDiff(ctx context.Context, index, frame strin
return nil, fmt.Errorf("unexpected status: code=%d", resp.StatusCode) return nil, fmt.Errorf("unexpected status: code=%d", resp.StatusCode)
} }
// Decode response object. // Read body.
var rsp postFrameAttrDiffResponse body, err := ioutil.ReadAll(resp.Body)
if err := json.NewDecoder(resp.Body).Decode(&rsp); err != nil { if err != nil {
return nil, err 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 { func (c *InternalHTTPClient) clientURI(ctx context.Context) *URI {

View file

@ -18,6 +18,7 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"net/http"
"reflect" "reflect"
"testing" "testing"
@ -43,6 +44,13 @@ func createCluster(c *pilosa.Cluster) ([]*test.Server, []*test.Holder) {
return server, hldr return server, hldr
} }
var defaultClient *http.Client
func init() {
defaultClient = pilosa.GetHTTPClient(nil)
}
// Test distributed TopN Row count across 3 nodes. // Test distributed TopN Row count across 3 nodes.
func TestClient_MultiNode(t *testing.T) { func TestClient_MultiNode(t *testing.T) {
cluster := test.NewCluster(3) 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) { 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.Holder = hldr[0].Holder
e.Scheme = cluster.Nodes[0].Scheme e.Scheme = cluster.Nodes[0].Scheme
e.Host = cluster.Nodes[0].Host e.Host = cluster.Nodes[0].Host
@ -62,7 +70,7 @@ func TestClient_MultiNode(t *testing.T) {
return e.Execute(ctx, index, query, slices, opt) 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) { 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.Holder = hldr[1].Holder
e.Scheme = cluster.Nodes[1].Scheme e.Scheme = cluster.Nodes[1].Scheme
e.Host = cluster.Nodes[1].Host e.Host = cluster.Nodes[1].Host
@ -70,7 +78,7 @@ func TestClient_MultiNode(t *testing.T) {
return e.Execute(ctx, index, query, slices, opt) 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) { 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.Holder = hldr[2].Holder
e.Scheme = cluster.Nodes[2].Scheme e.Scheme = cluster.Nodes[2].Scheme
e.Host = cluster.Nodes[2].Host e.Host = cluster.Nodes[2].Host
@ -135,9 +143,9 @@ func TestClient_MultiNode(t *testing.T) {
// Connect to each node to compare results. // Connect to each node to compare results.
client := make([]*test.Client, 3) client := make([]*test.Client, 3)
client[0] = test.MustNewClient(s[0].Host()) client[0] = test.MustNewClient(s[0].Host(), defaultClient)
client[1] = test.MustNewClient(s[1].Host()) client[1] = test.MustNewClient(s[1].Host(), defaultClient)
client[2] = test.MustNewClient(s[2].Host()) client[2] = test.MustNewClient(s[2].Host(), defaultClient)
topN := 4 topN := 4
queryRequest := &internal.QueryRequest{ queryRequest := &internal.QueryRequest{
@ -218,7 +226,7 @@ func TestClient_Import(t *testing.T) {
s.Handler.Holder = hldr.Holder s.Handler.Holder = hldr.Holder
// Send import request. // 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{ if err := c.Import(context.Background(), "i", "f", 0, []pilosa.Bit{
{RowID: 0, ColumnID: 1}, {RowID: 0, ColumnID: 1},
{RowID: 0, ColumnID: 5}, {RowID: 0, ColumnID: 5},
@ -269,7 +277,7 @@ func TestClient_ImportInverseEnabled(t *testing.T) {
s.Handler.Holder = hldr.Holder s.Handler.Holder = hldr.Holder
// Send import request. // 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{ if err := c.Import(context.Background(), "i", "f", 0, []pilosa.Bit{
{RowID: 0, ColumnID: 1}, {RowID: 0, ColumnID: 1},
{RowID: 0, ColumnID: 5}, {RowID: 0, ColumnID: 5},
@ -318,7 +326,7 @@ func TestClient_ImportValue(t *testing.T) {
s.Handler.Holder = hldr.Holder s.Handler.Holder = hldr.Holder
// Send import request. // 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{ if err := c.ImportValue(context.Background(), "i", "f", fld.Name, 0, []pilosa.FieldValue{
{ColumnID: 1, Value: -10}, {ColumnID: 1, Value: -10},
{ColumnID: 2, Value: 20}, {ColumnID: 2, Value: 20},
@ -355,7 +363,7 @@ func TestClient_BackupRestore(t *testing.T) {
s.Handler.Cluster.Nodes[0].Host = s.Host() s.Handler.Cluster.Nodes[0].Host = s.Host()
s.Handler.Holder = hldr.Holder s.Handler.Holder = hldr.Holder
c := test.MustNewClient(s.Host()) c := test.MustNewClient(s.Host(), defaultClient)
// Backup from frame. // Backup from frame.
var buf bytes.Buffer var buf bytes.Buffer
@ -420,7 +428,7 @@ func TestClient_BackupInverseView(t *testing.T) {
s.Handler.Cluster.Nodes[0].Host = s.Host() s.Handler.Cluster.Nodes[0].Host = s.Host()
s.Handler.Holder = hldr.Holder s.Handler.Holder = hldr.Holder
c := test.MustNewClient(s.Host()) c := test.MustNewClient(s.Host(), defaultClient)
// Backup from frame. // Backup from frame.
var buf bytes.Buffer var buf bytes.Buffer
@ -457,7 +465,7 @@ func TestClient_BackupInvalidView(t *testing.T) {
s.Handler.Cluster.Nodes[0].Host = s.Host() s.Handler.Cluster.Nodes[0].Host = s.Host()
s.Handler.Holder = hldr.Holder s.Handler.Holder = hldr.Holder
c := test.MustNewClient(s.Host()) c := test.MustNewClient(s.Host(), defaultClient)
// Backup from frame. // Backup from frame.
var buf bytes.Buffer var buf bytes.Buffer
@ -487,7 +495,7 @@ func TestClient_FragmentBlocks(t *testing.T) {
s.Handler.Holder = hldr.Holder s.Handler.Holder = hldr.Holder
// Retrieve blocks. // Retrieve blocks.
c := test.MustNewClient(s.Host()) c := test.MustNewClient(s.Host(), defaultClient)
blocks, err := c.FragmentBlocks(context.Background(), "i", "f", pilosa.ViewStandard, 0) blocks, err := c.FragmentBlocks(context.Background(), "i", "f", pilosa.ViewStandard, 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -144,14 +144,18 @@ type Cluster struct {
// Threshold for logging long-running queries // Threshold for logging long-running queries
LongQueryTime time.Duration LongQueryTime time.Duration
// Maximum number of SetBit() or ClearBit() commands per request.
MaxWritesPerRequest int
} }
// NewCluster returns a new instance of Cluster with defaults. // NewCluster returns a new instance of Cluster with defaults.
func NewCluster() *Cluster { func NewCluster() *Cluster {
return &Cluster{ return &Cluster{
Hasher: &jmphasher{}, Hasher: &jmphasher{},
PartitionN: DefaultPartitionN, PartitionN: DefaultPartitionN,
ReplicaN: DefaultReplicaN, ReplicaN: DefaultReplicaN,
MaxWritesPerRequest: DefaultMaxWritesPerRequest,
} }
} }

View file

@ -2,6 +2,7 @@ package ctl
import ( import (
"crypto/tls" "crypto/tls"
"github.com/pilosa/pilosa" "github.com/pilosa/pilosa"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@ -22,19 +23,18 @@ func SetTLSConfig(flags *pflag.FlagSet, certificatePath *string, certificateKeyP
// CommandClient returns a pilosa.InternalHTTPClient for the command // CommandClient returns a pilosa.InternalHTTPClient for the command
func CommandClient(cmd CommandWithTLSSupport) (*pilosa.InternalHTTPClient, error) { func CommandClient(cmd CommandWithTLSSupport) (*pilosa.InternalHTTPClient, error) {
tlsConfig := cmd.TLSConfiguration() tlsConfig := cmd.TLSConfiguration()
var clientOptions *pilosa.ClientOptions var TLSConfig *tls.Config
if tlsConfig.CertificatePath != "" && tlsConfig.CertificateKeyPath != "" { if tlsConfig.CertificatePath != "" && tlsConfig.CertificateKeyPath != "" {
cert, err := tls.LoadX509KeyPair(tlsConfig.CertificatePath, tlsConfig.CertificateKeyPath) cert, err := tls.LoadX509KeyPair(tlsConfig.CertificatePath, tlsConfig.CertificateKeyPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
TLSConfig := &tls.Config{ TLSConfig = &tls.Config{
Certificates: []tls.Certificate{cert}, Certificates: []tls.Certificate{cert},
InsecureSkipVerify: tlsConfig.SkipVerify, 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 { if err != nil {
return nil, err return nil, err
} }

View file

@ -74,19 +74,19 @@ There are four ways to install Pilosa on MacOS: Use [Homebrew](https://brew.sh/)
1. Download the latest release: 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.6/pilosa-v0.8.6-darwin-amd64.tar.gz
``` ```
Other releases can be downloaded from our Releases page on Github. Other releases can be downloaded from our Releases page on Github.
2. Extract the binary: 2. Extract the binary:
``` ```
tar xfz pilosa-v0.8.0-darwin-amd64.tar.gz tar xfz pilosa-v0.8.6-darwin-amd64.tar.gz
``` ```
3. Move the binary into your PATH so you can run `pilosa` from any shell: 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.6-darwin-amd64/pilosa /usr/local/bin
``` ```
4. Make sure Pilosa is installed successfully: 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: 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.6/pilosa-v0.8.6-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. 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: 2. Extract the binary:
``` ```
tar xfz pilosa-v0.8.0-linux-amd64.tar.gz tar xfz pilosa-v0.8.6-linux-amd64.tar.gz
``` ```
3. Move the binary into your PATH so you can run `pilosa` from any shell: 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.6-linux-amd64/pilosa /usr/local/bin
``` ```
4. Make sure Pilosa is installed successfully: 4. Make sure Pilosa is installed successfully:

View file

@ -18,6 +18,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"net/http"
"sort" "sort"
"time" "time"
@ -51,12 +52,9 @@ type Executor struct {
} }
// NewExecutor returns a new instance of Executor. // NewExecutor returns a new instance of Executor.
func NewExecutor(clientOptions *ClientOptions) *Executor { func NewExecutor(remoteClient *http.Client) *Executor {
if clientOptions == nil {
clientOptions = &ClientOptions{}
}
return &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. // 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 return false, err
} else { } else {
ret = res[0].(bool) 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. // 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 return false, err
} else { } else {
ret = res[0].(bool) 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)) resp := make(chan error, len(nodes))
for _, node := range nodes { for _, node := range nodes {
go func(node *Node) { 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 resp <- err
}(node) }(node)
} }
@ -1199,7 +1197,7 @@ func (e *Executor) executeSetRowAttrs(ctx context.Context, index string, c *pql.
resp := make(chan error, len(nodes)) resp := make(chan error, len(nodes))
for _, node := range nodes { for _, node := range nodes {
go func(node *Node) { 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 resp <- err
}(node) }(node)
} }
@ -1286,7 +1284,7 @@ func (e *Executor) executeBulkSetRowAttrs(ctx context.Context, index string, cal
resp := make(chan error, len(nodes)) resp := make(chan error, len(nodes))
for _, node := range nodes { for _, node := range nodes {
go func(node *Node) { 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 resp <- err
}(node) }(node)
} }
@ -1345,7 +1343,7 @@ func (e *Executor) executeSetColumnAttrs(ctx context.Context, index string, c *p
resp := make(chan error, len(nodes)) resp := make(chan error, len(nodes))
for _, node := range nodes { for _, node := range nodes {
go func(node *Node) { 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 resp <- err
}(node) }(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. // 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. // Encode request object.
pbreq := &internal.QueryRequest{ pbreq := &internal.QueryRequest{
Query: q.String(), Query: q.String(),
@ -1511,7 +1509,7 @@ func (e *Executor) mapper(ctx context.Context, ch chan mapResponse, nodes []*Nod
if n.Host == e.Host { if n.Host == e.Host {
resp.result, resp.err = e.mapperLocal(ctx, nodeSlices, mapFn, reduceFn) resp.result, resp.err = e.mapperLocal(ctx, nodeSlices, mapFn, reduceFn)
} else if !opt.Remote { } 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 { if len(results) > 0 {
resp.result = results[0] resp.result = results[0]
} }

View file

@ -28,6 +28,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http"
"os" "os"
"sort" "sort"
"sync" "sync"
@ -492,7 +493,7 @@ func (f *Fragment) FieldValue(columnID uint64, bitDepth uint) (value uint64, exi
f.mu.Lock() f.mu.Lock()
defer f.mu.Unlock() 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 { if v, err := f.bit(uint64(bitDepth), columnID); err != nil {
return 0, false, err return 0, false, err
} else if !v { } else if !v {
@ -586,7 +587,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. // 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. // 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) { 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)) row := f.Row(uint64(bitDepth))
if filter != nil { if filter != nil {
count = row.IntersectionCount(filter) count = row.IntersectionCount(filter)
@ -615,6 +616,7 @@ func (f *Fragment) FieldSum(filter *Bitmap, bitDepth uint) (sum, count uint64, e
return sum, count, nil 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) { func (f *Fragment) FieldRange(op pql.Token, bitDepth uint, predicate uint64) (*Bitmap, error) {
switch op { switch op {
case pql.EQ: case pql.EQ:
@ -753,6 +755,7 @@ func (f *Fragment) FieldNotNull(bitDepth uint) (*Bitmap, error) {
return f.Row(uint64(bitDepth)), nil 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) { func (f *Fragment) FieldRangeBetween(bitDepth uint, predicateMin, predicateMax uint64) (*Bitmap, error) {
b := f.Row(uint64(bitDepth)) b := f.Row(uint64(bitDepth))
keep1 := NewBitmap() // GTE keep1 := NewBitmap() // GTE
@ -1677,9 +1680,9 @@ func (h *blockHasher) WriteValue(v uint64) {
type FragmentSyncer struct { type FragmentSyncer struct {
Fragment *Fragment Fragment *Fragment
Host string Host string
Cluster *Cluster Cluster *Cluster
ClientOptions *ClientOptions RemoteClient *http.Client
Closing <-chan struct{} Closing <-chan struct{}
} }
@ -1714,7 +1717,7 @@ func (s *FragmentSyncer) SyncFragment() error {
} }
// Retrieve remote blocks. // Retrieve remote blocks.
client, err := NewInternalHTTPClient(node.Host, s.ClientOptions) client, err := NewInternalHTTPClient(node.Host, s.RemoteClient)
if err != nil { if err != nil {
return err return err
} }
@ -1793,7 +1796,7 @@ func (s *FragmentSyncer) syncBlock(id int) error {
return nil return nil
} }
client, err := NewInternalHTTPClient(node.Host, s.ClientOptions) client, err := NewInternalHTTPClient(node.Host, s.RemoteClient)
if err != nil { if err != nil {
return err return err
} }
@ -1825,36 +1828,43 @@ func (s *FragmentSyncer) syncBlock(id int) error {
// Write updates to remote blocks. // Write updates to remote blocks.
for i := 0; i < len(clients); i++ { for i := 0; i < len(clients); i++ {
set, clear := sets[i], clears[i] set, clear := sets[i], clears[i]
count := 0
// Ignore if there are no differences. // Ignore if there are no differences.
if len(set.ColumnIDs) == 0 && len(clear.ColumnIDs) == 0 { if len(set.ColumnIDs) == 0 && len(clear.ColumnIDs) == 0 {
continue continue
} }
// Generate query with sets & clears. // Generate query with sets & clears, and group the requests to not exceed MaxWritesPerRequest.
var buf bytes.Buffer 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. // Only sync the standard block.
for j := 0; j < len(set.ColumnIDs); j++ { 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++ { 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. // Iterate over the buffers.
if s.isClosing() { for k := 0; k < len(buffers); k++ {
return nil // Verify sync is not prematurely closing.
} if s.isClosing() {
return nil
}
// Execute query. // Execute query.
queryRequest := &internal.QueryRequest{ queryRequest := &internal.QueryRequest{
Query: buf.String(), Query: buffers[k].String(),
Remote: true, Remote: true,
} }
_, err := clients[i].ExecuteQuery(context.Background(), f.Index(), queryRequest) _, err := clients[i].ExecuteQuery(context.Background(), f.Index(), queryRequest)
if err != nil { if err != nil {
return err return err
}
} }
} }

View file

@ -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. // Views returns a list of all views in the frame.
func (f *Frame) Views() []*View { func (f *Frame) Views() []*View {
f.mu.Lock() f.mu.RLock()
defer f.mu.Unlock() defer f.mu.RUnlock()
other := make([]*View, 0, len(f.views)) other := make([]*View, 0, len(f.views))
for _, view := range f.views { for _, view := range f.views {

View file

@ -130,7 +130,7 @@ func NewGossipNodeSet(name string, gossipHost string, gossipPort int, gossipSeed
//TODO: pull memberlist config from pilosa.cfg file //TODO: pull memberlist config from pilosa.cfg file
g.config = &gossipConfig{ g.config = &gossipConfig{
memberlistConfig: memberlist.DefaultLocalConfig(), memberlistConfig: memberlist.DefaultWANConfig(),
gossipSeed: gossipSeed, gossipSeed: gossipSeed,
} }
g.config.memberlistConfig.Name = name g.config.memberlistConfig.Name = name

View file

@ -56,9 +56,9 @@ type Handler struct {
StatusHandler StatusHandler StatusHandler StatusHandler
// Local hostname & cluster configuration. // Local hostname & cluster configuration.
URI *URI URI *URI
Cluster *Cluster Cluster *Cluster
ClientOptions *ClientOptions RemoteClient *http.Client
Router *mux.Router Router *mux.Router
@ -538,11 +538,27 @@ type patchIndexTimeQuantumResponse struct{}
// handlePostIndexAttrDiff handles POST /index/attr/diff requests. // handlePostIndexAttrDiff handles POST /index/attr/diff requests.
func (h *Handler) handlePostIndexAttrDiff(w http.ResponseWriter, r *http.Request) { 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"] indexName := mux.Vars(r)["index"]
// Decode request. // Read entire body.
var req postIndexAttrDiffRequest body, err := ioutil.ReadAll(r.Body)
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { 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) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
@ -563,7 +579,7 @@ func (h *Handler) handlePostIndexAttrDiff(w http.ResponseWriter, r *http.Request
// Read all attributes from all mismatched blocks. // Read all attributes from all mismatched blocks.
attrs := make(map[uint64]map[string]interface{}) 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. // Retrieve block data.
m, err := index.ColumnAttrStore().BlockData(blockID) m, err := index.ColumnAttrStore().BlockData(blockID)
if err != nil { if err != nil {
@ -577,20 +593,17 @@ func (h *Handler) handlePostIndexAttrDiff(w http.ResponseWriter, r *http.Request
} }
} }
// Encode response. // Marshal response object.
if err := json.NewEncoder(w).Encode(postIndexAttrDiffResponse{ buf, err := proto.Marshal(&internal.AttrBlockResponse{
Attrs: attrs, Attrs: encodeAttrsMap(attrs),
}); err != nil { })
h.logger().Printf("response encoding error: %s", err)
// Write response.
if err != nil {
h.logger().Printf("row attr response encoding error: %s", err)
w.WriteHeader(http.StatusInternalServerError)
} }
} w.Write(buf)
type postIndexAttrDiffRequest struct {
Blocks []AttrBlock `json:"blocks"`
}
type postIndexAttrDiffResponse struct {
Attrs map[uint64]map[string]interface{} `json:"attrs"`
} }
// handlePostFrame handles POST /frame request. // handlePostFrame handles POST /frame request.
@ -956,12 +969,28 @@ type getFrameViewsResponse struct {
// handlePostFrameAttrDiff handles POST /frame/attr/diff requests. // handlePostFrameAttrDiff handles POST /frame/attr/diff requests.
func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request) { 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"] indexName := mux.Vars(r)["index"]
frameName := mux.Vars(r)["frame"] frameName := mux.Vars(r)["frame"]
// Decode request. // Read entire body.
var req postFrameAttrDiffRequest body, err := ioutil.ReadAll(r.Body)
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { 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) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
@ -982,7 +1011,7 @@ func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request
// Read all attributes from all mismatched blocks. // Read all attributes from all mismatched blocks.
attrs := make(map[uint64]map[string]interface{}) 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. // Retrieve block data.
m, err := f.RowAttrStore().BlockData(blockID) m, err := f.RowAttrStore().BlockData(blockID)
if err != nil { if err != nil {
@ -996,20 +1025,17 @@ func (h *Handler) handlePostFrameAttrDiff(w http.ResponseWriter, r *http.Request
} }
} }
// Encode response. // Marshal response object.
if err := json.NewEncoder(w).Encode(postFrameAttrDiffResponse{ buf, err := proto.Marshal(&internal.AttrBlockResponse{
Attrs: attrs, Attrs: encodeAttrsMap(attrs),
}); err != nil { })
h.logger().Printf("response encoding error: %s", err)
// Write response.
if err != nil {
h.logger().Printf("row attr response encoding error: %s", err)
w.WriteHeader(http.StatusInternalServerError)
} }
} w.Write(buf)
type postFrameAttrDiffRequest struct {
Blocks []AttrBlock `json:"blocks"`
}
type postFrameAttrDiffResponse struct {
Attrs map[uint64]map[string]interface{} `json:"attrs"`
} }
// readColumnAttrSets returns a list of column attribute objects by id. // readColumnAttrSets returns a list of column attribute objects by id.
@ -1506,7 +1532,7 @@ func (h *Handler) handlePostFrameRestore(w http.ResponseWriter, r *http.Request)
} }
// Create a client for the remote cluster. // Create a client for the remote cluster.
client := NewInternalHTTPClientFromURI(host, h.ClientOptions) client := NewInternalHTTPClientFromURI(host, h.RemoteClient)
// Determine the maximum number of slices. // Determine the maximum number of slices.
maxSlices, err := client.MaxSliceByIndex(r.Context()) maxSlices, err := client.MaxSliceByIndex(r.Context())

View file

@ -24,6 +24,7 @@ import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"reflect" "reflect"
"strconv"
"strings" "strings"
"testing" "testing"
@ -793,20 +794,53 @@ func TestHandler_Index_AttrStore_Diff(t *testing.T) {
blks = blks[1:] blks = blks[1:]
blks[1].Checksum = []byte("MISMATCHED_CHECKSUM") 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. // Send block checksums to determine diff.
resp, err := http.Post( client := &http.Client{}
req, err := http.NewRequest(
"POST",
s.URL+"/index/i/attr/diff", s.URL+"/index/i/attr/diff",
"application/json", bytes.NewReader(buf),
strings.NewReader(`{"blocks":`+string(test.MustMarshalJSON(blks))+`}`),
) )
if err != nil { if err != nil {
t.Fatal(err) 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() defer resp.Body.Close()
// Read and validate body. // Read body.
if body := string(test.MustReadAll(resp.Body)); body != `{"attrs":{"1":{"bar":2,"foo":1},"200":{"snowman":"☃"}}}`+"\n" { body, err := ioutil.ReadAll(resp.Body)
t.Fatalf("unexpected body: %s", 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 = blks[1:]
blks[1].Checksum = []byte("MISMATCHED_CHECKSUM") 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. // 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", s.URL+"/index/i/frame/meta/attr/diff",
"application/json", bytes.NewReader(buf),
strings.NewReader(`{"blocks":`+string(test.MustMarshalJSON(blks))+`}`),
) )
if err != nil { if err != nil {
t.Fatal(err) 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() defer resp.Body.Close()
// Read and validate body. // Read body.
if body := string(test.MustReadAll(resp.Body)); body != `{"attrs":{"1":{"bar":2,"foo":1},"200":{"snowman":"☃"}}}`+"\n" { body, err := ioutil.ReadAll(resp.Body)
t.Fatalf("unexpected body: %s", 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)
} }
} }

View file

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -195,15 +196,14 @@ func (h *Holder) index(name string) *Index { return h.indexes[name] }
// Indexes returns a list of all indexes in the holder. // Indexes returns a list of all indexes in the holder.
func (h *Holder) Indexes() []*Index { func (h *Holder) Indexes() []*Index {
h.mu.Lock() h.mu.RLock()
defer h.mu.Unlock()
a := make([]*Index, 0, len(h.indexes)) a := make([]*Index, 0, len(h.indexes))
for _, index := range h.indexes { for _, index := range h.indexes {
a = append(a, index) a = append(a, index)
} }
sort.Sort(indexSlice(a)) h.mu.RUnlock()
sort.Sort(indexSlice(a))
return a return a
} }
@ -430,9 +430,9 @@ func (h *Holder) logger() *log.Logger { return log.New(h.LogOutput, "", log.Lstd
type HolderSyncer struct { type HolderSyncer struct {
Holder *Holder Holder *Holder
URI *URI URI *URI
Cluster *Cluster Cluster *Cluster
ClientOptions *ClientOptions RemoteClient *http.Client
// Signals that the sync should stop. // Signals that the sync should stop.
Closing <-chan struct{} Closing <-chan struct{}
@ -518,7 +518,7 @@ func (s *HolderSyncer) syncIndex(index string) error {
// Sync with every other host. // Sync with every other host.
for _, node := range Nodes(s.Cluster.Nodes).FilterHost(s.URI.HostPort()) { 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 { if err != nil {
return err return err
} }
@ -563,7 +563,7 @@ func (s *HolderSyncer) syncFrame(index, name string) error {
// Sync with every other host. // Sync with every other host.
for _, node := range Nodes(s.Cluster.Nodes).FilterHost(s.URI.HostPort()) { 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 { if err != nil {
return err return err
} }
@ -616,11 +616,11 @@ func (s *HolderSyncer) syncFragment(index, frame, view string, slice uint64) err
// Sync fragments together. // Sync fragments together.
fs := FragmentSyncer{ fs := FragmentSyncer{
Fragment: frag, Fragment: frag,
Host: s.URI.HostPort(), Host: s.URI.HostPort(),
Cluster: s.Cluster, Cluster: s.Cluster,
Closing: s.Closing, Closing: s.Closing,
ClientOptions: s.ClientOptions, RemoteClient: s.RemoteClient,
} }
if err := fs.SyncFragment(); err != nil { if err := fs.SyncFragment(); err != nil {
return err return err

View file

@ -320,7 +320,7 @@ func TestHolder_DeleteIndex(t *testing.T) {
// Ensure holder can sync with a remote holder. // Ensure holder can sync with a remote holder.
func TestHolderSyncer_SyncHolder(t *testing.T) { func TestHolderSyncer_SyncHolder(t *testing.T) {
cluster := test.NewCluster(2) cluster := test.NewCluster(2)
client := pilosa.GetHTTPClient(nil)
// Create a local holder. // Create a local holder.
hldr0 := test.MustOpenHolder() hldr0 := test.MustOpenHolder()
defer hldr0.Close() defer hldr0.Close()
@ -332,7 +332,7 @@ func TestHolderSyncer_SyncHolder(t *testing.T) {
defer s.Close() defer s.Close()
s.Handler.Holder = hldr1.Holder 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) { 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.Holder = hldr1.Holder
e.Scheme = cluster.Nodes[1].Scheme e.Scheme = cluster.Nodes[1].Scheme
e.Host = cluster.Nodes[1].Host e.Host = cluster.Nodes[1].Host
@ -400,9 +400,10 @@ func TestHolderSyncer_SyncHolder(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
syncer := pilosa.HolderSyncer{ syncer := pilosa.HolderSyncer{
Holder: hldr0.Holder, Holder: hldr0.Holder,
URI: uri, URI: uri,
Cluster: cluster, Cluster: cluster,
RemoteClient: pilosa.GetHTTPClient(nil),
} }
if err := syncer.SyncHolder(); err != nil { if err := syncer.SyncHolder(); err != nil {

View file

@ -32,6 +32,8 @@
FrameSchema FrameSchema
Field Field
DeleteViewMessage DeleteViewMessage
AttrBlock
AttrBlockRequest
*/ */
package internal package internal
@ -768,6 +770,47 @@ func (m *DeleteViewMessage) GetView() string {
return "" 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() { func init() {
proto.RegisterType((*IndexMeta)(nil), "internal.IndexMeta") proto.RegisterType((*IndexMeta)(nil), "internal.IndexMeta")
proto.RegisterType((*FrameMeta)(nil), "internal.FrameMeta") proto.RegisterType((*FrameMeta)(nil), "internal.FrameMeta")
@ -793,6 +836,8 @@ func init() {
proto.RegisterType((*FrameSchema)(nil), "internal.FrameSchema") proto.RegisterType((*FrameSchema)(nil), "internal.FrameSchema")
proto.RegisterType((*Field)(nil), "internal.Field") proto.RegisterType((*Field)(nil), "internal.Field")
proto.RegisterType((*DeleteViewMessage)(nil), "internal.DeleteViewMessage") 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) { func (m *IndexMeta) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
@ -1762,6 +1807,65 @@ func (m *DeleteViewMessage) MarshalTo(dAtA []byte) (int, error) {
return i, nil 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 { func encodeVarintPrivate(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 { for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80) dAtA[offset] = uint8(v&0x7f | 0x80)
@ -2201,6 +2305,31 @@ func (m *DeleteViewMessage) Size() (n int) {
return n 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) { func sovPrivate(x uint64) (n int) {
for { for {
n++ n++
@ -5509,6 +5638,187 @@ func (m *DeleteViewMessage) Unmarshal(dAtA []byte) error {
} }
return nil 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) { func skipPrivate(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0
@ -5617,65 +5927,68 @@ var (
func init() { proto.RegisterFile("private.proto", fileDescriptorPrivate) } func init() { proto.RegisterFile("private.proto", fileDescriptorPrivate) }
var fileDescriptorPrivate = []byte{ var fileDescriptorPrivate = []byte{
// 948 bytes of a gzipped FileDescriptorProto // 999 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xc1, 0x6e, 0x23, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcd, 0x6e, 0x23, 0x45,
0x10, 0x65, 0x3c, 0x63, 0xaf, 0x5d, 0x26, 0x1b, 0xa7, 0x09, 0x2b, 0x6f, 0x14, 0x19, 0xab, 0x0f, 0x10, 0x66, 0xec, 0xb1, 0xd7, 0x2e, 0x6f, 0x12, 0x67, 0x08, 0x2b, 0x6f, 0x14, 0x19, 0xab, 0x0f,
0x6c, 0x88, 0x44, 0x0e, 0x41, 0x5a, 0x01, 0xcb, 0x01, 0x36, 0xce, 0x2a, 0x16, 0x78, 0x81, 0xf6, 0x6c, 0x08, 0x22, 0x87, 0x20, 0x2d, 0x3f, 0x8b, 0x04, 0xbb, 0x76, 0x56, 0x19, 0x81, 0x17, 0x68,
0x6a, 0xb9, 0x21, 0x75, 0x9c, 0x62, 0x77, 0x94, 0xf1, 0x8c, 0x99, 0x69, 0x27, 0x31, 0x07, 0x8e, 0xaf, 0x96, 0x1b, 0x52, 0xc7, 0x29, 0x36, 0xa3, 0x8c, 0x67, 0xcc, 0x4c, 0x3b, 0x89, 0x39, 0x70,
0x7c, 0x03, 0x12, 0x47, 0x7e, 0x86, 0x23, 0x9f, 0x80, 0xc2, 0x85, 0x3f, 0x40, 0xe2, 0x84, 0xba, 0xe4, 0x19, 0x90, 0x38, 0xf2, 0x32, 0x1c, 0x79, 0x04, 0x14, 0x2e, 0xbc, 0x01, 0x12, 0xa7, 0x55,
0xba, 0x7b, 0x66, 0x6c, 0xc7, 0x8e, 0xb2, 0xb7, 0xae, 0x57, 0xd5, 0x55, 0xaf, 0xab, 0xab, 0xaa, 0x57, 0x77, 0xcf, 0x8c, 0xed, 0xd8, 0x51, 0x72, 0xeb, 0xfa, 0xba, 0xba, 0xea, 0xeb, 0xea, 0xaa,
0x1b, 0x36, 0x26, 0x69, 0x78, 0x21, 0x15, 0x1e, 0x4c, 0xd2, 0x44, 0x25, 0xac, 0x1e, 0xc6, 0x0a, 0xea, 0x82, 0xb5, 0x71, 0x12, 0x9c, 0x0b, 0x89, 0xfb, 0xe3, 0x24, 0x96, 0xb1, 0x57, 0x0b, 0x22,
0xd3, 0x58, 0x46, 0xfc, 0x6b, 0x68, 0xf4, 0xe3, 0x33, 0xbc, 0x1a, 0xa0, 0x92, 0xac, 0x0b, 0xcd, 0x89, 0x49, 0x24, 0x42, 0xf6, 0x0d, 0xd4, 0xfd, 0xe8, 0x04, 0x2f, 0xfb, 0x28, 0x85, 0xd7, 0x81,
0xa3, 0x24, 0x9a, 0x8e, 0xe3, 0xaf, 0xe4, 0x29, 0x46, 0x6d, 0xaf, 0xeb, 0xed, 0x35, 0x44, 0x19, 0x46, 0x37, 0x0e, 0x27, 0xa3, 0xe8, 0x6b, 0x71, 0x8c, 0x61, 0xcb, 0xe9, 0x38, 0xbb, 0x75, 0x5e,
0xd2, 0x16, 0x2f, 0xc2, 0x31, 0x7e, 0x3b, 0x95, 0xb1, 0x9a, 0x8e, 0xdb, 0x15, 0x63, 0x51, 0x82, 0x84, 0x94, 0xc6, 0xcb, 0x60, 0x84, 0xdf, 0x4d, 0x44, 0x24, 0x27, 0xa3, 0x56, 0x49, 0x6b, 0x14,
0xf8, 0x7f, 0x1e, 0x34, 0x9e, 0xa5, 0x72, 0x8c, 0xe4, 0x71, 0x07, 0xea, 0x22, 0xb9, 0x2c, 0xbb, 0x20, 0xf6, 0xbf, 0x03, 0xf5, 0xe7, 0x89, 0x18, 0x21, 0x59, 0xdc, 0x86, 0x1a, 0x8f, 0x2f, 0x8a,
0xcb, 0x65, 0xf6, 0x3e, 0xdc, 0xef, 0xc7, 0x17, 0x98, 0x66, 0x78, 0x1c, 0xcb, 0xd3, 0x08, 0xcf, 0xe6, 0x32, 0xd9, 0x7b, 0x0f, 0xd6, 0xfd, 0xe8, 0x1c, 0x93, 0x14, 0x0f, 0x23, 0x71, 0x1c, 0xe2,
0xc8, 0x5d, 0x5d, 0x2c, 0xa0, 0x6c, 0x17, 0x1a, 0x47, 0x72, 0xf4, 0x1a, 0x5f, 0xcc, 0x26, 0xd8, 0x09, 0x99, 0xab, 0xf1, 0x39, 0xd4, 0xdb, 0x81, 0x7a, 0x57, 0x0c, 0x4f, 0xf1, 0xe5, 0x74, 0x8c,
0xf6, 0xc9, 0x49, 0x01, 0xe4, 0xda, 0x61, 0xf8, 0x13, 0xb6, 0x83, 0xae, 0xb7, 0xb7, 0x21, 0x0a, 0xad, 0x32, 0x19, 0xc9, 0x81, 0x6c, 0x77, 0x10, 0xfc, 0x8c, 0x2d, 0xb7, 0xe3, 0xec, 0xae, 0xf1,
0x60, 0x91, 0x6f, 0x75, 0x89, 0x2f, 0xe3, 0xf0, 0xb6, 0x90, 0xf1, 0xab, 0x9c, 0x43, 0x8d, 0x38, 0x1c, 0x98, 0xe7, 0x5b, 0x59, 0xe0, 0xeb, 0x31, 0xb8, 0xcf, 0x45, 0xf4, 0x3a, 0xe3, 0x50, 0x25,
0xcc, 0x61, 0xec, 0x11, 0xd4, 0x9e, 0x85, 0x18, 0x9d, 0x65, 0xed, 0x7b, 0x5d, 0x7f, 0xaf, 0x79, 0x0e, 0x33, 0x98, 0xf7, 0x08, 0xaa, 0xcf, 0x03, 0x0c, 0x4f, 0xd2, 0xd6, 0xbd, 0x4e, 0x79, 0xb7,
0xb8, 0x79, 0xe0, 0xf2, 0x77, 0x40, 0xb8, 0xb0, 0x6a, 0xce, 0xe1, 0x7e, 0x7f, 0x3c, 0x49, 0x52, 0x71, 0xb0, 0xb1, 0x6f, 0xe3, 0xb7, 0x4f, 0x38, 0x37, 0xdb, 0x8c, 0xc1, 0xba, 0x3f, 0x1a, 0xc7,
0x25, 0x30, 0x9b, 0x24, 0x71, 0x86, 0xac, 0x05, 0xfe, 0x71, 0x9a, 0xda, 0xb3, 0xeb, 0x25, 0xff, 0x89, 0xe4, 0x98, 0x8e, 0xe3, 0x28, 0x45, 0xaf, 0x09, 0xe5, 0xc3, 0x24, 0x31, 0x77, 0x57, 0x4b,
0x19, 0x5a, 0x4f, 0xa3, 0x64, 0x74, 0xde, 0x93, 0x4a, 0x0a, 0xfc, 0x71, 0x8a, 0x99, 0x62, 0xdb, 0xf6, 0x0b, 0x34, 0x9f, 0x85, 0xf1, 0xf0, 0xac, 0x27, 0xa4, 0xe0, 0xf8, 0xd3, 0x04, 0x53, 0xe9,
0x50, 0xa5, 0x5b, 0xb0, 0x76, 0x46, 0xd0, 0x28, 0x65, 0xd2, 0xa6, 0xd9, 0x08, 0x1a, 0xa5, 0xfd, 0x6d, 0x41, 0x85, 0x5e, 0xc1, 0xe8, 0x69, 0x41, 0xa1, 0x14, 0x49, 0x13, 0x66, 0x2d, 0x28, 0x94,
0x94, 0x8a, 0x40, 0x18, 0x41, 0xa3, 0xc3, 0x28, 0x1c, 0x99, 0x14, 0x04, 0xc2, 0x08, 0x8c, 0x41, 0xce, 0x53, 0x28, 0x5c, 0xae, 0x05, 0x85, 0x0e, 0xc2, 0x60, 0xa8, 0x43, 0xe0, 0x72, 0x2d, 0x78,
0xf0, 0x32, 0xc4, 0x4b, 0x7b, 0x6e, 0x5a, 0xf3, 0x3e, 0x6c, 0x95, 0xe2, 0x5b, 0x9a, 0x0f, 0xa0, 0x1e, 0xb8, 0xaf, 0x02, 0xbc, 0x30, 0xf7, 0xa6, 0x35, 0xf3, 0x61, 0xb3, 0xe0, 0xdf, 0xd0, 0x7c,
0x26, 0x92, 0xcb, 0x7e, 0x2f, 0x6b, 0x7b, 0x5d, 0x7f, 0x2f, 0x10, 0x56, 0xa2, 0xec, 0xd2, 0xf5, 0x00, 0x55, 0x1e, 0x5f, 0xf8, 0xbd, 0xb4, 0xe5, 0x74, 0xca, 0xbb, 0x2e, 0x37, 0x12, 0x45, 0x97,
0x6b, 0x55, 0x85, 0x54, 0x05, 0xc0, 0x1f, 0x42, 0x95, 0x52, 0xad, 0x4f, 0x59, 0xec, 0xd5, 0x4b, 0x9e, 0x5f, 0x6d, 0x95, 0x68, 0x2b, 0x07, 0xd8, 0x43, 0xa8, 0x50, 0xa8, 0xd5, 0x2d, 0xf3, 0xb3,
0xfe, 0x9b, 0x07, 0x5b, 0x03, 0x79, 0x45, 0x34, 0xb2, 0x3c, 0xcc, 0x09, 0x34, 0x72, 0x90, 0xac, 0x6a, 0xc9, 0x7e, 0x77, 0x60, 0xb3, 0x2f, 0x2e, 0x89, 0x46, 0x9a, 0xb9, 0x39, 0x82, 0x7a, 0x06,
0x9b, 0x87, 0xfb, 0x45, 0x2e, 0x97, 0xec, 0x0b, 0xe4, 0x38, 0x56, 0xe9, 0x4c, 0x14, 0x9b, 0x77, 0x92, 0x76, 0xe3, 0x60, 0x2f, 0x8f, 0xe5, 0x82, 0x7e, 0x8e, 0x1c, 0x46, 0x32, 0x99, 0xf2, 0xfc,
0x3e, 0x83, 0xfb, 0xf3, 0x4a, 0xcd, 0xe1, 0x1c, 0x67, 0x2e, 0xd3, 0xe7, 0x38, 0xd3, 0x39, 0xb9, 0xf0, 0xf6, 0xe7, 0xb0, 0x3e, 0xbb, 0xa9, 0x38, 0x9c, 0xe1, 0xd4, 0x46, 0xfa, 0x0c, 0xa7, 0x2a,
0x90, 0xd1, 0xd4, 0xe4, 0x2f, 0x10, 0x46, 0xf8, 0xb4, 0xf2, 0xb1, 0xc7, 0xbf, 0x07, 0x76, 0x94, 0x26, 0xe7, 0x22, 0x9c, 0xe8, 0xf8, 0xb9, 0x5c, 0x0b, 0x9f, 0x95, 0x3e, 0x71, 0xd8, 0x0f, 0xe0,
0xa2, 0x54, 0x48, 0x0e, 0x06, 0x98, 0x65, 0xf2, 0x15, 0xae, 0xbe, 0x05, 0x93, 0xd9, 0x4a, 0x39, 0x75, 0x13, 0x14, 0x12, 0xc9, 0x40, 0x1f, 0xd3, 0x54, 0xbc, 0xc6, 0xe5, 0xaf, 0xa0, 0x23, 0x5b,
0xb3, 0xbb, 0xd0, 0xe8, 0x67, 0xb6, 0x50, 0xe9, 0x26, 0xea, 0xa2, 0x00, 0xf8, 0x3e, 0xb0, 0x1e, 0x2a, 0x46, 0x76, 0x07, 0xea, 0x7e, 0x6a, 0x12, 0x95, 0x5e, 0xa2, 0xc6, 0x73, 0x80, 0xed, 0x81,
0x46, 0xa8, 0xd0, 0xf6, 0xd6, 0x1a, 0xff, 0x7c, 0xe8, 0xb8, 0xdc, 0x6e, 0xcb, 0x1e, 0x41, 0xa0, 0xd7, 0xc3, 0x10, 0x25, 0x9a, 0xda, 0x5a, 0x61, 0x9f, 0x0d, 0x2c, 0x97, 0x9b, 0x75, 0xbd, 0x47,
0xdb, 0x8a, 0xa8, 0x34, 0x0f, 0xdf, 0x29, 0x52, 0x97, 0xf7, 0xb0, 0x20, 0x03, 0x1e, 0x3a, 0xa7, 0xe0, 0xaa, 0xb2, 0x22, 0x2a, 0x8d, 0x83, 0xb7, 0xf3, 0xd0, 0x65, 0x35, 0xcc, 0x49, 0x81, 0x05,
0xb6, 0x15, 0x6f, 0x39, 0xe0, 0x0d, 0x65, 0xe6, 0x42, 0xf9, 0x8b, 0xa1, 0xf2, 0xe6, 0xb6, 0xa1, 0xd6, 0xa8, 0x29, 0xc5, 0x1b, 0x2e, 0x78, 0x4d, 0x9a, 0x59, 0x57, 0xe5, 0x79, 0x57, 0x59, 0x71,
0x3e, 0x77, 0x67, 0x7d, 0xd3, 0x50, 0xbc, 0x67, 0x51, 0x5d, 0xae, 0xcf, 0xb5, 0xd6, 0xec, 0xa1, 0x1b, 0x57, 0x5f, 0xda, 0xbb, 0xde, 0xd5, 0x15, 0xeb, 0x19, 0x54, 0xa5, 0xeb, 0x0b, 0xb5, 0xab,
0xf5, 0xea, 0x23, 0x2f, 0xf2, 0xf8, 0xc7, 0xb3, 0x21, 0xef, 0xe6, 0x66, 0x21, 0x73, 0x7a, 0x62, 0xcf, 0xd0, 0x7a, 0xf9, 0x95, 0xe7, 0x79, 0xfc, 0xeb, 0x18, 0x97, 0xb7, 0x33, 0x33, 0x17, 0x39,
0xb9, 0xc2, 0xb2, 0x1d, 0x96, 0xcb, 0x34, 0x07, 0x74, 0xd4, 0xac, 0x1d, 0x2c, 0xcd, 0x01, 0x8d, 0xd5, 0xb1, 0x6c, 0x62, 0x99, 0x0a, 0xcb, 0x64, 0xea, 0x03, 0xca, 0x6b, 0xda, 0x72, 0x17, 0xfa,
0x0b, 0xab, 0xd6, 0xed, 0x64, 0x8b, 0xbc, 0x6a, 0xda, 0xc9, 0x48, 0xec, 0x18, 0x5a, 0xfd, 0x78, 0x80, 0xc2, 0xb9, 0xd9, 0x56, 0xe5, 0x64, 0x92, 0xbc, 0xa2, 0xcb, 0x49, 0x4b, 0xde, 0x21, 0x34,
0x32, 0x55, 0x3d, 0xfc, 0x21, 0x8c, 0x43, 0x15, 0x26, 0x71, 0xd6, 0xae, 0x91, 0xab, 0x87, 0x65, 0xfd, 0x68, 0x3c, 0x91, 0x3d, 0xfc, 0x31, 0x88, 0x02, 0x19, 0xc4, 0x51, 0xda, 0xaa, 0x92, 0xa9,
0x46, 0x73, 0x16, 0x62, 0x69, 0x0b, 0xff, 0xc5, 0x83, 0xcd, 0x05, 0x70, 0xc5, 0xa1, 0x1d, 0xdf, 0x87, 0x45, 0x46, 0x33, 0x1a, 0x7c, 0xe1, 0x08, 0xfb, 0xd5, 0x81, 0x8d, 0x39, 0x70, 0xc9, 0xa5,
0xca, 0x7a, 0xbe, 0x8f, 0xf3, 0x01, 0xe7, 0x93, 0x61, 0x67, 0x25, 0x9b, 0xf9, 0x79, 0xf7, 0xbb, 0x2d, 0xdf, 0xd2, 0x6a, 0xbe, 0x8f, 0xb3, 0x06, 0x57, 0x26, 0xc5, 0xf6, 0x52, 0x36, 0xb3, 0xfd,
0x07, 0xdb, 0x37, 0x19, 0xdc, 0xc8, 0xa6, 0x03, 0xf0, 0x4d, 0x1a, 0x8e, 0x65, 0x3a, 0xfb, 0x12, 0xee, 0x0f, 0x07, 0xb6, 0xae, 0x53, 0xb8, 0x96, 0x4d, 0x1b, 0xe0, 0xdb, 0x24, 0x18, 0x89, 0x64,
0x67, 0x76, 0xd6, 0x97, 0x10, 0xf6, 0x1d, 0x3c, 0x58, 0xf0, 0xf5, 0xc5, 0xc8, 0xa4, 0xc8, 0x90, 0xfa, 0x15, 0x4e, 0x4d, 0xaf, 0x2f, 0x20, 0xde, 0xf7, 0xf0, 0x60, 0xce, 0xd6, 0xd3, 0xa1, 0x0e,
0x7a, 0x6f, 0x25, 0x29, 0x63, 0x27, 0x56, 0x6c, 0xe7, 0xff, 0x7a, 0xf0, 0xee, 0x8d, 0xaa, 0xa2, 0x91, 0x26, 0xf5, 0xee, 0x52, 0x52, 0x5a, 0x8f, 0x2f, 0x39, 0xce, 0xfe, 0x73, 0xe0, 0x9d, 0x6b,
0x1e, 0xbd, 0x72, 0xe9, 0xef, 0x43, 0xeb, 0xa5, 0x1e, 0x15, 0x3d, 0xcc, 0x54, 0x18, 0x4b, 0x6d, 0xb7, 0xf2, 0x7c, 0x74, 0x8a, 0xa9, 0xbf, 0x07, 0xcd, 0x57, 0xaa, 0x55, 0xf4, 0x30, 0x95, 0x41,
0x69, 0x0b, 0x76, 0x09, 0x67, 0x7d, 0xa8, 0x13, 0x36, 0x90, 0x13, 0x4b, 0xf3, 0xc3, 0x5b, 0x68, 0x24, 0x94, 0xa6, 0x49, 0xd8, 0x05, 0xdc, 0xf3, 0xa1, 0x46, 0x58, 0x5f, 0x8c, 0x0d, 0xcd, 0x0f,
0x1e, 0x38, 0x7b, 0x33, 0xd3, 0xf2, 0xed, 0x9a, 0x0c, 0x4d, 0x5d, 0x37, 0xc2, 0x49, 0xd8, 0x79, 0x6f, 0xa0, 0xb9, 0x6f, 0xf5, 0x75, 0x4f, 0xcb, 0x8e, 0x2b, 0x32, 0xd4, 0x75, 0x6d, 0x0b, 0x27,
0x02, 0x1b, 0x73, 0x1b, 0xee, 0x34, 0xe7, 0x12, 0xd8, 0x75, 0xb3, 0x65, 0x8e, 0xc9, 0xfa, 0x2e, 0x61, 0xfb, 0x09, 0xac, 0xcd, 0x1c, 0xb8, 0x55, 0x9f, 0x8b, 0x61, 0xc7, 0xf6, 0x96, 0x19, 0x26,
0xfd, 0x04, 0xa0, 0x30, 0xb5, 0x03, 0x60, 0x4d, 0x7d, 0x96, 0x8c, 0xf9, 0x09, 0xec, 0xba, 0xc1, 0xab, 0xab, 0xf4, 0x53, 0x80, 0x5c, 0xd5, 0x34, 0x80, 0x15, 0xf9, 0x59, 0x50, 0x66, 0x47, 0xb0,
0x77, 0x87, 0x80, 0xae, 0x5a, 0x2a, 0x45, 0xb5, 0xf0, 0x19, 0xc0, 0xf3, 0xe4, 0x0c, 0x87, 0x4a, 0x63, 0x1b, 0xdf, 0x2d, 0x1c, 0xda, 0x6c, 0x29, 0xe5, 0xd9, 0xc2, 0xa6, 0x00, 0x2f, 0xe2, 0x13,
0xaa, 0x69, 0xa6, 0x2d, 0x4e, 0x92, 0x4c, 0xb9, 0x7a, 0xd2, 0x6b, 0x1a, 0xcc, 0x4a, 0xaa, 0x7c, 0x1c, 0x48, 0x21, 0x27, 0xa9, 0xd2, 0x38, 0x8a, 0x53, 0x69, 0xf3, 0x49, 0xad, 0xa9, 0x31, 0x4b,
0x98, 0x90, 0xc0, 0x3e, 0x80, 0x7b, 0xe4, 0x14, 0x5d, 0xd9, 0x6c, 0x2e, 0xf4, 0xba, 0x70, 0x7a, 0x21, 0xb3, 0x66, 0x42, 0x82, 0xf7, 0x3e, 0xdc, 0x23, 0xa3, 0x68, 0xd3, 0x66, 0x63, 0xae, 0xd6,
0xea, 0xd2, 0xd1, 0x6b, 0x1c, 0x9b, 0x47, 0xb3, 0x21, 0xac, 0xc4, 0x9f, 0xc0, 0xc6, 0x51, 0x34, 0xb9, 0xdd, 0xa7, 0x2a, 0x1d, 0x9e, 0xe2, 0x48, 0x7f, 0x9a, 0x75, 0x6e, 0x24, 0xf6, 0x04, 0xd6,
0xcd, 0x14, 0xa6, 0x36, 0xfa, 0x3e, 0x54, 0x35, 0x17, 0xf7, 0x64, 0x6d, 0x17, 0x1e, 0x0b, 0x8a, 0xba, 0xe1, 0x24, 0x95, 0x98, 0x18, 0xef, 0x7b, 0x50, 0x51, 0x5c, 0xec, 0x97, 0xb5, 0x95, 0x5b,
0xc2, 0x98, 0xf0, 0xc7, 0xd0, 0xa4, 0x2a, 0x22, 0x5f, 0xb2, 0xf4, 0x75, 0xf0, 0xd6, 0x7f, 0x1d, 0xcc, 0x29, 0x72, 0xad, 0xc2, 0x1e, 0x43, 0x83, 0xb2, 0x88, 0x6c, 0x89, 0xc2, 0xe8, 0xe0, 0xac,
0x86, 0x50, 0x5d, 0xdd, 0x3a, 0x0c, 0x02, 0xfa, 0xfd, 0xd8, 0x04, 0xd1, 0xc7, 0xa7, 0x05, 0xfe, 0x1e, 0x1d, 0x06, 0x50, 0x59, 0x5e, 0x3a, 0x1e, 0xb8, 0x34, 0xfd, 0x98, 0x00, 0xd1, 0xe0, 0xd3,
0x20, 0x34, 0xd7, 0xe3, 0x0b, 0xbd, 0x24, 0x44, 0x5e, 0xd1, 0x61, 0x34, 0x22, 0xf5, 0xdb, 0xb2, 0x84, 0x72, 0x3f, 0xd0, 0xcf, 0x53, 0xe6, 0x6a, 0x49, 0x88, 0xb8, 0xa4, 0xcb, 0x28, 0x44, 0xa8,
0x65, 0xae, 0x43, 0xbf, 0xfc, 0x6f, 0xf2, 0x0a, 0xb8, 0x0f, 0x84, 0x5f, 0x7c, 0x20, 0x9e, 0xb6, 0xbf, 0x65, 0x53, 0x3f, 0x87, 0xfa, 0xf9, 0xef, 0xf2, 0x0b, 0xd8, 0x01, 0xa2, 0x5c, 0x18, 0x20,
0xfe, 0xb8, 0xee, 0x78, 0x7f, 0x5e, 0x77, 0xbc, 0xbf, 0xae, 0x3b, 0xde, 0xaf, 0x7f, 0x77, 0xde, 0x3e, 0x86, 0xfa, 0x53, 0x29, 0x13, 0x3d, 0x77, 0xac, 0x43, 0xc9, 0xef, 0x91, 0x25, 0x97, 0x97,
0x3a, 0xad, 0xd1, 0xaf, 0xf2, 0xa3, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x47, 0xdd, 0xdd, 0x8e, 0xfc, 0x9e, 0x6a, 0x9f, 0xdd, 0x53, 0x1c, 0x9e, 0xa5, 0x66, 0x3a, 0xbc, 0xcf, 0x33, 0x99, 0x7d,
0x66, 0x0a, 0x00, 0x00, 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,
} }

View file

@ -139,3 +139,13 @@ message DeleteViewMessage {
string Frame = 2; string Frame = 2;
string View = 3; 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;
}

View file

@ -20,6 +20,7 @@
QueryResult QueryResult
ImportRequest ImportRequest
ImportValueRequest ImportValueRequest
AttrBlockResponse
*/ */
package internal package internal
@ -490,6 +491,22 @@ func (m *ImportValueRequest) GetValues() []int64 {
return nil 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() { func init() {
proto.RegisterType((*Bitmap)(nil), "internal.Bitmap") proto.RegisterType((*Bitmap)(nil), "internal.Bitmap")
proto.RegisterType((*Pair)(nil), "internal.Pair") proto.RegisterType((*Pair)(nil), "internal.Pair")
@ -503,6 +520,7 @@ func init() {
proto.RegisterType((*QueryResult)(nil), "internal.QueryResult") proto.RegisterType((*QueryResult)(nil), "internal.QueryResult")
proto.RegisterType((*ImportRequest)(nil), "internal.ImportRequest") proto.RegisterType((*ImportRequest)(nil), "internal.ImportRequest")
proto.RegisterType((*ImportValueRequest)(nil), "internal.ImportValueRequest") proto.RegisterType((*ImportValueRequest)(nil), "internal.ImportValueRequest")
proto.RegisterType((*AttrBlockResponse)(nil), "internal.AttrBlockResponse")
} }
func (m *Bitmap) Marshal() (dAtA []byte, err error) { func (m *Bitmap) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
@ -1118,6 +1136,51 @@ func (m *ImportValueRequest) MarshalTo(dAtA []byte) (int, error) {
return i, nil 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 { func encodeVarintPublic(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 { for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80) dAtA[offset] = uint8(v&0x7f | 0x80)
@ -1388,6 +1451,25 @@ func (m *ImportValueRequest) Size() (n int) {
return n 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) { func sovPublic(x uint64) (n int) {
for { for {
n++ n++
@ -3326,6 +3408,168 @@ func (m *ImportValueRequest) Unmarshal(dAtA []byte) error {
} }
return nil 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) { func skipPublic(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0
@ -3434,46 +3678,50 @@ var (
func init() { proto.RegisterFile("public.proto", fileDescriptorPublic) } func init() { proto.RegisterFile("public.proto", fileDescriptorPublic) }
var fileDescriptorPublic = []byte{ var fileDescriptorPublic = []byte{
// 651 bytes of a gzipped FileDescriptorProto // 720 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcb, 0x6e, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcb, 0x6e, 0xd3, 0x40,
0x14, 0x65, 0x62, 0xe7, 0x75, 0x93, 0x56, 0xd5, 0x08, 0x8a, 0x85, 0x50, 0x14, 0x59, 0x2c, 0xbc, 0x14, 0x65, 0x62, 0xe7, 0x75, 0x93, 0x56, 0xed, 0x08, 0x8a, 0x55, 0xa1, 0x28, 0xb2, 0x10, 0x64,
0x4a, 0xa5, 0xf0, 0x01, 0x08, 0xb7, 0xa9, 0x64, 0x21, 0x2a, 0x98, 0x14, 0xf6, 0x6e, 0x3b, 0x2a, 0x95, 0x4a, 0x61, 0x83, 0x10, 0x12, 0x22, 0x6d, 0x2a, 0x45, 0x55, 0x2b, 0x98, 0x14, 0xf6, 0x6e,
0x96, 0xfc, 0x62, 0x3c, 0x16, 0xed, 0x77, 0xb0, 0x61, 0xcd, 0x06, 0x7e, 0x80, 0x1d, 0x1f, 0xc0, 0x3a, 0x2a, 0x56, 0xfd, 0xc2, 0x1e, 0x43, 0xf3, 0x1d, 0x6c, 0x58, 0xb1, 0x60, 0x03, 0x3f, 0xc0,
0x92, 0x4f, 0x40, 0xe1, 0x47, 0xd0, 0xbd, 0xe3, 0x89, 0x1d, 0x16, 0xc0, 0x82, 0xdd, 0x9c, 0x73, 0x8e, 0x0f, 0x60, 0xc9, 0x27, 0xa0, 0xf2, 0x23, 0xe8, 0xde, 0xf1, 0xc4, 0x36, 0x0b, 0x60, 0xc1,
0x1f, 0xbe, 0x8f, 0x73, 0x0d, 0xd3, 0xb2, 0xbe, 0x48, 0x93, 0xcb, 0x45, 0xa9, 0x0a, 0x5d, 0xf0, 0x6e, 0xce, 0xb9, 0x0f, 0xdf, 0xc7, 0xb9, 0x09, 0xf4, 0x93, 0xfc, 0x2c, 0xf0, 0x97, 0xe3, 0x24,
0x51, 0x92, 0x6b, 0xa9, 0xf2, 0x38, 0xf5, 0x43, 0x18, 0x84, 0x89, 0xce, 0xe2, 0x92, 0x73, 0x70, 0x8d, 0x55, 0xcc, 0x3b, 0x7e, 0xa4, 0x64, 0x1a, 0x79, 0x81, 0x3b, 0x85, 0xd6, 0xd4, 0x57, 0xa1,
0xc3, 0x44, 0x57, 0x1e, 0x9b, 0x3b, 0x81, 0x2b, 0xe8, 0xcd, 0x1f, 0x41, 0xff, 0xa9, 0xd6, 0xaa, 0x97, 0x70, 0x0e, 0xf6, 0xd4, 0x57, 0x99, 0xc3, 0x86, 0xd6, 0xc8, 0x16, 0xf4, 0xe6, 0x77, 0xa1,
0xf2, 0x7a, 0x73, 0x27, 0x98, 0x2c, 0xf7, 0x17, 0x36, 0x6e, 0x81, 0xb4, 0x30, 0x46, 0x7f, 0x01, 0xf9, 0x54, 0xa9, 0x34, 0x73, 0x1a, 0x43, 0x6b, 0xd4, 0x9b, 0x6c, 0x8e, 0x4d, 0xdc, 0x18, 0x69,
0xee, 0x8b, 0x38, 0x51, 0xfc, 0x00, 0x9c, 0x67, 0xf2, 0xd6, 0x63, 0x73, 0x16, 0xb8, 0x02, 0x9f, 0xa1, 0x8d, 0xee, 0x18, 0xec, 0x67, 0x9e, 0x9f, 0xf2, 0x2d, 0xb0, 0x8e, 0xe4, 0xca, 0x61, 0x43,
0xfc, 0x2e, 0xf4, 0x8f, 0x8b, 0x3a, 0xd7, 0x5e, 0x8f, 0x38, 0x03, 0xfc, 0x25, 0x8c, 0xd6, 0x75, 0x36, 0xb2, 0x05, 0x3e, 0xf9, 0x4d, 0x68, 0xee, 0xc7, 0x79, 0xa4, 0x9c, 0x06, 0x71, 0x1a, 0xb8,
0x46, 0x6f, 0x8c, 0x59, 0xd7, 0x19, 0xc5, 0x38, 0x02, 0x9f, 0xbb, 0x31, 0x8e, 0x8d, 0x79, 0x05, 0x13, 0xe8, 0x2c, 0xf2, 0x90, 0xde, 0x18, 0xb3, 0xc8, 0x43, 0x8a, 0xb1, 0x04, 0x3e, 0xeb, 0x31,
0x4e, 0x98, 0x68, 0x34, 0x8a, 0xe2, 0x5d, 0x74, 0xd2, 0x7c, 0xc4, 0x00, 0xfe, 0x00, 0x46, 0xc7, 0x96, 0x89, 0x79, 0x01, 0xd6, 0xd4, 0x57, 0x68, 0x14, 0xf1, 0xdb, 0xf9, 0x41, 0xf1, 0x11, 0x0d,
0x45, 0x5a, 0x67, 0x79, 0x74, 0xd2, 0x7c, 0x69, 0x8b, 0xf9, 0x43, 0x18, 0x9f, 0x27, 0x99, 0xac, 0xf8, 0x2e, 0x74, 0xf6, 0xe3, 0x20, 0x0f, 0xa3, 0xf9, 0x41, 0xf1, 0xa5, 0x35, 0xe6, 0x77, 0xa0,
0x74, 0x9c, 0x95, 0x9e, 0x43, 0x29, 0x5b, 0xc2, 0x5f, 0xc1, 0x9e, 0xf1, 0xc4, 0x4e, 0xd6, 0x52, 0x7b, 0xea, 0x87, 0x32, 0x53, 0x5e, 0x98, 0x38, 0x16, 0xa5, 0x2c, 0x09, 0x77, 0x06, 0x1b, 0xda,
0xf3, 0x7d, 0xe8, 0x6d, 0xb3, 0xf7, 0xa2, 0x93, 0x7f, 0x9c, 0xc0, 0x67, 0x06, 0x2e, 0xbe, 0xba, 0x13, 0x3b, 0x59, 0x48, 0xc5, 0x37, 0xa1, 0xb1, 0xce, 0xde, 0x98, 0x1f, 0xfc, 0xe3, 0x04, 0x3e,
0x23, 0x18, 0x9b, 0x11, 0x70, 0x70, 0xcf, 0x6f, 0x4b, 0xd9, 0xd4, 0x45, 0x6f, 0x3e, 0x87, 0xc9, 0x33, 0xb0, 0xf1, 0x55, 0x1d, 0x41, 0x57, 0x8f, 0x80, 0x83, 0x7d, 0xba, 0x4a, 0x64, 0x51, 0x17,
0x5a, 0xab, 0x24, 0xbf, 0x7e, 0x1d, 0xa7, 0xb5, 0xa4, 0xaa, 0xc6, 0xa2, 0x4b, 0x61, 0x47, 0x51, 0xbd, 0xf9, 0x10, 0x7a, 0x0b, 0x95, 0xfa, 0xd1, 0xc5, 0x4b, 0x2f, 0xc8, 0x25, 0x55, 0xd5, 0x15,
0xae, 0x8d, 0xd9, 0xa5, 0xa2, 0xb7, 0x18, 0x3b, 0x0a, 0x8b, 0x22, 0x35, 0xc6, 0xfe, 0x9c, 0x05, 0x55, 0x0a, 0x3b, 0x9a, 0x47, 0x4a, 0x9b, 0x6d, 0x2a, 0x7a, 0x8d, 0xb1, 0xa3, 0x69, 0x1c, 0x07,
0x23, 0xd1, 0x12, 0x7c, 0x06, 0x70, 0x9a, 0x16, 0x71, 0x13, 0x3b, 0x98, 0xb3, 0x80, 0x89, 0x0e, 0xda, 0xd8, 0x1c, 0xb2, 0x51, 0x47, 0x94, 0x04, 0x1f, 0x00, 0x1c, 0x06, 0xb1, 0x57, 0xc4, 0xb6,
0xe3, 0x1f, 0xc1, 0x10, 0x2b, 0x7d, 0x1e, 0x97, 0x6d, 0x6f, 0xec, 0x4f, 0xbd, 0x7d, 0x65, 0x30, 0x86, 0x6c, 0xc4, 0x44, 0x85, 0x71, 0xf7, 0xa0, 0x8d, 0x95, 0x1e, 0x7b, 0x49, 0xd9, 0x1b, 0xfb,
0x7d, 0x59, 0x4b, 0x75, 0x2b, 0xe4, 0xdb, 0x5a, 0x56, 0xb4, 0x03, 0xc2, 0x4d, 0x97, 0x06, 0xf0, 0x53, 0x6f, 0x5f, 0x19, 0xf4, 0x9f, 0xe7, 0x32, 0x5d, 0x09, 0xf9, 0x3a, 0x97, 0x19, 0xed, 0x80,
0x43, 0x18, 0xac, 0xd3, 0xe4, 0x52, 0x9a, 0x49, 0xb9, 0xa2, 0x41, 0xd8, 0x6b, 0x3b, 0xe1, 0x8a, 0x70, 0xd1, 0xa5, 0x06, 0x7c, 0x07, 0x5a, 0x8b, 0xc0, 0x5f, 0x4a, 0x3d, 0x29, 0x5b, 0x14, 0x08,
0x7a, 0x1d, 0x89, 0x2e, 0x85, 0x91, 0x42, 0x66, 0x85, 0xb6, 0xcd, 0x34, 0x88, 0xfb, 0x30, 0x5d, 0x7b, 0x2d, 0x27, 0x9c, 0x51, 0xaf, 0x1d, 0x51, 0xa5, 0x30, 0x52, 0xc8, 0x30, 0x56, 0xa6, 0x99,
0xdd, 0x5c, 0xa6, 0xf5, 0x95, 0x34, 0xa1, 0x03, 0xb2, 0xee, 0x70, 0x98, 0xbd, 0xc1, 0xa4, 0xdd, 0x02, 0x71, 0x17, 0xfa, 0xb3, 0xab, 0x65, 0x90, 0x9f, 0x4b, 0x1d, 0xda, 0x22, 0x6b, 0x8d, 0xc3,
0xa1, 0xc9, 0xde, 0xa1, 0xfc, 0xf7, 0x0c, 0xf6, 0x9a, 0xf2, 0xab, 0xb2, 0xc8, 0x2b, 0x89, 0x3b, 0xec, 0x05, 0x26, 0xed, 0xb6, 0x75, 0xf6, 0x0a, 0xe5, 0xbe, 0x63, 0xb0, 0x51, 0x94, 0x9f, 0x25,
0x5a, 0x29, 0x65, 0x77, 0xb4, 0x52, 0x8a, 0x1f, 0xc1, 0x50, 0xc8, 0xaa, 0x4e, 0xb5, 0x5d, 0xf3, 0x71, 0x94, 0x49, 0xdc, 0xd1, 0x2c, 0x4d, 0xcd, 0x8e, 0x66, 0x69, 0xca, 0xf7, 0xa0, 0x2d, 0x64,
0xbd, 0x76, 0x14, 0x36, 0xb6, 0x4e, 0xb5, 0xb0, 0x5e, 0xfc, 0x09, 0xec, 0xef, 0xc8, 0x06, 0xfb, 0x96, 0x07, 0xca, 0xac, 0xf9, 0x56, 0x39, 0x0a, 0x13, 0x9b, 0x07, 0x4a, 0x18, 0x2f, 0xfe, 0x04,
0xc2, 0xb8, 0xfb, 0x6d, 0xdc, 0x8e, 0x5d, 0xfc, 0xe6, 0xee, 0x7f, 0x61, 0x30, 0xe9, 0x64, 0xe6, 0x36, 0x6b, 0xb2, 0xc1, 0xbe, 0x30, 0xee, 0x76, 0x19, 0x57, 0xb3, 0x8b, 0xdf, 0xdc, 0xdd, 0x2f,
0x81, 0x3d, 0x43, 0x2a, 0x6b, 0xb2, 0x3c, 0x68, 0x13, 0x19, 0x5e, 0xd8, 0x33, 0x9d, 0x02, 0x3b, 0x0c, 0x7a, 0x95, 0xcc, 0x7c, 0x64, 0xce, 0x90, 0xca, 0xea, 0x4d, 0xb6, 0xca, 0x44, 0x9a, 0x17,
0x6b, 0xc4, 0xc4, 0xce, 0x70, 0x85, 0x78, 0x7a, 0xf6, 0xfb, 0x9d, 0x15, 0x22, 0x2d, 0x8c, 0x91, 0xe6, 0x4c, 0xfb, 0xc0, 0x4e, 0x0a, 0x31, 0xb1, 0x13, 0x5c, 0x21, 0x9e, 0x9e, 0xf9, 0x7e, 0x65,
0x7b, 0x30, 0x3c, 0x7e, 0x13, 0xe7, 0xd7, 0xf2, 0x8a, 0xc4, 0x34, 0x12, 0x16, 0xf2, 0x45, 0x7b, 0x85, 0x48, 0x0b, 0x6d, 0xe4, 0x0e, 0xb4, 0xf7, 0x5f, 0x79, 0xd1, 0x85, 0x3c, 0x27, 0x31, 0x75,
0x8a, 0x34, 0xfd, 0xc9, 0x92, 0xb7, 0x29, 0xac, 0x45, 0x6c, 0x7d, 0xfc, 0x4f, 0x0c, 0xf6, 0xa2, 0x84, 0x81, 0x7c, 0x5c, 0x9e, 0x22, 0x4d, 0xbf, 0x37, 0xe1, 0x65, 0x0a, 0x63, 0x11, 0x6b, 0x1f,
0xac, 0x2c, 0x94, 0xee, 0xa8, 0x21, 0xca, 0xaf, 0xe4, 0x8d, 0x55, 0x03, 0x01, 0x64, 0x4f, 0x55, 0xf7, 0x13, 0x83, 0x8d, 0x79, 0x98, 0xc4, 0xa9, 0xaa, 0xa8, 0x61, 0x1e, 0x9d, 0xcb, 0x2b, 0xa3,
0x9c, 0x19, 0xd9, 0x8f, 0x85, 0x01, 0xc8, 0x92, 0x2a, 0x48, 0x05, 0xae, 0x30, 0x80, 0xf6, 0x8f, 0x06, 0x02, 0xc8, 0x1e, 0xa6, 0x5e, 0xa8, 0x65, 0xdf, 0x15, 0x1a, 0x20, 0x4b, 0xaa, 0x20, 0x15,
0x67, 0x5c, 0x79, 0xae, 0x51, 0x8e, 0x41, 0xa8, 0x73, 0x7b, 0xc5, 0x95, 0xd7, 0x27, 0x53, 0x4b, 0xd8, 0x42, 0x03, 0xda, 0x3f, 0x9e, 0x71, 0xe6, 0xd8, 0x5a, 0x39, 0x1a, 0xa1, 0xce, 0xcd, 0x15,
0xa0, 0xce, 0xb7, 0x67, 0x8c, 0xda, 0x70, 0x02, 0x47, 0x74, 0x18, 0xff, 0x23, 0x03, 0x6e, 0x2a, 0x67, 0x4e, 0x93, 0x4c, 0x25, 0x81, 0x3a, 0x5f, 0x9f, 0x31, 0x6a, 0xc3, 0x1a, 0x59, 0xa2, 0xc2,
0x25, 0xdd, 0xff, 0xbf, 0x72, 0xd1, 0x37, 0x91, 0xa9, 0x19, 0x25, 0xfa, 0x22, 0xf8, 0x4b, 0xb1, 0xb8, 0x1f, 0x19, 0x70, 0x5d, 0x29, 0xe9, 0xfe, 0xff, 0x95, 0x8b, 0xbe, 0xbe, 0x0c, 0xf4, 0x28,
0x87, 0x30, 0xa0, 0x2a, 0x6c, 0xa1, 0x0d, 0x0a, 0x0f, 0xbe, 0x6d, 0x66, 0xec, 0xfb, 0x66, 0xc6, 0xd1, 0x17, 0xc1, 0x5f, 0x8a, 0xdd, 0x81, 0x16, 0x55, 0x61, 0x0a, 0x2d, 0x90, 0xfb, 0x81, 0xc1,
0x7e, 0x6c, 0x66, 0xec, 0xc3, 0xcf, 0xd9, 0x9d, 0x8b, 0x01, 0xfd, 0xa0, 0x1f, 0xff, 0x0a, 0x00, 0x36, 0x6a, 0x62, 0x1a, 0xc4, 0xcb, 0xcb, 0xb5, 0x40, 0x1f, 0xd7, 0xef, 0xf2, 0x5e, 0xfd, 0x2e,
0x00, 0xff, 0xff, 0x4d, 0x1e, 0xdf, 0xba, 0xb0, 0x05, 0x00, 0x00, 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,
} }

View file

@ -81,3 +81,7 @@ message ImportValueRequest {
repeated uint64 ColumnIDs = 5; repeated uint64 ColumnIDs = 5;
repeated int64 Values = 6; repeated int64 Values = 6;
} }
message AttrBlockResponse {
map<uint64, AttrMap> Attrs = 1;
}

View file

@ -665,13 +665,19 @@ func (b *Bitmap) UnmarshalBinary(data []byte) error {
c := b.containers[i] c := b.containers[i]
switch c.container_type { switch c.container_type {
case ContainerRun: case ContainerRun:
c.array = nil
c.bitmap = nil
runCount := binary.LittleEndian.Uint16(data[offset : offset+runCountHeaderSize]) runCount := binary.LittleEndian.Uint16(data[offset : offset+runCountHeaderSize])
c.runs = (*[0xFFFFFFF]interval16)(unsafe.Pointer(&data[offset+runCountHeaderSize]))[:runCount] c.runs = (*[0xFFFFFFF]interval16)(unsafe.Pointer(&data[offset+runCountHeaderSize]))[:runCount]
opsOffset = int(offset) + runCountHeaderSize + len(c.runs)*interval16Size opsOffset = int(offset) + runCountHeaderSize + len(c.runs)*interval16Size
case ContainerArray: case ContainerArray:
c.runs = nil
c.bitmap = nil
c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[offset]))[:c.n] c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[offset]))[:c.n]
opsOffset = int(offset) + len(c.array)*2 // sizeof(uint32) opsOffset = int(offset) + len(c.array)*2 // sizeof(uint32)
case ContainerBitmap: case ContainerBitmap:
c.array = nil
c.runs = nil
c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[offset]))[:bitmapN] c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[offset]))[:bitmapN]
opsOffset = int(offset) + len(c.bitmap)*8 // sizeof(uint64) opsOffset = int(offset) + len(c.bitmap)*8 // sizeof(uint64)
} }
@ -808,6 +814,10 @@ func (itr *Iterator) eof() bool { return int(itr.i) >= len(itr.bitmap.containers
// Seek moves to the first value equal to or greater than `seek`. // Seek moves to the first value equal to or greater than `seek`.
func (itr *Iterator) Seek(seek uint64) { func (itr *Iterator) Seek(seek uint64) {
// k should always be -1 unless we're seeking into a run container. Then the
// "if c.isRun" section will take care of it.
itr.k = -1
// Move to the correct container. // Move to the correct container.
itr.i = search64(itr.bitmap.keys, highbits(seek)) itr.i = search64(itr.bitmap.keys, highbits(seek))
if itr.i < 0 { if itr.i < 0 {
@ -1019,17 +1029,16 @@ func (c *container) unmap() {
return return
} }
if c.array != nil { switch c.container_type {
case ContainerArray:
tmp := make([]uint16, len(c.array)) tmp := make([]uint16, len(c.array))
copy(tmp, c.array) copy(tmp, c.array)
c.array = tmp c.array = tmp
} case ContainerBitmap:
if c.bitmap != nil {
tmp := make([]uint64, len(c.bitmap)) tmp := make([]uint64, len(c.bitmap))
copy(tmp, c.bitmap) copy(tmp, c.bitmap)
c.bitmap = tmp c.bitmap = tmp
} case ContainerRun:
if c.runs != nil {
tmp := make([]interval16, len(c.runs)) tmp := make([]interval16, len(c.runs))
copy(tmp, c.runs) copy(tmp, c.runs)
c.runs = tmp c.runs = tmp
@ -1614,21 +1623,17 @@ func (c *container) runToArray() {
func (c *container) clone() *container { func (c *container) clone() *container {
other := &container{n: c.n, container_type: c.container_type} 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)) other.array = make([]uint16, len(c.array))
copy(other.array, c.array) copy(other.array, c.array)
} case ContainerBitmap:
if c.bitmap != nil {
other.bitmap = make([]uint64, len(c.bitmap)) other.bitmap = make([]uint64, len(c.bitmap))
copy(other.bitmap, c.bitmap) copy(other.bitmap, c.bitmap)
} case ContainerRun:
if c.runs != nil {
other.runs = make([]interval16, len(c.runs)) other.runs = make([]interval16, len(c.runs))
copy(other.runs, c.runs) copy(other.runs, c.runs)
} }
return other return other
} }
@ -2467,6 +2472,8 @@ func differenceRunArray(a, b *container) *container {
bidx := 0 bidx := 0
vb := b.array[bidx] vb := b.array[bidx]
RUNLOOP:
for _, run := range a.runs { for _, run := range a.runs {
start := run.start start := run.start
for vb < run.start { for vb < run.start {
@ -2478,6 +2485,9 @@ func differenceRunArray(a, b *container) *container {
} }
for vb >= run.start && vb <= run.last { for vb >= run.start && vb <= run.last {
if vb == start { if vb == start {
if vb == 65535 { // overflow
break RUNLOOP
}
start++ start++
bidx++ bidx++
if bidx >= len(b.array) { if bidx >= len(b.array) {
@ -2488,6 +2498,9 @@ func differenceRunArray(a, b *container) *container {
} }
output.runs = append(output.runs, interval16{start: start, last: vb - 1}) output.runs = append(output.runs, interval16{start: start, last: vb - 1})
output.n += int(vb - start) output.n += int(vb - start)
if vb == 65535 { // overflow
break RUNLOOP
}
start = vb + 1 start = vb + 1
bidx++ bidx++
if bidx >= len(b.array) { if bidx >= len(b.array) {

View file

@ -347,8 +347,8 @@ func TestRunMax(t *testing.T) {
} }
func TestIntersectionCountArrayRun(t *testing.T) { func TestIntersectionCountArrayRun(t *testing.T) {
a := &container{array: []uint16{1, 5, 10, 11, 12}} a := &container{container_type: ContainerArray, array: []uint16{1, 5, 10, 11, 12}}
b := &container{runs: []interval16{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}} b := &container{container_type: ContainerRun, runs: []interval16{{start: 2, last: 10}, {start: 12, last: 13}, {start: 15, last: 16}}}
ret := intersectionCountArrayRun(a, b) ret := intersectionCountArrayRun(a, b)
if ret != 3 { if ret != 3 {
@ -357,16 +357,16 @@ func TestIntersectionCountArrayRun(t *testing.T) {
} }
func TestIntersectionCountBitmapRun(t *testing.T) { func TestIntersectionCountBitmapRun(t *testing.T) {
a := &container{bitmap: []uint64{0x8000000000000000}} a := &container{container_type: ContainerBitmap, bitmap: []uint64{0x8000000000000000}}
b := &container{runs: []interval16{{start: 63, last: 64}}} b := &container{container_type: ContainerRun, runs: []interval16{{start: 63, last: 64}}}
ret := intersectionCountBitmapRun(a, b) ret := intersectionCountBitmapRun(a, b)
if ret != 1 { if ret != 1 {
t.Fatalf("count of %v with %v should be 1, but got %v", a.bitmap, b.runs, ret) 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}} a = &container{container_type: ContainerBitmap, 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}}} 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) ret = intersectionCountBitmapRun(a, b)
if ret != 14 { if ret != 14 {
@ -414,6 +414,8 @@ func TestIntersectionCountRunRun(t *testing.T) {
bruns: []interval16{{start: 9, last: 9}, {start: 11, last: 17}}, exp: 6}, bruns: []interval16{{start: 9, last: 9}, {start: 11, last: 17}}, exp: 6},
} }
for i, test := range tests { for i, test := range tests {
a.container_type = ContainerRun
b.container_type = ContainerRun
a.runs = test.aruns a.runs = test.aruns
b.runs = test.bruns b.runs = test.bruns
ret := intersectionCountRunRun(a, b) ret := intersectionCountRunRun(a, b)
@ -454,6 +456,8 @@ func TestIntersectArrayRun(t *testing.T) {
} }
for i, test := range tests { for i, test := range tests {
a.container_type = ContainerArray
b.container_type = ContainerRun
a.array = test.array a.array = test.array
b.runs = test.runs b.runs = test.runs
ret := intersectArrayRun(a, b) ret := intersectArrayRun(a, b)
@ -510,6 +514,8 @@ func TestIntersectRunRun(t *testing.T) {
}, },
} }
for i, test := range tests { for i, test := range tests {
a.container_type = ContainerRun
b.container_type = ContainerRun
a.runs = test.aruns a.runs = test.aruns
b.runs = test.bruns b.runs = test.bruns
ret := intersectRunRun(a, b) ret := intersectRunRun(a, b)
@ -573,6 +579,8 @@ func TestIntersectBitmapRunBitmap(t *testing.T) {
for i, v := range test.exp { for i, v := range test.exp {
exp[i] = v exp[i] = v
} }
a.container_type = ContainerBitmap
b.container_type = ContainerRun
ret := intersectBitmapRun(a, b) ret := intersectBitmapRun(a, b)
if ret.isArray() { if ret.isArray() {
ret.arrayToBitmap() ret.arrayToBitmap()
@ -632,6 +640,8 @@ func TestIntersectBitmapRunArray(t *testing.T) {
a.bitmap[i] = v a.bitmap[i] = v
} }
b.runs = test.runs b.runs = test.runs
a.container_type = ContainerBitmap
b.container_type = ContainerRun
ret := intersectBitmapRun(a, b) ret := intersectBitmapRun(a, b)
if !reflect.DeepEqual(ret.array, test.exp) { if !reflect.DeepEqual(ret.array, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array) 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 { for i, test := range tests {
a.runs = test.aruns a.runs = test.aruns
b.runs = test.bruns b.runs = test.bruns
a.container_type = ContainerRun
b.container_type = ContainerRun
ret := unionRunRun(a, b) ret := unionRunRun(a, b)
if !reflect.DeepEqual(ret.runs, test.exp) { if !reflect.DeepEqual(ret.runs, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs) 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 { for i, test := range tests {
a.array = test.array a.array = test.array
b.runs = test.runs b.runs = test.runs
a.container_type = ContainerArray
b.container_type = ContainerRun
ret := unionArrayRun(a, b) ret := unionArrayRun(a, b)
if !reflect.DeepEqual(ret.array, test.exp) { if !reflect.DeepEqual(ret.array, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array) 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) { func TestBitmapSetRange(t *testing.T) {
c := &container{bitmap: make([]uint64, bitmapN)} c := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)}
tests := []struct { tests := []struct {
bitmap []uint64 bitmap []uint64
start uint64 start uint64
@ -961,7 +975,7 @@ func TestBitmapSetRange(t *testing.T) {
} }
func TestArrayToBitmap(t *testing.T) { func TestArrayToBitmap(t *testing.T) {
a := &container{} a := &container{container_type: ContainerArray}
tests := []struct { tests := []struct {
array []uint16 array []uint16
exp []uint64 exp []uint64
@ -992,7 +1006,7 @@ func TestArrayToBitmap(t *testing.T) {
} }
func TestBitmapToArray(t *testing.T) { func TestBitmapToArray(t *testing.T) {
a := &container{} a := &container{container_type: ContainerBitmap}
tests := []struct { tests := []struct {
bitmap []uint64 bitmap []uint64
exp []uint16 exp []uint16
@ -1023,7 +1037,7 @@ func TestBitmapToArray(t *testing.T) {
} }
func TestRunToBitmap(t *testing.T) { func TestRunToBitmap(t *testing.T) {
a := &container{} a := &container{container_type: ContainerRun}
tests := []struct { tests := []struct {
runs []interval16 runs []interval16
exp []uint64 exp []uint64
@ -1077,7 +1091,7 @@ func getFullBitmap() []uint64 {
} }
func TestBitmapToRun(t *testing.T) { func TestBitmapToRun(t *testing.T) {
a := &container{} a := &container{container_type: ContainerBitmap}
tests := []struct { tests := []struct {
bitmap []uint64 bitmap []uint64
exp []interval16 exp []interval16
@ -1155,7 +1169,7 @@ func TestBitmapToRun(t *testing.T) {
} }
func TestArrayToRun(t *testing.T) { func TestArrayToRun(t *testing.T) {
a := &container{} a := &container{container_type: ContainerArray}
tests := []struct { tests := []struct {
array []uint16 array []uint16
exp []interval16 exp []interval16
@ -1189,7 +1203,7 @@ func TestArrayToRun(t *testing.T) {
} }
func TestRunToArray(t *testing.T) { func TestRunToArray(t *testing.T) {
a := &container{} a := &container{container_type: ContainerRun}
tests := []struct { tests := []struct {
runs []interval16 runs []interval16
exp []uint16 exp []uint16
@ -1223,7 +1237,7 @@ func TestRunToArray(t *testing.T) {
} }
func TestBitmapZeroRange(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 { tests := []struct {
bitmap []uint64 bitmap []uint64
start uint64 start uint64
@ -1267,8 +1281,8 @@ func TestBitmapZeroRange(t *testing.T) {
} }
func TestUnionBitmapRun(t *testing.T) { func TestUnionBitmapRun(t *testing.T) {
a := &container{bitmap: make([]uint64, bitmapN)} a := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)}
b := &container{} b := &container{container_type: ContainerRun}
tests := []struct { tests := []struct {
bitmap []uint64 bitmap []uint64
runs []interval16 runs []interval16
@ -1288,6 +1302,7 @@ func TestUnionBitmapRun(t *testing.T) {
} }
a.n = a.bitmapCountRange(0, 65535) a.n = a.bitmapCountRange(0, 65535)
b.runs = test.runs b.runs = test.runs
b.n = b.runCountRange(0, 65535)
ret := unionBitmapRun(a, b) ret := unionBitmapRun(a, b)
if ret.isArray() { if ret.isArray() {
ret.arrayToBitmap() ret.arrayToBitmap()
@ -1305,7 +1320,7 @@ func TestUnionBitmapRun(t *testing.T) {
} }
func TestBitmapCountRuns(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 { tests := []struct {
bitmap []uint64 bitmap []uint64
exp int exp int
@ -1355,7 +1370,7 @@ func TestBitmapCountRuns(t *testing.T) {
} }
func TestArrayCountRuns(t *testing.T) { func TestArrayCountRuns(t *testing.T) {
c := &container{} c := &container{container_type: ContainerArray}
tests := []struct { tests := []struct {
array []uint16 array []uint16
exp int exp int
@ -1396,8 +1411,8 @@ func TestArrayCountRuns(t *testing.T) {
} }
func TestDifferenceArrayRun(t *testing.T) { func TestDifferenceArrayRun(t *testing.T) {
a := &container{} a := &container{container_type: ContainerArray}
b := &container{} b := &container{container_type: ContainerRun}
tests := []struct { tests := []struct {
array []uint16 array []uint16
runs []interval16 runs []interval16
@ -1422,8 +1437,8 @@ func TestDifferenceArrayRun(t *testing.T) {
} }
func TestDifferenceRunArray(t *testing.T) { func TestDifferenceRunArray(t *testing.T) {
a := &container{} a := &container{container_type: ContainerRun}
b := &container{} b := &container{container_type: ContainerArray}
tests := []struct { tests := []struct {
runs []interval16 runs []interval16
array []uint16 array []uint16
@ -1464,6 +1479,16 @@ func TestDifferenceRunArray(t *testing.T) {
array: []uint16{0, 9, 10, 11, 12, 13, 14, 17, 19, 25, 27}, array: []uint16{0, 9, 10, 11, 12, 13, 14, 17, 19, 25, 27},
exp: []interval16{{start: 1, last: 8}, {start: 15, last: 16}, {start: 20, last: 24}, {start: 26, last: 26}, {start: 28, last: 28}}, exp: []interval16{{start: 1, last: 8}, {start: 15, last: 16}, {start: 20, last: 24}, {start: 26, last: 26}, {start: 28, last: 28}},
}, },
{
runs: []interval16{{start: 0, last: 20}, {start: 65533, last: 65535}},
array: []uint16{65533, 65534, 65535},
exp: []interval16{{start: 0, last: 20}},
},
{
runs: []interval16{{start: 0, last: 20}, {start: 65530, last: 65535}},
array: []uint16{37, 65535},
exp: []interval16{{start: 0, last: 20}, {start: 65530, last: 65534}},
},
} }
for i, test := range tests { for i, test := range tests {
a.runs = test.runs a.runs = test.runs
@ -1493,8 +1518,8 @@ func MakeLastBitSet() []uint64 {
} }
func TestDifferenceRunBitmap(t *testing.T) { func TestDifferenceRunBitmap(t *testing.T) {
a := &container{} a := &container{container_type: ContainerRun}
b := &container{bitmap: make([]uint64, bitmapN)} b := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)}
tests := []struct { tests := []struct {
runs []interval16 runs []interval16
bitmap []uint64 bitmap []uint64
@ -1556,8 +1581,8 @@ func TestDifferenceRunBitmap(t *testing.T) {
} }
func TestDifferenceBitmapRun(t *testing.T) { func TestDifferenceBitmapRun(t *testing.T) {
a := &container{bitmap: make([]uint64, bitmapN)} a := &container{container_type: ContainerBitmap, bitmap: make([]uint64, bitmapN)}
b := &container{} b := &container{container_type: ContainerRun}
tests := []struct { tests := []struct {
bitmap []uint64 bitmap []uint64
runs []interval16 runs []interval16
@ -1584,7 +1609,7 @@ func TestDifferenceBitmapRun(t *testing.T) {
} }
func TestDifferenceBitmapArray(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} a := &container{container_type: ContainerArray}
tests := []struct { tests := []struct {
bitmap []uint64 bitmap []uint64
@ -2229,6 +2254,44 @@ func TestIteratorRuns(t *testing.T) {
} }
} }
func TestIteratorVarious(t *testing.T) {
tests := []struct {
bm *Bitmap
exp uint64
}{
{
bm: NewBitmap(3, 4, 5),
exp: 3,
},
{
bm: bitmapVariousContainers(),
exp: 61221,
},
{
bm: NewBitmap(2, 66000, 70000, 70001, 70002, 70003, 70004),
exp: 7,
},
}
for i, test := range tests {
test.bm.Optimize()
t.Run(fmt.Sprintf("#%d:", i), func(t *testing.T) {
if cnt := test.bm.Count(); cnt != test.exp {
t.Fatalf("merged count %d is not %d", cnt, test.exp)
}
iter := test.bm.Iterator()
bits := make([]uint64, 0, test.bm.Count())
for v, eof := iter.Next(); !eof; v, eof = iter.Next() {
bits = append(bits, v)
}
if length := len(bits); uint64(length) != test.exp {
t.Fatalf("length %d is not %d", length, test.exp)
}
})
}
}
func TestRunBinSearchContains(t *testing.T) { func TestRunBinSearchContains(t *testing.T) {
tests := []struct { tests := []struct {
runs []interval16 runs []interval16
@ -2513,8 +2576,9 @@ func TestSearc64(t *testing.T) {
} }
func TestIntersectArrayBitmap(t *testing.T) { func TestIntersectArrayBitmap(t *testing.T) {
a, b := &container{}, &container{ a, b := &container{container_type: ContainerArray}, &container{
bitmap: make([]uint64, bitmapN), container_type: ContainerBitmap,
bitmap: make([]uint64, bitmapN),
} }
tests := []struct { tests := []struct {
array []uint16 array []uint16
@ -2590,3 +2654,87 @@ func bitmapEvens() []uint64 {
} }
return bitmap return bitmap
} }
var containerWidth uint64 = 65536
// rleCont returns a slice of numbers all in the range starting from
// container_width*num, and ending at container_width*(num+1)-1. If left is
// true, then the first 100 bits will be set, if mid is true, 100 bits in the
// middle will be set, if right is true, the last 100 bits will be set.
// sets 100 bits per true
func rleCont(num int, left, mid, right bool) []uint64 {
ret := make([]uint64, 0)
base := containerWidth * uint64(num)
if left {
for i := uint64(0); i < 100; i++ {
ret = append(ret, base+i)
}
}
if mid {
for i := containerWidth / 2; i < containerWidth/2+100; i++ {
ret = append(ret, base+i)
}
}
if right {
for i := containerWidth - 100; i < containerWidth; i++ {
ret = append(ret, base+i)
}
}
return ret
}
// sets 2 bits per true.
func arrCont(num int, left, mid, right bool) []uint64 {
ret := make([]uint64, 0)
base := containerWidth * uint64(num)
if left {
ret = append(ret, base+0, base+2)
}
if mid {
half := containerWidth / 2
ret = append(ret, base+half, base+half+2)
}
if right {
ret = append(ret, base+containerWidth-3, base+containerWidth-1)
}
return ret
}
// sets 6667 bits per true.
func bitCont(num int, left, mid, right bool) []uint64 {
ret := make([]uint64, 0)
base := containerWidth * uint64(num)
if left {
for i := uint64(0); i < 20001; i += 3 {
ret = append(ret, base+i)
}
}
if mid {
for i := uint64(21000); i < 41001; i += 3 {
ret = append(ret, base+i)
}
}
if right {
for i := uint64(45537); i <= 65535; i += 3 {
ret = append(ret, base+i)
}
}
return ret
}
func bitmapVariousContainers() *Bitmap {
bits := make([]uint64, 0)
bits = append(bits, rleCont(0, true, true, true)...)
bits = append(bits, rleCont(1, true, true, true)...)
bits = append(bits, arrCont(2, true, true, true)...)
bits = append(bits, arrCont(3, true, true, true)...)
bits = append(bits, bitCont(4, true, true, true)...)
bits = append(bits, bitCont(5, true, true, true)...)
bits = append(bits, rleCont(6, true, true, true)...)
bits = append(bits, bitCont(7, true, true, true)...)
bits = append(bits, arrCont(8, true, true, true)...)
bits = append(bits, rleCont(9, true, true, true)...)
bm := NewBitmap(bits...)
bm.Optimize()
return bm
}

View file

@ -58,6 +58,7 @@ type Server struct {
Handler *Handler Handler *Handler
Broadcaster Broadcaster Broadcaster Broadcaster
BroadcastReceiver BroadcastReceiver BroadcastReceiver BroadcastReceiver
RemoteClient *http.Client
// Cluster configuration. // Cluster configuration.
// Host is replaced with actual host after opening if port is ":0". // Host is replaced with actual host after opening if port is ":0".
@ -79,6 +80,7 @@ type Server struct {
MaxWritesPerRequest int MaxWritesPerRequest int
LogOutput io.Writer LogOutput io.Writer
logger *log.Logger
defaultClient InternalClient defaultClient InternalClient
} }
@ -103,9 +105,9 @@ func NewServer() *Server {
LogOutput: os.Stderr, LogOutput: os.Stderr,
} }
s.logger = log.New(s.LogOutput, "", log.LstdFlags)
s.Handler.Holder = s.Holder s.Handler.Holder = s.Holder
return s return s
} }
@ -167,15 +169,16 @@ func (s *Server) Open() error {
} }
// Create default HTTP client // Create default HTTP client
s.createDefaultClient() s.createDefaultClient(s.RemoteClient)
// Create executor for executing queries. // Create executor for executing queries.
e := NewExecutor(&ClientOptions{TLS: s.TLS}) e := NewExecutor(s.RemoteClient)
e.Holder = s.Holder e.Holder = s.Holder
e.Scheme = s.URI.Scheme() e.Scheme = s.URI.Scheme()
e.Host = s.URI.HostPort() e.Host = s.URI.HostPort()
e.Cluster = s.Cluster e.Cluster = s.Cluster
e.MaxWritesPerRequest = s.MaxWritesPerRequest e.MaxWritesPerRequest = s.MaxWritesPerRequest
s.Cluster.MaxWritesPerRequest = s.MaxWritesPerRequest
// Initialize HTTP handler. // Initialize HTTP handler.
s.Handler.Broadcaster = s.Broadcaster s.Handler.Broadcaster = s.Broadcaster
@ -229,9 +232,28 @@ func (s *Server) Addr() net.Addr {
} }
return s.ln.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 // 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() { func (s *Server) monitorAntiEntropy() {
ticker := time.NewTicker(s.AntiEntropyInterval) ticker := time.NewTicker(s.AntiEntropyInterval)
@ -256,7 +278,7 @@ func (s *Server) monitorAntiEntropy() {
syncer.URI = s.URI syncer.URI = s.URI
syncer.Cluster = s.Cluster syncer.Cluster = s.Cluster
syncer.Closing = s.closing syncer.Closing = s.closing
syncer.ClientOptions = &ClientOptions{TLS: s.TLS} syncer.RemoteClient = s.RemoteClient
// Sync holders. // Sync holders.
if err := syncer.SyncHolder(); err != nil { if err := syncer.SyncHolder(); err != nil {
@ -603,12 +625,8 @@ func (s *Server) monitorRuntime() {
} }
} }
func (s *Server) createDefaultClient() { func (s *Server) createDefaultClient(remoteClient *http.Client) {
transport := &http.Transport{} s.defaultClient = NewInternalHTTPClientFromURI(nil, remoteClient)
if s.TLS != nil {
transport.TLSClientConfig = s.TLS
}
s.defaultClient = NewInternalHTTPClientFromURI(nil, &ClientOptions{TLS: s.TLS})
} }
// CountOpenFiles on operating systems that support lsof. // CountOpenFiles on operating systems that support lsof.

View file

@ -31,10 +31,11 @@ import (
"crypto/tls" "crypto/tls"
"io/ioutil"
"github.com/pilosa/pilosa" "github.com/pilosa/pilosa"
"github.com/pilosa/pilosa/gossip" "github.com/pilosa/pilosa/gossip"
"github.com/pilosa/pilosa/statsd" "github.com/pilosa/pilosa/statsd"
"io/ioutil"
) )
func init() { func init() {
@ -161,6 +162,7 @@ func (m *Command) SetupServer() error {
m.Server.MaxWritesPerRequest = m.Config.MaxWritesPerRequest m.Server.MaxWritesPerRequest = m.Config.MaxWritesPerRequest
// Setup TLS // Setup TLS
var TLSConfig *tls.Config
if uri.Scheme() == "https" { if uri.Scheme() == "https" {
if m.Config.TLS.CertificatePath == "" { if m.Config.TLS.CertificatePath == "" {
return errors.New("certificate path is required for TLS sockets") return errors.New("certificate path is required for TLS sockets")
@ -176,8 +178,15 @@ func (m *Command) SetupServer() error {
Certificates: []tls.Certificate{cert}, Certificates: []tls.Certificate{cert},
InsecureSkipVerify: m.Config.TLS.SkipVerify, 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). // Set internal port (string).
gossipPortStr := pilosa.DefaultGossipPort gossipPortStr := pilosa.DefaultGossipPort

View file

@ -50,7 +50,7 @@ func TestMain_Set_Quick(t *testing.T) {
defer m.Close() defer m.Close()
// Create client. // 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -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. // Ensure program can set bits on one cluster and then restore to a second cluster.
func TestMain_FrameRestore(t *testing.T) { func TestMain_FrameRestore(t *testing.T) {
m0 := MustRunMain() m0 := MustRunMain()
defer m0.Close() // 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
m1 := MustRunMain() // arbitrarily sized Pilosa clusters for testing, and then we should
defer m1.Close() // re-instate the multi-node nature of this test.
// 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
// Create frames. // Create frames.
client := m0.Client() client := m0.Client()
if err := client.CreateIndex(context.Background(), "i", pilosa.IndexOptions{}); err != nil && err != pilosa.ErrIndexExists { 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 { } 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. // 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=600000)
SetBit(rowID=1, frame="f", columnID=800000) SetBit(rowID=1, frame="f", columnID=800000)
`); err != nil { `); err != nil {
t.Fatal(err) t.Fatal("setting bits:", err)
} }
// Query row on first cluster. // Query row on first cluster.
if res, err := m0.Query("i", "", `Bitmap(rowID=1, frame="f")`); err != nil { 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" { } else if res != `{"results":[{"attrs":{},"bits":[100,1000,100000,200000,400000,600000,800000]}]}`+"\n" {
t.Fatalf("unexpected result: %s", res) t.Fatalf("unexpected result: %s", res)
} }
@ -323,22 +316,22 @@ func TestMain_FrameRestore(t *testing.T) {
defer m2.Close() defer m2.Close()
// Import from first cluster. // 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 { 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 { } 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 { } 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 { } 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. // Query row on second cluster.
if res, err := m2.Query("i", "", `Bitmap(rowID=1, frame="f")`); err != nil { 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" { } 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)
} }
} }
@ -672,7 +665,7 @@ func (m *Main) URL() string { return "http://" + m.Server.Addr().String() }
// Client returns a client to connect to the program. // Client returns a client to connect to the program.
func (m *Main) Client() *pilosa.InternalHTTPClient { 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 { if err != nil {
panic(err) panic(err)
} }

View file

@ -1,6 +1,8 @@
package test package test
import ( import (
"net/http"
"github.com/pilosa/pilosa" "github.com/pilosa/pilosa"
) )
@ -10,8 +12,8 @@ type Client struct {
} }
// MustNewClient returns a new instance of Client. Panic on error. // MustNewClient returns a new instance of Client. Panic on error.
func MustNewClient(host string) *Client { func MustNewClient(host string, h *http.Client) *Client {
c, err := pilosa.NewInternalHTTPClient(host, nil) c, err := pilosa.NewInternalHTTPClient(host, h)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -1,6 +1,7 @@
package test package test
import ( import (
"net/http"
"strings" "strings"
"github.com/pilosa/pilosa" "github.com/pilosa/pilosa"
@ -12,10 +13,16 @@ type Executor struct {
*pilosa.Executor *pilosa.Executor
} }
var remoteClient *http.Client
func init() {
remoteClient = pilosa.GetHTTPClient(nil)
}
// NewExecutor returns a new instance of Executor. // NewExecutor returns a new instance of Executor.
// The executor always matches the hostname of the first cluster node. // The executor always matches the hostname of the first cluster node.
func NewExecutor(holder *pilosa.Holder, cluster *pilosa.Cluster) *Executor { func NewExecutor(holder *pilosa.Holder, cluster *pilosa.Cluster) *Executor {
executor := pilosa.NewExecutor(nil) executor := pilosa.NewExecutor(remoteClient)
e := &Executor{Executor: executor} e := &Executor{Executor: executor}
e.Holder = holder e.Holder = holder
e.Cluster = cluster e.Cluster = cluster