mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-08 03:47:51 +00:00
Merge branch 'master' into cluster-resize
This commit is contained in:
commit
c4f6a6beda
15 changed files with 735 additions and 645 deletions
|
|
@ -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="
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.9.2 as builder
|
||||
FROM golang:1.10 as builder
|
||||
|
||||
ARG ldflags=''
|
||||
|
||||
|
|
|
|||
10
broadcast.go
10
broadcast.go
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
33
handler.go
33
handler.go
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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) }
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
11
server.go
11
server.go
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue