expanded views to contain viewType for special handling

This commit is contained in:
Todd Gruben 2018-06-26 10:54:06 -05:00
parent 5160ed58f7
commit 35af580183
15 changed files with 266 additions and 162 deletions

2
api.go
View file

@ -399,7 +399,7 @@ func (api *API) UnmarshalFragment(ctx context.Context, indexName string, fieldNa
}
// Retrieve view.
view, err := f.CreateViewIfNotExists(ViewStandard)
view, err := f.CreateViewIfNotExists(viewTimeKey{name: ViewStandard})
if err != nil {
return errors.Wrap(err, "creating view")
}

View file

@ -1226,7 +1226,7 @@ func (c *Cluster) followResizeInstruction(instr *internal.ResizeInstruction) err
}
// Create view.
v, err := f.CreateViewIfNotExists(src.View)
v, err := f.CreateViewIfNotExists(viewTimeKey{name: src.View})
if err != nil {
return errors.Wrap(err, "creating view")
}

View file

@ -785,7 +785,7 @@ func (e *Executor) executeRangeSlice(ctx context.Context, index string, c *pql.C
// Union bitmaps across all time-based views.
row := &Row{}
for _, view := range viewsByTimeRange(ViewStandard, startTime, endTime, q) {
f := e.Holder.Fragment(index, fieldName, view, slice)
f := e.Holder.Fragment(index, fieldName, view.name, slice)
if f == nil {
continue
}
@ -1037,7 +1037,7 @@ func (e *Executor) executeClearBitField(ctx context.Context, index string, c *pq
for _, node := range e.Cluster.sliceNodes(index, slice) {
// Update locally if host matches.
if node.ID == e.Node.ID {
val, err := f.ClearBit(rowID, colID, nil)
val, err := f.ClearBit(rowID, colID)
if err != nil {
return false, err
} else if val {

136
field.go
View file

@ -20,6 +20,7 @@ import (
"os"
"path/filepath"
"sort"
"strings"
"sync"
"time"
@ -37,6 +38,9 @@ const (
// Default ranked field cache
defaultCacheSize = 50000
BitsPerWord = 32 << (^uint(0) >> 63) // either 32 or 64
MaxInt = 1<<(BitsPerWord-1) - 1 // either 1<<31 - 1 or 1<<63 - 1
)
// Field types.
@ -248,7 +252,7 @@ func (f *Field) openViews() error {
}
name := filepath.Base(fi.Name())
view := f.newView(f.ViewPath(name), name)
view := f.newView(f.ViewPath(name), viewTimeKey{name: name})
if err := view.open(); err != nil {
return fmt.Errorf("opening view: view=%s, err=%s", view.name, err)
}
@ -555,9 +559,9 @@ func (f *Field) RecalculateCaches() {
// CreateViewIfNotExists returns the named view, creating it if necessary.
// Additionally, a CreateViewMessage is sent to the cluster.
func (f *Field) CreateViewIfNotExists(name string) (*View, error) {
func (f *Field) CreateViewIfNotExists(vtk viewTimeKey) (*View, error) {
view, created, err := f.createViewIfNotExistsBase(name)
view, created, err := f.createViewIfNotExistsBase(vtk)
if err != nil {
return nil, err
}
@ -568,7 +572,8 @@ func (f *Field) CreateViewIfNotExists(name string) (*View, error) {
&internal.CreateViewMessage{
Index: f.index,
Field: f.name,
View: name,
View: vtk.name,
Type: string(vtk.quantum),
})
if err != nil {
return nil, errors.Wrap(err, "sending CreateView message")
@ -580,15 +585,15 @@ func (f *Field) CreateViewIfNotExists(name string) (*View, error) {
// createViewIfNotExistsBase returns the named view, creating it if necessary.
// The returned bool indicates whether the view was created or not.
func (f *Field) createViewIfNotExistsBase(name string) (*View, bool, error) {
func (f *Field) createViewIfNotExistsBase(vtk viewTimeKey) (*View, bool, error) {
f.mu.Lock()
defer f.mu.Unlock()
if view := f.views[name]; view != nil {
if view := f.views[vtk.name]; view != nil {
return view, false, nil
}
view := f.newView(f.ViewPath(name), name)
view := f.newView(f.ViewPath(vtk.name), vtk)
if err := view.open(); err != nil {
return nil, false, errors.Wrap(err, "opening view")
@ -599,13 +604,14 @@ func (f *Field) createViewIfNotExistsBase(name string) (*View, bool, error) {
return view, true, nil
}
func (f *Field) newView(path, name string) *View {
view := NewView(path, f.index, f.name, name, f.options.CacheSize)
func (f *Field) newView(path string, vtk viewTimeKey) *View {
view := NewView(path, f.index, f.name, vtk.name, f.options.CacheSize)
view.cacheType = f.options.CacheType
view.Logger = f.Logger
view.RowAttrStore = f.rowAttrStore
view.stats = f.Stats.WithTags(fmt.Sprintf("view:%s", name))
view.stats = f.Stats.WithTags(fmt.Sprintf("view:%s", vtk.name))
view.broadcaster = f.broadcaster
view.viewType = vtk.quantum
return view
}
@ -655,7 +661,7 @@ func (f *Field) ViewRow(viewName string, rowID uint64) (*Row, error) {
// SetBit sets a bit on a view within the field.
func (f *Field) SetBit(rowID, colID uint64, t *time.Time) (changed bool, err error) {
viewName := ViewStandard
viewName := viewTimeKey{name: ViewStandard}
// Retrieve view. Exit if it doesn't exist.
view, err := f.CreateViewIfNotExists(viewName)
@ -676,14 +682,14 @@ func (f *Field) SetBit(rowID, colID uint64, t *time.Time) (changed bool, err err
}
// If a timestamp is specified then set bits across all views for the quantum.
for _, subname := range viewsByTime(viewName, *t, f.TimeQuantum()) {
view, err := f.CreateViewIfNotExists(subname)
for _, vtk := range viewsByTime(viewName.name, *t, f.TimeQuantum()) {
view, err := f.CreateViewIfNotExists(vtk)
if err != nil {
return changed, errors.Wrapf(err, "creating view %s", subname)
return changed, errors.Wrapf(err, "creating view %s", vtk.name)
}
if c, err := view.setBit(rowID, colID); err != nil {
return changed, errors.Wrapf(err, "setting on view %s", subname)
return changed, errors.Wrapf(err, "setting on view %s", vtk.name)
} else if c {
changed = true
}
@ -693,44 +699,88 @@ func (f *Field) SetBit(rowID, colID uint64, t *time.Time) (changed bool, err err
}
// ClearBit clears a bit within the field.
func (f *Field) ClearBit(rowID, colID uint64, t *time.Time) (changed bool, err error) {
viewName := ViewStandard
func (f *Field) ClearBit(rowID, colID uint64) (changed bool, err error) {
viewName := viewTimeKey{name: ViewStandard}
// Retrieve view. Exit if it doesn't exist.
view, err := f.CreateViewIfNotExists(viewName)
if err != nil {
return changed, errors.Wrap(err, "creating view")
view, present := f.views[viewName.name]
if !present {
return changed, errors.Wrap(err, "clearing missing view")
}
// Clear non-time bit.
if v, err := view.clearBit(rowID, colID); err != nil {
if v, _, err := view.clearBit(rowID, colID); err != nil {
return changed, errors.Wrap(err, "clearing on view")
} else if v {
changed = v
}
// Exit early if no timestamp is specified.
if t == nil {
return changed, nil
}
// If a timestamp is specified then clear bits across all views for the quantum.
for _, subname := range viewsByTime(viewName, *t, f.TimeQuantum()) {
view, err := f.CreateViewIfNotExists(subname)
if err != nil {
return changed, errors.Wrapf(err, "creating view %s", subname)
process := true
anyRemaining := false
lastLevel := 0
skipLevel := MaxInt //just setting to a bignum
for i, quantumView := range f.allTimeViewsSortedByQuantum() {
if process {
if changed, remainingBits, err := quantumView.clearBit(rowID, colID); err != nil {
return changed, errors.Wrapf(err, "clearing on view %s", quantumView.name)
} else if remainingBits { //now empty implies that the row as just been cleared and removed
anyRemaining = true
}
}
if i == 0 {
lastLevel = len(quantumView.name)
} else if lastLevel != len(quantumView.name) {
if lastLevel < len(quantumView.name) {
if anyRemaining {
skipLevel = lastLevel
process = false
anyRemaining = false
}
} else if lastLevel > len(quantumView.name) {
if len(quantumView.name) <= skipLevel { //skip no more
process = true
skipLevel = MaxInt
}
}
if c, err := view.clearBit(rowID, colID); err != nil {
return changed, errors.Wrapf(err, "clearing on view %s", subname)
} else if c {
changed = true
}
lastLevel = len(quantumView.name)
}
return changed, nil
}
func groupCompare(a, b string, offset int) (lt, eq bool) {
v := strings.Compare(a[:offset], b[:offset])
return v < 0, v == 0
}
func (f *Field) allTimeViewsSortedByQuantum() (me []*View) {
me = make([]*View, len(f.views), len(f.views))
for _, v := range f.views {
if v.viewType != 0 { // skip non-time views
me = append(me, v)
}
}
year := strings.Index(me[0].name, "_") + 4
month := year + 2
day := month + 2
sort.Slice(me, func(i, j int) (lt bool) {
var eq bool
// ensure all catA are grouped together:
if lt, eq = groupCompare(me[i].name, me[j].name, year); eq {
if lt, eq = groupCompare(me[i].name, me[j].name, month); eq {
if lt, eq = groupCompare(me[i].name, me[j].name, day); eq {
lt = strings.Compare(me[i].name, me[j].name) > 0
}
}
}
return
})
return
}
// Value reads a field value for a column.
func (f *Field) Value(columnID uint64) (value int64, exists bool, err error) {
bsig := f.bsiGroup(f.name)
@ -766,7 +816,7 @@ func (f *Field) SetValue(columnID uint64, value int64) (changed bool, err error)
}
// Fetch target view.
view, err := f.CreateViewIfNotExists(viewBSIGroupPrefix + f.name)
view, err := f.CreateViewIfNotExists(viewTimeKey{name: viewBSIGroupPrefix + f.name})
if err != nil {
return false, errors.Wrap(err, "creating view")
}
@ -900,19 +950,19 @@ func (f *Field) Import(rowIDs, columnIDs []uint64, timestamps []*time.Time) erro
timestamp = timestamps[i]
}
var standard []string
var standard []viewTimeKey
if timestamp == nil {
standard = []string{ViewStandard}
standard = []viewTimeKey{{name: ViewStandard}}
} else {
standard = viewsByTime(ViewStandard, *timestamp, q)
// In order to match the logic of `SetBit()`, we want bits
// with timestamps to write to both time and standard views.
standard = append(standard, ViewStandard)
standard = append(standard, viewTimeKey{name: ViewStandard})
}
// Attach bit to each standard view.
for _, name := range standard {
key := importKey{View: name, Slice: columnID / SliceWidth}
for _, vtk := range standard {
key := importKey{View: vtk.name, Slice: columnID / SliceWidth}
data := dataByFragment[key]
data.RowIDs = append(data.RowIDs, rowID)
data.ColumnIDs = append(data.ColumnIDs, columnID)
@ -922,7 +972,7 @@ func (f *Field) Import(rowIDs, columnIDs []uint64, timestamps []*time.Time) erro
// Import into each fragment.
for key, data := range dataByFragment {
view, err := f.CreateViewIfNotExists(key.View)
view, err := f.CreateViewIfNotExists(viewTimeKey{name: key.View})
if err != nil {
return errors.Wrap(err, "creating view")
}
@ -974,7 +1024,7 @@ func (f *Field) ImportValue(columnIDs []uint64, values []int64) error {
// The view must already exist (i.e. we can't create it)
// because we need to know bitDepth (based on min/max value).
view, err := f.CreateViewIfNotExists(key.View)
view, err := f.CreateViewIfNotExists(viewTimeKey{name: key.View})
if err != nil {
return errors.Wrap(err, "creating view")
}

View file

@ -412,28 +412,28 @@ func (f *Fragment) unprotectedSetBit(rowID, columnID uint64) (changed bool, err
// clearBit clears a bit for a given column & row within the fragment.
// This updates both the on-disk storage and the in-cache bitmap.
func (f *Fragment) clearBit(rowID, columnID uint64) (bool, error) {
func (f *Fragment) clearBit(rowID, columnID uint64) (bool, bool, error) {
f.mu.Lock()
defer f.mu.Unlock()
return f.unprotectedClearBit(rowID, columnID)
}
func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed bool, err error) {
func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed bool, remaining bool, err error) {
changed = false
// Determine the position of the bit in the storage.
pos, err := f.pos(rowID, columnID)
if err != nil {
return false, errors.Wrap(err, "getting bit pos")
return false, false, errors.Wrap(err, "getting bit pos")
}
// Write to storage.
if changed, err = f.storage.Remove(pos); err != nil {
return false, errors.Wrap(err, "writing")
return false, false, errors.Wrap(err, "writing")
}
// Don't update the cache if nothing changed.
if !changed {
return changed, nil
return changed, false, nil
}
// Invalidate block checksum.
@ -441,7 +441,7 @@ func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed bool, er
// Increment number of operations until snapshot is required.
if err := f.incrementOpN(); err != nil {
return false, errors.Wrap(err, "incrementing")
return false, false, errors.Wrap(err, "incrementing")
}
// Get the row from cache or fragment.storage.
@ -449,11 +449,12 @@ func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed bool, er
row.ClearBit(columnID)
// Update the cache.
f.cache.Add(rowID, row.Count())
c := row.Count()
f.cache.Add(rowID, c)
f.stats.Count("clearBit", 1, 1.0)
return changed, nil
return changed, c > 0, nil
}
func (f *Fragment) bit(rowID, columnID uint64) (bool, error) {
@ -501,7 +502,7 @@ func (f *Fragment) setValue(columnID uint64, bitDepth uint, value uint64) (chang
changed = true
}
} else {
if c, err := f.unprotectedClearBit(uint64(i), columnID); err != nil {
if c, _, err := f.unprotectedClearBit(uint64(i), columnID); err != nil {
return changed, err
} else if c {
changed = true
@ -1285,7 +1286,7 @@ func (f *Fragment) mergeBlock(id int, data []pairSet) (sets, clears []pairSet, e
// Clear local bits.
for i := range clears[0].columnIDs {
if _, err := f.unprotectedClearBit(clears[0].rowIDs[i], (f.slice*SliceWidth)+clears[0].columnIDs[i]); err != nil {
if _, _, err := f.unprotectedClearBit(clears[0].rowIDs[i], (f.slice*SliceWidth)+clears[0].columnIDs[i]); err != nil {
return nil, nil, errors.Wrap(err, "clearing")
}
}

View file

@ -75,7 +75,7 @@ func TestFragment_ClearBit(t *testing.T) {
t.Fatal(err)
} else if _, err := f.setBit(1000, 2); err != nil {
t.Fatal(err)
} else if _, err := f.clearBit(1000, 1); err != nil {
} else if _, _, err := f.clearBit(1000, 1); err != nil {
t.Fatal(err)
}
@ -532,7 +532,7 @@ func TestFragment_Snapshot(t *testing.T) {
t.Fatal(err)
} else if _, err := f.setBit(1000, 2); err != nil {
t.Fatal(err)
} else if _, err := f.clearBit(1000, 1); err != nil {
} else if _, _, err := f.clearBit(1000, 1); err != nil {
t.Fatal(err)
}
@ -756,7 +756,7 @@ func TestFragment_TopN_CacheSize(t *testing.T) {
}
// Create view.
view, err := field.CreateViewIfNotExists(ViewStandard)
view, err := field.CreateViewIfNotExists(viewTimeKey{name: ViewStandard})
if err != nil {
t.Fatal(err)
}
@ -922,7 +922,7 @@ func TestFragment_RankCache_Persistence(t *testing.T) {
}
// Create view.
view, err := field.CreateViewIfNotExists(ViewStandard)
view, err := field.CreateViewIfNotExists(viewTimeKey{name: ViewStandard})
if err != nil {
t.Fatal(err)
}
@ -973,7 +973,7 @@ func TestFragment_WriteTo_ReadFrom(t *testing.T) {
t.Fatal(err)
} else if _, err := f0.setBit(1000, 2); err != nil {
t.Fatal(err)
} else if _, err := f0.clearBit(1000, 1); err != nil {
} else if _, _, err := f0.clearBit(1000, 1); err != nil {
t.Fatal(err)
}

View file

@ -247,7 +247,7 @@ func (h *Holder) ApplySchema(schema *internal.Schema) error {
}
// Create views that don't exist.
for _, v := range f.Views {
_, err := field.CreateViewIfNotExists(v)
_, err := field.CreateViewIfNotExists(viewTimeKey{name: v})
if err != nil {
return errors.Wrap(err, "creating view")
}
@ -744,7 +744,7 @@ func (s *HolderSyncer) syncFragment(index, field, view string, slice uint64) err
}
// Ensure view exists locally.
v, err := f.CreateViewIfNotExists(view)
v, err := f.CreateViewIfNotExists(viewTimeKey{name: view})
if err != nil {
return errors.Wrap(err, "creating view")
}

View file

@ -671,6 +671,7 @@ type CreateViewMessage struct {
Index string `protobuf:"bytes,1,opt,name=Index,proto3" json:"Index,omitempty"`
Field string `protobuf:"bytes,2,opt,name=Field,proto3" json:"Field,omitempty"`
View string `protobuf:"bytes,3,opt,name=View,proto3" json:"View,omitempty"`
Type string `protobuf:"bytes,4,opt,name=Type,proto3" json:"Type,omitempty"`
}
func (m *CreateViewMessage) Reset() { *m = CreateViewMessage{} }
@ -699,6 +700,13 @@ func (m *CreateViewMessage) GetView() string {
return ""
}
func (m *CreateViewMessage) GetType() string {
if m != nil {
return m.Type
}
return ""
}
type DeleteViewMessage struct {
Index string `protobuf:"bytes,1,opt,name=Index,proto3" json:"Index,omitempty"`
Field string `protobuf:"bytes,2,opt,name=Field,proto3" json:"Field,omitempty"`
@ -1823,6 +1831,12 @@ func (m *CreateViewMessage) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintPrivate(dAtA, i, uint64(len(m.View)))
i += copy(dAtA[i:], m.View)
}
if len(m.Type) > 0 {
dAtA[i] = 0x22
i++
i = encodeVarintPrivate(dAtA, i, uint64(len(m.Type)))
i += copy(dAtA[i:], m.Type)
}
return i, nil
}
@ -2520,6 +2534,10 @@ func (m *CreateViewMessage) Size() (n int) {
if l > 0 {
n += 1 + l + sovPrivate(uint64(l))
}
l = len(m.Type)
if l > 0 {
n += 1 + l + sovPrivate(uint64(l))
}
return n
}
@ -5539,6 +5557,35 @@ func (m *CreateViewMessage) Unmarshal(dAtA []byte) error {
}
m.View = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPrivate
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthPrivate
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Type = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipPrivate(dAtA[iNdEx:])
@ -6681,70 +6728,70 @@ var (
func init() { proto.RegisterFile("private.proto", fileDescriptorPrivate) }
var fileDescriptorPrivate = []byte{
// 1028 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcb, 0x72, 0x1c, 0x35,
0x17, 0xfe, 0xfb, 0x32, 0xe3, 0x99, 0xe3, 0x8c, 0x7f, 0x5b, 0x01, 0xd3, 0xa1, 0x28, 0x67, 0x50,
0xa5, 0x2a, 0x26, 0x0b, 0x57, 0x48, 0x36, 0xdc, 0x52, 0xe5, 0xb2, 0xc7, 0x40, 0x03, 0x36, 0xa0,
0xb6, 0xb3, 0xcb, 0x42, 0x99, 0x51, 0x25, 0x5d, 0xee, 0x69, 0x35, 0xdd, 0x6a, 0xdb, 0x93, 0x05,
0x5b, 0xd8, 0xb0, 0xa7, 0x78, 0x12, 0x1e, 0x81, 0x25, 0x8f, 0x40, 0x99, 0x17, 0xa1, 0x74, 0xa4,
0xbe, 0xd8, 0x33, 0x8e, 0x53, 0x86, 0x9d, 0xce, 0xfd, 0xd3, 0xd1, 0x77, 0x24, 0xc1, 0x20, 0xcb,
0xe3, 0x13, 0xae, 0xc4, 0x56, 0x96, 0x4b, 0x25, 0x49, 0x2f, 0x4e, 0x95, 0xc8, 0x53, 0x9e, 0xd0,
0xbb, 0xd0, 0x0f, 0xd3, 0x89, 0x38, 0xdb, 0x17, 0x8a, 0x13, 0x02, 0xfe, 0xd7, 0x62, 0x56, 0x04,
0xde, 0xd0, 0xd9, 0xec, 0x31, 0x5c, 0xd3, 0xdf, 0x1d, 0xb8, 0xf5, 0x79, 0x2c, 0x92, 0xc9, 0xb7,
0x99, 0x8a, 0x65, 0x5a, 0x90, 0xf7, 0xa0, 0xbf, 0xcb, 0xc7, 0x2f, 0xc5, 0xe1, 0x2c, 0x13, 0xe8,
0xd9, 0x67, 0x8d, 0xa2, 0xb6, 0x46, 0xf1, 0x2b, 0x11, 0xf8, 0x43, 0x67, 0x73, 0xc0, 0x1a, 0x05,
0x19, 0xc2, 0xf2, 0x61, 0x3c, 0x15, 0xdf, 0x97, 0x3c, 0x55, 0xe5, 0x34, 0xe8, 0x60, 0x74, 0x5b,
0xa5, 0x21, 0x60, 0xe2, 0x1e, 0x9a, 0x70, 0x4d, 0x56, 0xc1, 0xdb, 0x8f, 0xd3, 0xa0, 0x3f, 0x74,
0x36, 0x3d, 0xa6, 0x97, 0xa8, 0xe1, 0x67, 0x01, 0x58, 0x0d, 0x3f, 0xab, 0xa1, 0x2f, 0xb7, 0xa0,
0x53, 0x58, 0x09, 0xa7, 0x99, 0xcc, 0x15, 0x13, 0x45, 0x26, 0xd3, 0x02, 0x33, 0xed, 0xe5, 0x79,
0xe0, 0x60, 0x72, 0xbd, 0xa4, 0x3f, 0xc2, 0xea, 0x4e, 0x22, 0xc7, 0xc7, 0x23, 0xae, 0x38, 0x13,
0x3f, 0x94, 0xa2, 0x50, 0xe4, 0x2d, 0xe8, 0x60, 0x4f, 0xac, 0x9f, 0x11, 0xb4, 0x16, 0xfb, 0x10,
0xb8, 0x46, 0x8b, 0x82, 0xd6, 0x62, 0x3c, 0x76, 0xc2, 0x67, 0x46, 0xd0, 0xda, 0x28, 0x89, 0xc7,
0xa6, 0x03, 0x3e, 0x33, 0x82, 0xc6, 0xf8, 0x34, 0x16, 0xa7, 0x76, 0xdb, 0xb8, 0xa6, 0x21, 0xac,
0xb5, 0xea, 0x5b, 0x98, 0xeb, 0xd0, 0x65, 0xf2, 0x34, 0x1c, 0x15, 0x81, 0x33, 0xf4, 0x36, 0x7d,
0x66, 0x25, 0x6c, 0xae, 0x4c, 0xca, 0x69, 0xaa, 0x4d, 0x2e, 0x9a, 0x1a, 0x05, 0xbd, 0x03, 0x1d,
0xec, 0xb4, 0xde, 0x65, 0x13, 0xab, 0x97, 0xf4, 0x27, 0x07, 0xfa, 0xfb, 0xfc, 0x0c, 0x61, 0x14,
0xe4, 0x09, 0xf4, 0x22, 0xc5, 0xd3, 0x09, 0xcf, 0x27, 0xe8, 0xb4, 0xfc, 0xe8, 0xfd, 0xad, 0x8a,
0x10, 0x5b, 0xb5, 0xdb, 0x56, 0xe5, 0xb3, 0x97, 0xaa, 0x7c, 0xc6, 0xea, 0x90, 0x77, 0x3f, 0x85,
0xc1, 0x05, 0x93, 0xae, 0x77, 0x2c, 0x66, 0x55, 0x57, 0x8f, 0xc5, 0x4c, 0xef, 0xff, 0x84, 0x27,
0xa5, 0xc0, 0x5e, 0xf9, 0xcc, 0x08, 0x9f, 0xb8, 0x1f, 0x39, 0x74, 0x1b, 0xc8, 0x6e, 0x2e, 0xb8,
0x12, 0x58, 0x64, 0x5f, 0x14, 0x05, 0x7f, 0x21, 0xae, 0xee, 0xb8, 0xe9, 0xa2, 0xdb, 0xea, 0x22,
0x7d, 0x00, 0x64, 0x24, 0x12, 0xa1, 0x84, 0xe5, 0xed, 0x6b, 0x32, 0xd0, 0xa8, 0xaa, 0x76, 0xbd,
0x2f, 0xb9, 0x0f, 0xbe, 0x1e, 0x02, 0x2c, 0xb6, 0xfc, 0xe8, 0x76, 0xd3, 0x91, 0x7a, 0x3e, 0x18,
0x3a, 0xd0, 0xa4, 0x4a, 0x8a, 0x0c, 0xb8, 0x76, 0x0b, 0x0b, 0x48, 0xf3, 0xc0, 0x96, 0xf2, 0xb0,
0xd4, 0x7a, 0x53, 0xaa, 0x3d, 0x68, 0xb6, 0xda, 0x76, 0xb5, 0xdd, 0x9b, 0x56, 0xa3, 0xcf, 0xac,
0x56, 0xf3, 0xef, 0x80, 0x4f, 0x85, 0x8d, 0xc1, 0x75, 0x0d, 0xc5, 0xbd, 0x1e, 0x8a, 0x4e, 0xaf,
0x39, 0xab, 0xef, 0x07, 0x4f, 0xa7, 0x47, 0x81, 0x3e, 0x86, 0x6e, 0x34, 0x7e, 0x29, 0xa6, 0x9c,
0x7c, 0x00, 0x4b, 0x88, 0x43, 0x14, 0x96, 0x56, 0xff, 0xbf, 0xd4, 0x44, 0x56, 0xd9, 0xe9, 0xc8,
0xe2, 0x5f, 0x88, 0xe9, 0x3e, 0x74, 0xb1, 0x7a, 0x11, 0xf8, 0x97, 0xd3, 0xa0, 0x9e, 0x59, 0x33,
0xdd, 0x03, 0xef, 0x88, 0x85, 0x7a, 0x5c, 0x10, 0x41, 0x95, 0xc5, 0x4a, 0x3a, 0xf7, 0x97, 0xb2,
0x50, 0xb6, 0x1b, 0xb8, 0xd6, 0xba, 0xef, 0x64, 0xae, 0xb0, 0xf5, 0x03, 0x86, 0x6b, 0xfa, 0x0c,
0xfc, 0x03, 0x39, 0x11, 0x64, 0x05, 0xdc, 0x70, 0x64, 0x73, 0xb8, 0xe1, 0x88, 0xdc, 0xc5, 0xf4,
0xb6, 0x35, 0x83, 0x06, 0xc4, 0x11, 0x0b, 0x19, 0x16, 0xbe, 0x07, 0x83, 0xb0, 0xd8, 0x95, 0x32,
0x9f, 0xc4, 0x29, 0x57, 0x32, 0xb7, 0x17, 0xe7, 0x45, 0x25, 0xdd, 0x86, 0x55, 0x9d, 0x3e, 0x52,
0x5c, 0xd5, 0x84, 0x5f, 0x87, 0xae, 0xd6, 0xd5, 0xe5, 0xac, 0x84, 0x94, 0xd7, 0x7e, 0xd5, 0x09,
0xa2, 0x40, 0xbf, 0x31, 0x19, 0xf6, 0x4e, 0x44, 0xaa, 0x5a, 0x0c, 0x40, 0x19, 0x13, 0x0c, 0x98,
0x11, 0x08, 0x35, 0x5b, 0xb1, 0x98, 0x57, 0x1a, 0xcc, 0x5a, 0xcb, 0xd0, 0x46, 0x7f, 0x71, 0x00,
0x2a, 0x40, 0x65, 0x51, 0x87, 0x38, 0x57, 0x87, 0x90, 0x0f, 0x5b, 0xd7, 0xc7, 0xfc, 0x80, 0xd4,
0x26, 0xd6, 0xba, 0x64, 0x36, 0x2b, 0x5a, 0x58, 0x96, 0xaf, 0x36, 0xfe, 0x46, 0x6f, 0x8f, 0x89,
0xd3, 0x18, 0x06, 0xbb, 0x49, 0x59, 0x28, 0x91, 0x5b, 0x44, 0xfa, 0x9a, 0x33, 0x8a, 0xba, 0x3f,
0x8d, 0x62, 0x71, 0x8b, 0xc8, 0x3d, 0xe8, 0x68, 0xa4, 0x86, 0x9b, 0xf3, 0xdb, 0x30, 0x46, 0xfa,
0x14, 0x7a, 0x3b, 0x51, 0xf8, 0x45, 0x2e, 0xcb, 0x6c, 0x21, 0xf3, 0xaa, 0xd7, 0xc7, 0x9d, 0x7f,
0x7d, 0xbc, 0xb9, 0xd7, 0xc7, 0xaf, 0x5f, 0x1f, 0x1a, 0xc1, 0x9a, 0xb9, 0x12, 0xf4, 0x48, 0xdc,
0xe4, 0x46, 0xa8, 0x9e, 0x06, 0xaf, 0xf5, 0x34, 0x44, 0xb0, 0x66, 0x26, 0xff, 0xbf, 0x4c, 0xfa,
0x9b, 0x0b, 0x6b, 0x4c, 0x14, 0xf1, 0x2b, 0x11, 0xa6, 0x85, 0xca, 0xcb, 0xb1, 0x1e, 0x70, 0x1d,
0xff, 0x95, 0x7c, 0x6e, 0xbb, 0xed, 0x31, 0x23, 0xbc, 0x09, 0x99, 0xc8, 0x43, 0x58, 0xbe, 0x3c,
0x00, 0xf3, 0xae, 0x6d, 0x17, 0xf2, 0x10, 0x96, 0x22, 0x59, 0xe6, 0x9a, 0x49, 0x66, 0xbc, 0x5b,
0x97, 0x8e, 0x41, 0x66, 0xcc, 0xac, 0x72, 0x6b, 0x51, 0xa9, 0xf3, 0x7a, 0x2a, 0x91, 0x27, 0x97,
0xa8, 0x14, 0x74, 0x31, 0xe0, 0x9d, 0x26, 0xe0, 0x82, 0x99, 0x5d, 0xf4, 0xa6, 0x3f, 0x3b, 0x70,
0xab, 0x0d, 0xe1, 0x8d, 0x66, 0xa3, 0x3e, 0x11, 0x77, 0xe1, 0x89, 0x78, 0x8b, 0x4e, 0xc4, 0x6f,
0x4e, 0xa4, 0x79, 0xe5, 0x3a, 0xed, 0x57, 0xee, 0x18, 0xee, 0xcc, 0x1d, 0xd3, 0xae, 0x9c, 0x66,
0x9a, 0x0f, 0xff, 0xe2, 0xb8, 0xf4, 0xad, 0x91, 0xe7, 0xf6, 0xa0, 0xfa, 0xcc, 0x08, 0xf4, 0x63,
0x78, 0x3b, 0x12, 0xaa, 0x75, 0x48, 0x15, 0xdb, 0x86, 0xe0, 0x1d, 0x88, 0xd3, 0x2b, 0xb6, 0xaf,
0x4d, 0xf4, 0x33, 0x08, 0x8e, 0xb2, 0x09, 0x57, 0xe2, 0x46, 0xd1, 0x3b, 0xd0, 0x3b, 0x94, 0x99,
0x4c, 0xe4, 0x8b, 0xd9, 0x35, 0x53, 0x1f, 0xc0, 0x92, 0xb9, 0x22, 0xcd, 0xc7, 0xa7, 0xcf, 0x2a,
0x91, 0xde, 0xd6, 0x84, 0x1e, 0xf3, 0x64, 0x5c, 0x26, 0x1a, 0x86, 0xfe, 0x01, 0x15, 0x3b, 0xab,
0x7f, 0x9c, 0x6f, 0x38, 0x7f, 0x9e, 0x6f, 0x38, 0x7f, 0x9d, 0x6f, 0x38, 0xbf, 0xfe, 0xbd, 0xf1,
0xbf, 0xe7, 0x5d, 0xfc, 0xf9, 0x3e, 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x25, 0x40, 0x21,
0x0a, 0x0b, 0x00, 0x00,
// 1034 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x73, 0xdb, 0x44,
0x14, 0x47, 0x96, 0xec, 0xd8, 0x2f, 0x75, 0x48, 0xb6, 0x10, 0x54, 0x86, 0x49, 0xcd, 0x4e, 0x67,
0x1a, 0x7a, 0xc8, 0x94, 0xf6, 0xc2, 0xbf, 0xce, 0x64, 0x62, 0x07, 0x10, 0x90, 0x00, 0xab, 0xa4,
0xb7, 0x1e, 0xb6, 0xf6, 0x4e, 0xaa, 0x89, 0xac, 0x15, 0xd2, 0x2a, 0x89, 0x7b, 0xe0, 0x0a, 0x17,
0xee, 0x0c, 0x9f, 0x84, 0x8f, 0xc0, 0x91, 0x8f, 0xc0, 0x84, 0x2f, 0xc2, 0xec, 0xdb, 0xd5, 0x9f,
0xc4, 0x4e, 0xd3, 0x09, 0xbd, 0xed, 0xfb, 0xff, 0xd3, 0x7b, 0xbf, 0x7d, 0x2b, 0xe8, 0xa7, 0x59,
0x74, 0xc2, 0x95, 0xd8, 0x4a, 0x33, 0xa9, 0x24, 0xe9, 0x46, 0x89, 0x12, 0x59, 0xc2, 0x63, 0x7a,
0x17, 0x7a, 0x41, 0x32, 0x11, 0x67, 0x7b, 0x42, 0x71, 0x42, 0xc0, 0xfb, 0x56, 0xcc, 0x72, 0xdf,
0x1d, 0x38, 0x9b, 0x5d, 0x86, 0x67, 0xfa, 0xa7, 0x03, 0xb7, 0xbe, 0x8c, 0x44, 0x3c, 0xf9, 0x3e,
0x55, 0x91, 0x4c, 0x72, 0xf2, 0x01, 0xf4, 0x86, 0x7c, 0xfc, 0x42, 0x1c, 0xcc, 0x52, 0x81, 0x9e,
0x3d, 0x56, 0x2b, 0x2a, 0x6b, 0x18, 0xbd, 0x14, 0xbe, 0x37, 0x70, 0x36, 0xfb, 0xac, 0x56, 0x90,
0x01, 0x2c, 0x1f, 0x44, 0x53, 0xf1, 0x63, 0xc1, 0x13, 0x55, 0x4c, 0xfd, 0x36, 0x46, 0x37, 0x55,
0x1a, 0x02, 0x26, 0xee, 0xa2, 0x09, 0xcf, 0x64, 0x15, 0xdc, 0xbd, 0x28, 0xf1, 0x7b, 0x03, 0x67,
0xd3, 0x65, 0xfa, 0x88, 0x1a, 0x7e, 0xe6, 0x83, 0xd5, 0xf0, 0xb3, 0x0a, 0xfa, 0x72, 0x03, 0x3a,
0x85, 0x95, 0x60, 0x9a, 0xca, 0x4c, 0x31, 0x91, 0xa7, 0x32, 0xc9, 0x31, 0xd3, 0x6e, 0x96, 0xf9,
0x0e, 0x26, 0xd7, 0x47, 0xfa, 0x33, 0xac, 0xee, 0xc4, 0x72, 0x7c, 0x3c, 0xe2, 0x8a, 0x33, 0xf1,
0x53, 0x21, 0x72, 0x45, 0xde, 0x81, 0x36, 0xf6, 0xc4, 0xfa, 0x19, 0x41, 0x6b, 0xb1, 0x0f, 0x7e,
0xcb, 0x68, 0x51, 0xd0, 0x5a, 0x8c, 0xc7, 0x4e, 0x78, 0xcc, 0x08, 0x5a, 0x1b, 0xc6, 0xd1, 0xd8,
0x74, 0xc0, 0x63, 0x46, 0xd0, 0x18, 0x9f, 0x46, 0xe2, 0xd4, 0x7e, 0x36, 0x9e, 0x69, 0x00, 0x6b,
0x8d, 0xfa, 0x16, 0xe6, 0x3a, 0x74, 0x98, 0x3c, 0x0d, 0x46, 0xb9, 0xef, 0x0c, 0xdc, 0x4d, 0x8f,
0x59, 0x09, 0x9b, 0x2b, 0xe3, 0x62, 0x9a, 0x68, 0x53, 0x0b, 0x4d, 0xb5, 0x82, 0xde, 0x81, 0x36,
0x76, 0x5a, 0x7f, 0x65, 0x1d, 0xab, 0x8f, 0xf4, 0x17, 0x07, 0x7a, 0x7b, 0xfc, 0x0c, 0x61, 0xe4,
0xe4, 0x09, 0x74, 0x43, 0xc5, 0x93, 0x09, 0xcf, 0x26, 0xe8, 0xb4, 0xfc, 0xe8, 0xc3, 0xad, 0x92,
0x10, 0x5b, 0x95, 0xdb, 0x56, 0xe9, 0xb3, 0x9b, 0xa8, 0x6c, 0xc6, 0xaa, 0x90, 0xf7, 0x3f, 0x87,
0xfe, 0x05, 0x93, 0xae, 0x77, 0x2c, 0x66, 0x65, 0x57, 0x8f, 0xc5, 0x4c, 0x7f, 0xff, 0x09, 0x8f,
0x0b, 0x81, 0xbd, 0xf2, 0x98, 0x11, 0x3e, 0x6b, 0x7d, 0xe2, 0xd0, 0x6d, 0x20, 0xc3, 0x4c, 0x70,
0x25, 0xb0, 0xc8, 0x9e, 0xc8, 0x73, 0x7e, 0x24, 0xae, 0xee, 0xb8, 0xe9, 0x62, 0xab, 0xd1, 0x45,
0xfa, 0x00, 0xc8, 0x48, 0xc4, 0x42, 0x09, 0xcb, 0xdb, 0x57, 0x64, 0xa0, 0x61, 0x59, 0xed, 0x7a,
0x5f, 0x72, 0x1f, 0x3c, 0x7d, 0x09, 0xb0, 0xd8, 0xf2, 0xa3, 0xdb, 0x75, 0x47, 0xaa, 0xfb, 0xc1,
0xd0, 0x81, 0xc6, 0x65, 0x52, 0x64, 0xc0, 0xb5, 0x9f, 0xb0, 0x80, 0x34, 0x0f, 0x6c, 0x29, 0x17,
0x4b, 0xad, 0xd7, 0xa5, 0x9a, 0x17, 0xcd, 0x56, 0xdb, 0x2e, 0x3f, 0xf7, 0xa6, 0xd5, 0xe8, 0x33,
0xab, 0xd5, 0xfc, 0xdb, 0xe7, 0x53, 0x61, 0x63, 0xf0, 0x5c, 0x41, 0x69, 0x5d, 0x0f, 0x45, 0xa7,
0xd7, 0x9c, 0xd5, 0xfb, 0xc1, 0xd5, 0xe9, 0x51, 0xa0, 0x8f, 0xa1, 0x13, 0x8e, 0x5f, 0x88, 0x29,
0x27, 0x1f, 0xc1, 0x12, 0xe2, 0x10, 0xb9, 0xa5, 0xd5, 0xdb, 0x97, 0x9a, 0xc8, 0x4a, 0x3b, 0x1d,
0x59, 0xfc, 0x0b, 0x31, 0xdd, 0x87, 0x0e, 0x56, 0xcf, 0x7d, 0xef, 0x72, 0x1a, 0xd4, 0x33, 0x6b,
0xa6, 0xbb, 0xe0, 0x1e, 0xb2, 0x40, 0x5f, 0x17, 0x44, 0x50, 0x66, 0xb1, 0x92, 0xce, 0xfd, 0xb5,
0xcc, 0x95, 0xed, 0x06, 0x9e, 0xb5, 0xee, 0x07, 0x99, 0x29, 0x6c, 0x7d, 0x9f, 0xe1, 0x99, 0x3e,
0x03, 0x6f, 0x5f, 0x4e, 0x04, 0x59, 0x81, 0x56, 0x30, 0xb2, 0x39, 0x5a, 0xc1, 0x88, 0xdc, 0xc5,
0xf4, 0xb6, 0x35, 0xfd, 0x1a, 0xc4, 0x21, 0x0b, 0x18, 0x16, 0xbe, 0x07, 0xfd, 0x20, 0x1f, 0x4a,
0x99, 0x4d, 0xa2, 0x84, 0x2b, 0x99, 0xd9, 0xc5, 0x79, 0x51, 0x49, 0xb7, 0x61, 0x55, 0xa7, 0x0f,
0x15, 0x57, 0x15, 0xe1, 0xd7, 0xa1, 0xa3, 0x75, 0x55, 0x39, 0x2b, 0x21, 0xe5, 0xb5, 0x5f, 0x39,
0x41, 0x14, 0xe8, 0x77, 0x26, 0xc3, 0xee, 0x89, 0x48, 0x54, 0x83, 0x01, 0x28, 0x63, 0x82, 0x3e,
0x33, 0x02, 0xa1, 0xe6, 0x53, 0x2c, 0xe6, 0x95, 0x1a, 0xb3, 0xd6, 0x32, 0xb4, 0xd1, 0xdf, 0x1c,
0x80, 0x12, 0x50, 0x91, 0x57, 0x21, 0xce, 0xd5, 0x21, 0xe4, 0xe3, 0xc6, 0xfa, 0x98, 0xbf, 0x20,
0x95, 0x89, 0x35, 0x96, 0xcc, 0x66, 0x49, 0x0b, 0xcb, 0xf2, 0xd5, 0xda, 0xdf, 0xe8, 0xed, 0x98,
0x38, 0x8d, 0xa0, 0x3f, 0x8c, 0x8b, 0x5c, 0x89, 0xcc, 0x22, 0xd2, 0x6b, 0xce, 0x28, 0xaa, 0xfe,
0xd4, 0x8a, 0xc5, 0x2d, 0x22, 0xf7, 0xa0, 0xad, 0x91, 0x1a, 0x6e, 0xce, 0x7f, 0x86, 0x31, 0xd2,
0xa7, 0xd0, 0xdd, 0x09, 0x83, 0xaf, 0x32, 0x59, 0xa4, 0x0b, 0x99, 0x57, 0xbe, 0x3e, 0xad, 0xf9,
0xd7, 0xc7, 0x9d, 0x7b, 0x7d, 0xbc, 0xea, 0xf5, 0xa1, 0x47, 0xb0, 0x66, 0x56, 0x82, 0xbe, 0x12,
0x37, 0xd9, 0x08, 0xe5, 0xd3, 0xe0, 0xd6, 0x4f, 0x43, 0x05, 0xc6, 0xab, 0xc1, 0xd0, 0x10, 0xd6,
0xcc, 0x36, 0x78, 0x83, 0x85, 0xe8, 0x1f, 0x2d, 0x58, 0x63, 0x22, 0x8f, 0x5e, 0x8a, 0x20, 0xc9,
0x55, 0x56, 0x8c, 0xf5, 0xa5, 0xd7, 0xf1, 0xdf, 0xc8, 0xe7, 0x76, 0x02, 0x2e, 0x33, 0xc2, 0xeb,
0x10, 0x8c, 0x3c, 0x84, 0xe5, 0xcb, 0x97, 0x62, 0xde, 0xb5, 0xe9, 0x42, 0x1e, 0xc2, 0x52, 0x28,
0x8b, 0x4c, 0xb3, 0xcb, 0x5c, 0xf9, 0xc6, 0x22, 0x32, 0xc8, 0x8c, 0x99, 0x95, 0x6e, 0x0d, 0x7a,
0xb5, 0x5f, 0x4d, 0x2f, 0xf2, 0xe4, 0x12, 0xbd, 0xfc, 0x0e, 0x06, 0xbc, 0x57, 0x07, 0x5c, 0x30,
0xb3, 0x8b, 0xde, 0xf4, 0x57, 0x07, 0x6e, 0x35, 0x21, 0xbc, 0xd6, 0x7d, 0xa9, 0x26, 0xd2, 0x5a,
0x38, 0x11, 0x77, 0xd1, 0x44, 0xbc, 0xc6, 0xe8, 0xab, 0x97, 0xaf, 0xdd, 0x7c, 0xf9, 0x8e, 0xe1,
0xce, 0xdc, 0x98, 0x86, 0x72, 0x9a, 0x6a, 0x3e, 0xfc, 0x8f, 0x71, 0xe9, 0x4d, 0x92, 0x65, 0x76,
0x50, 0x3d, 0x66, 0x04, 0xfa, 0x29, 0xbc, 0x1b, 0x0a, 0xd5, 0x18, 0x52, 0xc9, 0xb6, 0x01, 0xb8,
0xfb, 0xe2, 0xf4, 0x8a, 0xcf, 0xd7, 0x26, 0xfa, 0x05, 0xf8, 0x87, 0xe9, 0x84, 0x2b, 0x71, 0xa3,
0xe8, 0x1d, 0xe8, 0x1e, 0xc8, 0x54, 0xc6, 0xf2, 0x68, 0x76, 0xcd, 0x26, 0xf0, 0x61, 0xc9, 0xac,
0x4d, 0xf3, 0x33, 0xd4, 0x63, 0xa5, 0x48, 0x6f, 0x6b, 0x42, 0x8f, 0x79, 0x3c, 0x2e, 0x62, 0x0d,
0x43, 0xff, 0x15, 0xe5, 0x3b, 0xab, 0x7f, 0x9d, 0x6f, 0x38, 0x7f, 0x9f, 0x6f, 0x38, 0xff, 0x9c,
0x6f, 0x38, 0xbf, 0xff, 0xbb, 0xf1, 0xd6, 0xf3, 0x0e, 0xfe, 0x0d, 0x3f, 0xfe, 0x2f, 0x00, 0x00,
0xff, 0xff, 0x41, 0xae, 0x0a, 0x68, 0x1e, 0x0b, 0x00, 0x00,
}

View file

@ -126,6 +126,7 @@ message CreateViewMessage {
string Index = 1;
string Field = 2;
string View = 3;
string Type = 4;
}
message DeleteViewMessage {

View file

@ -27,7 +27,7 @@ import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import encoding_binary "encoding/binary"
import binary "encoding/binary"
import io "io"
@ -800,7 +800,7 @@ func (m *Attr) MarshalTo(dAtA []byte) (int, error) {
if m.FloatValue != 0 {
dAtA[i] = 0x31
i++
encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.FloatValue))))
binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.FloatValue))))
i += 8
}
return i, nil
@ -2317,7 +2317,7 @@ func (m *Attr) Unmarshal(dAtA []byte) error {
if (iNdEx + 8) > l {
return io.ErrUnexpectedEOF
}
v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:]))
v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:]))
iNdEx += 8
m.FloatValue = float64(math.Float64frombits(v))
default:

View file

@ -458,7 +458,7 @@ func (s *Server) ReceiveMessage(pb proto.Message) error {
if f == nil {
return fmt.Errorf("Local Field not found: %s", obj.Field)
}
_, _, err := f.createViewIfNotExistsBase(obj.View)
_, _, err := f.createViewIfNotExistsBase(viewTimeKey{name: obj.View})
if err != nil {
return err
}

View file

@ -96,7 +96,7 @@ func (h *Holder) MustCreateRankedFragmentIfNotExists(index, field, view string,
if err != nil {
panic(err)
}
v, err := f.CreateViewIfNotExists(view)
v, err := f.CreateViewIfNotExists(viewTimeKey{name: view})
if err != nil {
panic(err)
}
@ -152,7 +152,7 @@ func (h *Holder) ClearBit(index, field string, rowID, columnID uint64) {
if err != nil {
panic(err)
}
f.ClearBit(rowID, columnID, nil)
f.ClearBit(rowID, columnID)
}
// MustSetBits sets columns on a row. Panic on error.

27
time.go
View file

@ -79,28 +79,33 @@ func ParseTimeQuantum(v string) (TimeQuantum, error) {
return q, nil
}
type viewTimeKey struct {
name string
quantum rune
}
// viewByTimeUnit returns the view name for time with a given quantum unit.
func viewByTimeUnit(name string, t time.Time, unit rune) string {
func viewByTimeUnit(name string, t time.Time, unit rune) viewTimeKey {
switch unit {
case 'Y':
return fmt.Sprintf("%s_%s", name, t.Format("2006"))
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("2006")), quantum: unit}
case 'M':
return fmt.Sprintf("%s_%s", name, t.Format("200601"))
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("200601")), quantum: unit}
case 'D':
return fmt.Sprintf("%s_%s", name, t.Format("20060102"))
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("20060102")), quantum: unit}
case 'H':
return fmt.Sprintf("%s_%s", name, t.Format("2006010215"))
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("2006010215")), quantum: unit}
default:
return ""
return viewTimeKey{}
}
}
// viewsByTime returns a list of views for a given timestamp.
func viewsByTime(name string, t time.Time, q TimeQuantum) []string {
a := make([]string, 0, len(q))
func viewsByTime(name string, t time.Time, q TimeQuantum) []viewTimeKey {
a := make([]viewTimeKey, 0, len(q))
for _, unit := range q {
view := viewByTimeUnit(name, t, unit)
if view == "" {
if view.name == "" {
continue
}
a = append(a, view)
@ -109,7 +114,7 @@ func viewsByTime(name string, t time.Time, q TimeQuantum) []string {
}
// viewsByTimeRange returns a list of views to traverse to query a time range.
func viewsByTimeRange(name string, start, end time.Time, q TimeQuantum) []string {
func viewsByTimeRange(name string, start, end time.Time, q TimeQuantum) []viewTimeKey {
t := start
// Save flags for performance.
@ -118,7 +123,7 @@ func viewsByTimeRange(name string, start, end time.Time, q TimeQuantum) []string
hasDay := q.HasDay()
hasHour := q.HasHour()
var results []string
var results []viewTimeKey
// Walk up from smallest units to largest units.
if hasHour || hasDay || hasMonth {

View file

@ -42,23 +42,23 @@ func TestViewByTimeUnit(t *testing.T) {
ts := time.Date(2000, time.January, 2, 3, 4, 5, 6, time.UTC)
t.Run("Y", func(t *testing.T) {
if s := viewByTimeUnit("F", ts, 'Y'); s != "F_2000" {
t.Fatalf("unexpected name: %s", s)
if s := viewByTimeUnit("F", ts, 'Y'); s.name != "F_2000" {
t.Fatalf("unexpected name: %s", s.name)
}
})
t.Run("M", func(t *testing.T) {
if s := viewByTimeUnit("F", ts, 'M'); s != "F_200001" {
t.Fatalf("unexpected name: %s", s)
if s := viewByTimeUnit("F", ts, 'M'); s.name != "F_200001" {
t.Fatalf("unexpected name: %s", s.name)
}
})
t.Run("D", func(t *testing.T) {
if s := viewByTimeUnit("F", ts, 'D'); s != "F_20000102" {
t.Fatalf("unexpected name: %s", s)
if s := viewByTimeUnit("F", ts, 'D'); s.name != "F_20000102" {
t.Fatalf("unexpected name: %s", s.name)
}
})
t.Run("H", func(t *testing.T) {
if s := viewByTimeUnit("F", ts, 'H'); s != "F_2000010203" {
t.Fatalf("unexpected name: %s", s)
if s := viewByTimeUnit("F", ts, 'H'); s.name != "F_2000010203" {
t.Fatalf("unexpected name: %s", s.name)
}
})
}

14
view.go
View file

@ -57,9 +57,9 @@ type View struct {
// prevent sending multiple `CreateSliceMessage` messages
maxSlice uint64
broadcaster Broadcaster
stats StatsClient
broadcaster Broadcaster
stats StatsClient
viewType rune
RowAttrStore AttrStore
Logger Logger
}
@ -316,11 +316,11 @@ func (v *View) setBit(rowID, columnID uint64) (changed bool, err error) {
}
// clearBit clears a bit within the view.
func (v *View) clearBit(rowID, columnID uint64) (changed bool, err error) {
func (v *View) clearBit(rowID, columnID uint64) (changed bool, remaining bool, err error) {
slice := columnID / SliceWidth
frag, err := v.CreateFragmentIfNotExists(slice)
if err != nil {
return changed, err
frag, found := v.fragments[slice]
if !found {
return false, false, nil
}
return frag.clearBit(rowID, columnID)
}