Merge branch 'master' into cluster-resize

This commit is contained in:
Travis Turner 2018-02-21 16:23:53 -06:00
commit c4f6a6beda
No known key found for this signature in database
GPG key ID: 7F08008DFD9314C9
15 changed files with 735 additions and 645 deletions

View file

@ -1,7 +1,8 @@
language: go
go:
- 1.8
- 1.9
- "1.10" # Use string, as 1.10==1.1 if interpreted as float.
- master
env:
global: # AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
- secure: "VnBFmFfBOrrf7ONLN9WpAFCcV8SEt5G5VPnnHv97TP7PlJG8LWR6k6O+vRJOvf8V4vDMfKCTDonwWLgbssVf3yygo3C8ZoftY2phehEkWGffCgsd9ML/YBNbGq4LYLSE5HKvBqrZjQaOrVby71BAsP8W7RhC6hqzFQ00M/z8dZVfwaQQFwew2eEcSxLEaaDFS8Wgc3/UuwxDRPBq6u3cCN5RxfB+q70HvGVq4TT+0dqS4eCvz688+Z0GIGYx9olNjh0F2Kc8R2Po0lnUNa0GiHrZ21zeQ1DxIK04QABrWWmjL4h+bx3VHNKPFR4GYSKDf+pj1kfaqbfrAg6rMAJdGejgoS+QyjhgCoN4d3qRp8s+1nrxtp0TvezEdjwyxt4quGHbP5TxWUszssbGhWqf4mx6OeJ8MmdTaJjfu0f3NWJXMycqT6J73WKORk4rHeIqF9CIdxdmcpkwYj8rk0TEMTPTsd7WA8w2HIDsCz/jQnRmEgLUiNnTAofYc/uUi/Wg/T2hllkp+oBDTzxk9NTelkqx8TJ0bDmYYL9JWUi1siFHTHiVYTJgyirSfGNpe61u8OLmT0Hak/D399IfL7qgFLlMXk8q92typfO2xEduq6G+8KygeqiOMSsOY+xcDvZf5xtcEihYd21vjtrxRSqFsup/o8DIxEurQnfXBx1B+WA="

View file

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

View file

@ -130,6 +130,8 @@ const (
MessageTypeDeleteFrame
MessageTypeCreateView
MessageTypeDeleteView
MessageTypeCreateField
MessageTypeDeleteField
MessageTypeCreateInputDefinition
MessageTypeDeleteInputDefinition
MessageTypeClusterStatus
@ -158,6 +160,10 @@ func MarshalMessage(m proto.Message) ([]byte, error) {
typ = MessageTypeCreateView
case *internal.DeleteViewMessage:
typ = MessageTypeDeleteView
case *internal.CreateFieldMessage:
typ = MessageTypeCreateField
case *internal.DeleteFieldMessage:
typ = MessageTypeDeleteField
case *internal.CreateInputDefinitionMessage:
typ = MessageTypeCreateInputDefinition
case *internal.DeleteInputDefinitionMessage:
@ -204,6 +210,10 @@ func UnmarshalMessage(buf []byte) (proto.Message, error) {
m = &internal.CreateViewMessage{}
case MessageTypeDeleteView:
m = &internal.DeleteViewMessage{}
case MessageTypeCreateField:
m = &internal.CreateFieldMessage{}
case MessageTypeDeleteField:
m = &internal.DeleteFieldMessage{}
case MessageTypeCreateInputDefinition:
m = &internal.CreateInputDefinitionMessage{}
case MessageTypeDeleteInputDefinition:

View file

@ -1687,7 +1687,7 @@ func (c *Cluster) NodeLeave(node *Node) error {
}
if c.State() != ClusterStateNormal {
return fmt.Errorf("Cluster must be in state %s to remove a node. Current state: %s", ClusterStateNormal, c.State)
return fmt.Errorf("Cluster must be in state %s to remove a node. Current state: %s", ClusterStateNormal, c.State())
}
return c.nodeLeave(node)

View file

@ -182,9 +182,8 @@ Any flag that has a value that is a comma separated list on the command line bec
#### Cluster Type
* Description: Determine how the cluster handles membership and state sharing. Choose from [static, http, gossip].
* Description: Determine how the cluster handles membership and state sharing. Choose from [static, gossip].
* static - Messaging between nodes is disabled. This is primarily used for testing.
* http - Messages are transmitted over HTTP.
* gossip - Messages are transmitted over TCP. Cluster status and node state are kept in sync via internode gossip.
* Flag: `cluster.type="gossip"`
* Env: `PILOSA_CLUSTER_TYPE="gossip"`

View file

@ -188,7 +188,7 @@ func loadNormal(router *mux.Router, handler *Handler) {
}
func (h *Handler) reportRestricted(w http.ResponseWriter, r *http.Request) {
http.Error(w, fmt.Sprintf("not allowed in cluster state %s", h.Cluster.State), http.StatusMethodNotAllowed)
http.Error(w, fmt.Sprintf("not allowed in cluster state %s", h.Cluster.State()), http.StatusMethodNotAllowed)
}
func (h *Handler) methodNotAllowedHandler(w http.ResponseWriter, r *http.Request) {
@ -682,7 +682,6 @@ func (h *Handler) handlePostFrame(w http.ResponseWriter, r *http.Request) {
}
h.Holder.Stats.CountWithCustomTags("createFrame", 1, 1.0, []string{fmt.Sprintf("index:%s", indexName)})
}
type _postFrameRequest postFrameRequest
@ -834,17 +833,30 @@ func (h *Handler) handlePostFrameField(w http.ResponseWriter, r *http.Request) {
return
}
// Create new field.
if err := f.CreateField(&Field{
field := &Field{
Name: fieldName,
Type: req.Type,
Min: req.Min,
Max: req.Max,
}); err != nil {
}
// Create new field.
if err := f.CreateField(field); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Send the create field message to all nodes.
err := h.Broadcaster.SendSync(
&internal.CreateFieldMessage{
Index: indexName,
Frame: frameName,
Field: encodeField(field),
})
if err != nil {
h.logger().Printf("problem sending CreateField message: %s", err)
}
// Encode response.
if err := json.NewEncoder(w).Encode(postFrameFieldResponse{}); err != nil {
h.logger().Printf("response encoding error: %s", err)
@ -878,6 +890,17 @@ func (h *Handler) handleDeleteFrameField(w http.ResponseWriter, r *http.Request)
return
}
// Send the delete field message to all nodes.
err := h.Broadcaster.SendSync(
&internal.DeleteFieldMessage{
Index: indexName,
Frame: frameName,
Field: fieldName,
})
if err != nil {
h.logger().Printf("problem sending DeleteField message: %s", err)
}
// Encode response.
if err := json.NewEncoder(w).Encode(deleteFrameFieldResponse{}); err != nil {
h.logger().Printf("response encoding error: %s", err)

File diff suppressed because it is too large Load diff

View file

@ -69,6 +69,18 @@ message DeleteFrameMessage {
string Frame = 2;
}
message CreateFieldMessage {
string Index = 1;
string Frame = 2;
Field Field = 3;
}
message DeleteFieldMessage {
string Index = 1;
string Frame = 2;
string Field = 3;
}
message Frame {
string Name = 1;
FrameMeta Meta = 2;

View file

@ -1,68 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package roaring
// bit population count, take from
// https://code.google.com/p/go/issues/detail?id=4988#c11
// credit: https://code.google.com/u/arnehormann/
func popcntGo(x uint64) (n uint64) {
x -= (x >> 1) & 0x5555555555555555
x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
x += x >> 4
x &= 0x0f0f0f0f0f0f0f0f
x *= 0x0101010101010101
return x >> 56
}
func popcntSliceGo(s []uint64) uint64 {
cnt := uint64(0)
for _, x := range s {
cnt += popcntGo(x)
}
return cnt
}
func popcntMaskSliceGo(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcntGo(s[i] &^ m[i])
}
return cnt
}
func popcntAndSliceGo(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcntGo(s[i] & m[i])
}
return cnt
}
func popcntOrSliceGo(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcntGo(s[i] | m[i])
}
return cnt
}
func popcntXorSliceGo(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcntGo(s[i] ^ m[i])
}
return cnt
}

View file

@ -1,122 +0,0 @@
#include "textflag.h"
TEXT ·hasAsm(SB),4,$0-1
MOVQ $1, AX
CPUID
SHRQ $23, CX
ANDQ $1, CX
MOVB CX, ret+0(FP)
RET
TEXT ·POPCNTQ(SB),NOSPLIT,$0-16
MOVQ memory+0(FP), BP
POPCNTQ BP, BX
MOVQ BX, ret+8(FP)
RET
TEXT ·BSFQ(SB),NOSPLIT,$0-16
MOVQ memory+0(FP), BP
BSFQ BP, BX
MOVQ BX, ret+8(FP)
RET
#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2
TEXT ·popcntSliceAsm(SB),4,$0-32
XORQ AX, AX
MOVQ s_base+0(FP), SI
MOVQ s_len+8(FP), CX
TESTQ CX, CX
JZ popcntSliceEnd
popcntSliceLoop:
BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX
ADDQ DX, AX
ADDQ $8, SI
LOOP popcntSliceLoop
popcntSliceEnd:
MOVQ AX, ret+24(FP)
RET
TEXT ·popcntMaskSliceAsm(SB),4,$0-56
XORQ AX, AX
MOVQ s_base+0(FP), SI
MOVQ s_len+8(FP), CX
TESTQ CX, CX
JZ popcntMaskSliceEnd
MOVQ m+24(FP), DI
popcntMaskSliceLoop:
MOVQ (DI), DX
NOTQ DX
ANDQ (SI), DX
POPCNTQ_DX_DX
ADDQ DX, AX
ADDQ $8, SI
ADDQ $8, DI
LOOP popcntMaskSliceLoop
popcntMaskSliceEnd:
MOVQ AX, ret+48(FP)
RET
TEXT ·popcntAndSliceAsm(SB),4,$0-56
XORQ AX, AX
MOVQ s_base+0(FP), SI
MOVQ s_len+8(FP), CX
TESTQ CX, CX
JZ popcntAndSliceEnd
MOVQ m+24(FP), DI
popcntAndSliceLoop:
MOVQ (DI), DX
ANDQ (SI), DX
POPCNTQ_DX_DX
ADDQ DX, AX
ADDQ $8, SI
ADDQ $8, DI
LOOP popcntAndSliceLoop
popcntAndSliceEnd:
MOVQ AX, ret+48(FP)
RET
TEXT ·popcntOrSliceAsm(SB),4,$0-56
XORQ AX, AX
MOVQ s_base+0(FP), SI
MOVQ s_len+8(FP), CX
TESTQ CX, CX
JZ popcntOrSliceEnd
MOVQ m+24(FP), DI
popcntOrSliceLoop:
MOVQ (DI), DX
ORQ (SI), DX
POPCNTQ_DX_DX
ADDQ DX, AX
ADDQ $8, SI
ADDQ $8, DI
LOOP popcntOrSliceLoop
popcntOrSliceEnd:
MOVQ AX, ret+48(FP)
RET
TEXT ·popcntXorSliceAsm(SB),4,$0-56
XORQ AX, AX
MOVQ s_base+0(FP), SI
MOVQ s_len+8(FP), CX
TESTQ CX, CX
JZ popcntXorSliceEnd
MOVQ m+24(FP), DI
popcntXorSliceLoop:
MOVQ (DI), DX
XORQ (SI), DX
POPCNTQ_DX_DX
ADDQ DX, AX
ADDQ $8, SI
ADDQ $8, DI
LOOP popcntXorSliceLoop
popcntXorSliceEnd:
MOVQ AX, ret+48(FP)
RET
TEXT ·popcntAsm(SB),4,$0-16
MOVQ x+0(FP), DX
POPCNTQ_DX_DX
MOVQ DX, ret+8(FP)
RET

View file

@ -1,87 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build amd64
package roaring
func hasAsm() bool
func BSFQ(memory uint64) int
func POPCNTQ(memory uint64) int
//go:noescape
var useAsm = hasAsm()
//go:noescape
func popcntSliceAsm(s []uint64) uint64
//go:noescape
func popcntMaskSliceAsm(s, m []uint64) uint64
//go:noescape
func popcntAndSliceAsm(s, m []uint64) uint64
//go:noescape
func popcntOrSliceAsm(s, m []uint64) uint64
//go:noescape
func popcntXorSliceAsm(s, m []uint64) uint64
//go:noescape
func popcntAsm(x uint64) uint64
func popcntSlice(s []uint64) uint64 {
if useAsm {
return popcntSliceAsm(s)
}
return popcntSliceGo(s)
}
func popcntMaskSlice(s, m []uint64) uint64 {
if useAsm {
return popcntMaskSliceAsm(s, m)
}
return popcntMaskSliceGo(s, m)
}
func popcntAndSlice(s, m []uint64) uint64 {
if useAsm {
return popcntAndSliceAsm(s, m)
}
return popcntAndSliceGo(s, m)
}
func popcntOrSlice(s, m []uint64) uint64 {
if useAsm {
return popcntOrSliceAsm(s, m)
}
return popcntOrSliceGo(s, m)
}
func popcntXorSlice(s, m []uint64) uint64 {
if useAsm {
return popcntXorSliceAsm(s, m)
}
return popcntXorSliceGo(s, m)
}
func popcnt(x uint64) uint64 {
if useAsm {
return popcntAsm(x)
}
return popcntGo(x)
}

View file

@ -1,27 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !amd64
package roaring
func hasAsm() bool {return false}
func popcntSlice(s []uint64) uint64 { return popcntSliceGo(s) }
func popcntMaskSlice(s, m []uint64) uint64 { return popcntMaskSliceGo(s, m) }
func popcntAndSlice(s, m []uint64) uint64 { return popcntAndSliceGo(s, m) }
func popcntOrSlice(s, m []uint64) uint64 { return popcntOrSliceGo(s, m) }
func popcntXorSlice(s, m []uint64) uint64 { return popcntXorSliceGo(s, m) }
func popcnt(s uint64) uint64 { return popcntGo(s) }

View file

@ -1,139 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package roaring
import "testing"
func TestBSFQ(t *testing.T) {
result := BSFQ(2)
if result != 1 {
t.Fatalf("BSF INCORRECT: %d", result)
}
}
func TestBSFQ_CompareGo(t *testing.T) {
v := uint64(1)
for i := 0; i < 64; i++ {
if BSFQ(v) != trailingZeroN(v) {
t.Fatalf("BSF INCORRECT: %d %d", BSFQ(v), trailingZeroN(v))
}
if v == 0 {
v = 1
} else {
v *= 2
}
}
/*
if bsfq(0) != trailingZeroN(0) {
fmt.Println(bsfq(0))
t.Fatalf("BSF INCORRECT")
}
*/
}
func BenchmarkBSF(b *testing.B) {
for i := 0; i < b.N; i++ {
BSFQ(uint64(i))
}
}
func BenchmarkTrailingZeroN(b *testing.B) {
for i := 0; i < b.N; i++ {
trailingZeroN(uint64(i))
}
}
func BenchmarkPOPCNTQ(b *testing.B) {
for i := 0; i < b.N; i++ {
POPCNTQ(uint64(i))
}
}
func BenchmarkPopcount(b *testing.B) {
for i := 0; i < b.N; i++ {
popcount(uint64(i))
}
}
func BenchmarkPopcntAsm(b *testing.B) {
// run the Fib function b.N times
for n := 0; n < b.N; n++ {
popcntAsm(0xdeadbeef)
}
}
func BenchmarkPopcntGo(b *testing.B) {
// run the Fib function b.N times
for n := 0; n < b.N; n++ {
popcntGo(0xdeadbeef)
}
}
func getData() []uint64 {
return []uint64{
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
}
}
func BenchmarkPopcntSliceGo(b *testing.B) {
d := getData()
for n := 0; n < b.N; n++ {
popcntSliceGo(d)
}
}
func BenchmarkPopcntSliceAsm(b *testing.B) {
d := getData()
for n := 0; n < b.N; n++ {
popcntSliceAsm(d)
}
}
func BenchmarkPopcntSlice(b *testing.B) {
d := getData()
for n := 0; n < b.N; n++ {
popcntSlice(d)
}
}

View file

@ -21,6 +21,7 @@ import (
"fmt"
"hash/fnv"
"io"
"math/bits"
"sort"
"unsafe"
)
@ -1274,10 +1275,10 @@ func (c *container) contains(v uint16) bool {
func (c *container) bitmapCountRuns() (r int) {
for i := 0; i < 1023; i++ {
v, v1 := c.bitmap[i], c.bitmap[i+1]
r = r + int(popcnt((v<<1)&^v)+((v>>63)&^v1))
r = r + int(popcount((v<<1)&^v)+((v>>63)&^v1))
}
vl := c.bitmap[len(c.bitmap)-1]
r = r + int(popcnt((vl<<1)&^vl)+vl>>63)
r = r + int(popcount((vl<<1)&^vl)+vl>>63)
return r
}
@ -1918,7 +1919,7 @@ func intersectionCountArrayBitmap(a, b *container) (n int) {
}
func intersectionCountBitmapBitmap(a, b *container) (n int) {
return int(popcntAndSlice(a.bitmap, b.bitmap))
return int(popcountAndSlice(a.bitmap, b.bitmap))
}
func intersect(a, b *container) *container {
@ -2061,22 +2062,22 @@ func intersectBitmapRun(a, b *container) *container {
for valast >= vb.start && vastart <= vb.last && i < bitmapN {
if vastart >= vb.start && valast <= vb.last { // a within b
output.bitmap[i] = a.bitmap[i]
output.n += int(popcnt(a.bitmap[i]))
output.n += int(popcount(a.bitmap[i]))
} else if vb.start >= vastart && vb.last <= valast { // b within a
var mask uint64 = ((1 << (vb.last - vb.start + 1)) - 1) << (vb.start - vastart)
bits := a.bitmap[i] & mask
output.bitmap[i] |= bits
output.n += int(popcnt(bits))
output.n += int(popcount(bits))
} else if vastart < vb.start { // a overlaps front of b
offset := 64 - (1 + valast - vb.start)
bits := (a.bitmap[i] >> offset) << offset
output.bitmap[i] |= bits
output.n += int(popcnt(bits))
output.n += int(popcount(bits))
} else if vb.start < vastart { // b overlaps front of a
offset := 64 - (1 + vb.last - vastart)
bits := (a.bitmap[i] << offset) >> offset
output.bitmap[i] |= bits
output.n += int(popcnt(bits))
output.n += int(popcount(bits))
}
// update loop vars
i++
@ -2293,19 +2294,19 @@ func (c *container) bitmapSetRange(i, j uint64) {
y := (j - 1) >> 6
var X uint64 = maxBitmap << (i % 64)
var Y uint64 = maxBitmap >> (63 - ((j - 1) % 64))
xcnt := popcnt(X)
ycnt := popcnt(Y)
xcnt := popcount(X)
ycnt := popcount(Y)
if x == y {
c.n += int((j - i) - popcnt(c.bitmap[x]&(X&Y)))
c.n += int((j - i) - popcount(c.bitmap[x]&(X&Y)))
c.bitmap[x] |= (X & Y)
} else {
c.n += int(xcnt - popcnt(c.bitmap[x]&X))
c.n += int(xcnt - popcount(c.bitmap[x]&X))
c.bitmap[x] |= X
for i := x + 1; i < y; i++ {
c.n += int(64 - popcnt(c.bitmap[i]))
c.n += int(64 - popcount(c.bitmap[i]))
c.bitmap[i] = maxBitmap
}
c.n += int(ycnt - popcnt(c.bitmap[y]&Y))
c.n += int(ycnt - popcount(c.bitmap[y]&Y))
c.bitmap[y] |= Y
}
}
@ -2317,21 +2318,21 @@ func (c *container) bitmapXorRange(i, j uint64) {
var X uint64 = maxBitmap << (i % 64)
var Y uint64 = maxBitmap >> (63 - ((j - 1) % 64))
if x == y {
cnt := popcnt(c.bitmap[x])
cnt := popcount(c.bitmap[x])
c.bitmap[x] ^= (X & Y) //// flip
c.n += int(popcnt(c.bitmap[x]) - cnt)
c.n += int(popcount(c.bitmap[x]) - cnt)
} else {
cnt := popcnt(c.bitmap[x])
cnt := popcount(c.bitmap[x])
c.bitmap[x] ^= X
c.n += int(popcnt(c.bitmap[x]) - cnt)
c.n += int(popcount(c.bitmap[x]) - cnt)
for i := x + 1; i < y; i++ {
cnt = popcnt(c.bitmap[i])
cnt = popcount(c.bitmap[i])
c.bitmap[i] ^= maxBitmap
c.n += int(popcnt(c.bitmap[i]) - cnt)
c.n += int(popcount(c.bitmap[i]) - cnt)
}
cnt = popcnt(c.bitmap[y])
cnt = popcount(c.bitmap[y])
c.bitmap[y] ^= Y
c.n += int(popcnt(c.bitmap[y]) - cnt)
c.n += int(popcount(c.bitmap[y]) - cnt)
}
}
@ -2342,16 +2343,16 @@ func (c *container) bitmapZeroRange(i, j uint64) {
var X uint64 = maxBitmap << (i % 64)
var Y uint64 = maxBitmap >> (63 - ((j - 1) % 64))
if x == y {
c.n -= int(popcnt(c.bitmap[x] & (X & Y)))
c.n -= int(popcount(c.bitmap[x] & (X & Y)))
c.bitmap[x] &= ^(X & Y)
} else {
c.n -= int(popcnt(c.bitmap[x] & X))
c.n -= int(popcount(c.bitmap[x] & X))
c.bitmap[x] &= ^X
for i := x + 1; i < y; i++ {
c.n -= int(popcnt(c.bitmap[i]))
c.n -= int(popcount(c.bitmap[i]))
c.bitmap[i] = 0
}
c.n -= int(popcnt(c.bitmap[y] & Y))
c.n -= int(popcount(c.bitmap[y] & Y))
c.bitmap[y] &= ^Y
}
}
@ -2376,7 +2377,7 @@ func unionBitmapBitmap(a, b *container) *container {
for i := 0; i < bitmapN; i++ {
v := a.bitmap[i] | b.bitmap[i]
output.bitmap[i] = v
output.n += int(popcnt(v))
output.n += int(popcount(v))
}
return output
@ -2812,7 +2813,7 @@ func xorBitmapBitmap(a, b *container) *container {
for i := 0; i < bitmapN; i++ {
v := a.bitmap[i] ^ b.bitmap[i]
output.bitmap[i] = v
output.n += int(popcnt(v))
output.n += int(popcount(v))
}
if output.count() < ArrayMaxSize {
@ -2975,35 +2976,7 @@ func search64(a []uint64, value uint64) int {
// trailingZeroN returns the number of trailing zeros in v.
// v must be greater than zero.
func trailingZeroN(v uint64) int {
n := int64(63)
if y := v << 32; y != 0 {
n, v = n-32, y
}
if y := v << 16; y != 0 {
n, v = n-16, y
}
if y := v << 8; y != 0 {
n, v = n-8, y
}
if y := v << 4; y != 0 {
n, v = n-4, y
}
if y := v << 2; y != 0 {
n, v = n-2, y
}
return int(n - int64(v<<1>>63))
}
// bit population count, taken from
// https://code.google.com/p/go/issues/detail?id=4988#c11
// credit: https://code.google.com/u/arnehormann/
func popcount(x uint64) (n uint64) {
x -= (x >> 1) & 0x5555555555555555
x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
x += x >> 4
x &= 0x0f0f0f0f0f0f0f0f
x *= 0x0101010101010101
return x >> 56
return bits.TrailingZeros64(v)
}
// ErrorList represents a list of errors.
@ -3265,3 +3238,47 @@ func xorBitmapRun(a, b *container) *container {
}
return output
}
func popcount(x uint64) uint64 {
return uint64(bits.OnesCount64(x))
}
func popcountSlice(s []uint64) uint64 {
cnt := uint64(0)
for _, x := range s {
cnt += popcount(x)
}
return cnt
}
func popcountMaskSlice(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcount(s[i] &^ m[i])
}
return cnt
}
func popcountAndSlice(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcount(s[i] & m[i])
}
return cnt
}
func popcountOrSlice(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcount(s[i] | m[i])
}
return cnt
}
func popcountXorSlice(s, m []uint64) uint64 {
cnt := uint64(0)
for i := range s {
cnt += popcount(s[i] ^ m[i])
}
return cnt
}

View file

@ -396,6 +396,17 @@ func (s *Server) ReceiveMessage(pb proto.Message) error {
if err := idx.DeleteFrame(obj.Frame); err != nil {
return err
}
case *internal.CreateFieldMessage:
f := s.Holder.Frame(obj.Index, obj.Frame)
field := decodeField(obj.Field)
if err := f.CreateField(field); err != nil {
return err
}
case *internal.DeleteFieldMessage:
f := s.Holder.Frame(obj.Index, obj.Frame)
if err := f.DeleteField(obj.Field); err != nil {
return err
}
case *internal.CreateInputDefinitionMessage:
idx := s.Holder.Index(obj.Index)
if idx == nil {