refactored strategy for time based clearbit

This commit is contained in:
Todd Gruben 2018-06-27 18:15:44 -05:00
parent f16426b50a
commit 4970083d4d
15 changed files with 183 additions and 222 deletions

2
api.go
View file

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

View file

@ -1221,7 +1221,7 @@ func (c *Cluster) followResizeInstruction(instr *internal.ResizeInstruction) err
}
// Create view.
v, err := f.CreateViewIfNotExists(viewTimeKey{name: src.View})
v, err := f.CreateViewIfNotExists(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.name, slice)
f := e.Holder.Fragment(index, fieldName, view, slice)
if f == nil {
continue
}

View file

@ -928,6 +928,18 @@ func TestExecutor_Execute_Range(t *testing.T) {
t.Fatalf("unexpected columns: %+v", columns)
}
})
t.Run("Clear", func(t *testing.T) {
if _, err := e.Execute(context.Background(), "i", test.MustParse(`Clear( 2, f=1)`), nil, nil); err != nil {
t.Fatal(err)
}
if res, err := e.Execute(context.Background(), "i", test.MustParse(`Range(f=1, 1999-12-31T00:00, 2002-01-01T03:00)`), nil, nil); err != nil {
t.Fatal(err)
} else if columns := res[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(columns, []uint64{3, 4, 5, 6, 7}) {
t.Fatalf("unexpected columns: %+v", columns)
}
})
}
// Ensure a Range(bsiGroup) query can be executed.

119
field.go
View file

@ -252,7 +252,7 @@ func (f *Field) openViews() error {
}
name := filepath.Base(fi.Name())
view := f.newView(f.ViewPath(name), viewTimeKey{name: name})
view := f.newView(f.ViewPath(name), name)
if err := view.open(); err != nil {
return fmt.Errorf("opening view: view=%s, err=%s", view.name, err)
}
@ -559,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(vtk viewTimeKey) (*View, error) {
func (f *Field) CreateViewIfNotExists(name string) (*View, error) {
view, created, err := f.createViewIfNotExistsBase(vtk)
view, created, err := f.createViewIfNotExistsBase(name)
if err != nil {
return nil, err
}
@ -572,8 +572,7 @@ func (f *Field) CreateViewIfNotExists(vtk viewTimeKey) (*View, error) {
&internal.CreateViewMessage{
Index: f.index,
Field: f.name,
View: vtk.name,
Type: string(vtk.quantum),
View: view.name,
})
if err != nil {
return nil, errors.Wrap(err, "sending CreateView message")
@ -585,15 +584,14 @@ func (f *Field) CreateViewIfNotExists(vtk viewTimeKey) (*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(vtk viewTimeKey) (*View, bool, error) {
func (f *Field) createViewIfNotExistsBase(name string) (*View, bool, error) {
f.mu.Lock()
defer f.mu.Unlock()
if view := f.views[vtk.name]; view != nil {
if view := f.views[name]; view != nil {
return view, false, nil
}
view := f.newView(f.ViewPath(vtk.name), vtk)
view := f.newView(f.ViewPath(name), name)
if err := view.open(); err != nil {
return nil, false, errors.Wrap(err, "opening view")
@ -604,14 +602,13 @@ func (f *Field) createViewIfNotExistsBase(vtk viewTimeKey) (*View, bool, error)
return view, true, nil
}
func (f *Field) newView(path string, vtk viewTimeKey) *View {
view := NewView(path, f.index, f.name, vtk.name, f.options.CacheSize)
func (f *Field) newView(path string, name string) *View {
view := NewView(path, f.index, f.name, 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", vtk.name))
view.stats = f.Stats.WithTags(fmt.Sprintf("view:%s", name))
view.broadcaster = f.broadcaster
view.viewType = vtk.quantum
return view
}
@ -661,7 +658,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 := viewTimeKey{name: ViewStandard}
viewName := ViewStandard
// Retrieve view. Exit if it doesn't exist.
view, err := f.CreateViewIfNotExists(viewName)
@ -682,14 +679,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 _, vtk := range viewsByTime(viewName.name, *t, f.TimeQuantum()) {
view, err := f.CreateViewIfNotExists(vtk)
for _, name := range viewsByTime(viewName, *t, f.TimeQuantum()) {
view, err := f.CreateViewIfNotExists(name)
if err != nil {
return changed, errors.Wrapf(err, "creating view %s", vtk.name)
return changed, errors.Wrapf(err, "creating view %s", name)
}
if c, err := view.setBit(rowID, colID); err != nil {
return changed, errors.Wrapf(err, "setting on view %s", vtk.name)
return changed, errors.Wrapf(err, "setting on view %s", name)
} else if c {
changed = true
}
@ -700,69 +697,75 @@ 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) (changed bool, err error) {
viewName := viewTimeKey{name: ViewStandard}
viewName := ViewStandard
// Retrieve view. Exit if it doesn't exist.
view, present := f.views[viewName.name]
view, present := f.views[viewName]
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
}
process := true
anyRemaining := false
if len(f.views) == 1 { // assuming no time views
return changed, nil
}
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
}
level := 0
skipBelow := MaxInt
for _, view := range f.allTimeViewsSortedByQuantum() {
if lastLevel < len(view.name) {
level++
} else if lastLevel > len(view.name) {
level--
}
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 level < skipBelow {
if changed, err = view.clearBit(rowID, colID); err != nil {
return changed, errors.Wrapf(err, "clearing on view %s", view.name)
}
if !changed {
if level < skipBelow {
skipBelow = level + 1
}
} else {
skipBelow = MaxInt
}
}
lastLevel = len(quantumView.name)
lastLevel = len(view.name)
}
return changed, nil
}
func groupCompare(a, b string, offset int) (lt, eq bool) {
v := strings.Compare(a[:offset], b[:offset])
if len(a) > offset {
a = a[:offset]
}
if len(b) > offset {
b = b[:offset]
}
v := strings.Compare(a, b)
return v < 0, v == 0
}
func (f *Field) allTimeViewsSortedByQuantum() (me []*View) {
me = make([]*View, len(f.views), len(f.views))
prefix := ViewStandard + "_"
offset := len(ViewStandard) + 1
i := 0
for _, v := range f.views {
if v.viewType != 0 { // skip non-time views
me = append(me, v)
if len(v.name) > offset && strings.Compare(v.name[:offset], prefix) == 0 { // skip non-time views
me[i] = v
i++
}
}
me = me[:i]
year := strings.Index(me[0].name, "_") + 4
month := year + 2
day := month + 2
@ -816,7 +819,7 @@ func (f *Field) SetValue(columnID uint64, value int64) (changed bool, err error)
}
// Fetch target view.
view, err := f.CreateViewIfNotExists(viewTimeKey{name: viewBSIGroupPrefix + f.name})
view, err := f.CreateViewIfNotExists(viewBSIGroupPrefix + f.name)
if err != nil {
return false, errors.Wrap(err, "creating view")
}
@ -950,19 +953,19 @@ func (f *Field) Import(rowIDs, columnIDs []uint64, timestamps []*time.Time) erro
timestamp = timestamps[i]
}
var standard []viewTimeKey
var standard []string
if timestamp == nil {
standard = []viewTimeKey{{name: ViewStandard}}
standard = []string{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, viewTimeKey{name: ViewStandard})
standard = append(standard, ViewStandard)
}
// Attach bit to each standard view.
for _, vtk := range standard {
key := importKey{View: vtk.name, Slice: columnID / SliceWidth}
for _, name := range standard {
key := importKey{View: name, Slice: columnID / SliceWidth}
data := dataByFragment[key]
data.RowIDs = append(data.RowIDs, rowID)
data.ColumnIDs = append(data.ColumnIDs, columnID)
@ -972,7 +975,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(viewTimeKey{name: key.View})
view, err := f.CreateViewIfNotExists(key.View)
if err != nil {
return errors.Wrap(err, "creating view")
}
@ -1024,7 +1027,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(viewTimeKey{name: key.View})
view, err := f.CreateViewIfNotExists(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, bool, error) {
func (f *Fragment) clearBit(rowID, columnID uint64) (bool, error) {
f.mu.Lock()
defer f.mu.Unlock()
return f.unprotectedClearBit(rowID, columnID)
}
func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed bool, remaining bool, err error) {
func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed 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, false, errors.Wrap(err, "getting bit pos")
return false, errors.Wrap(err, "getting bit pos")
}
// Write to storage.
if changed, err = f.storage.Remove(pos); err != nil {
return false, false, errors.Wrap(err, "writing")
return false, errors.Wrap(err, "writing")
}
// Don't update the cache if nothing changed.
if !changed {
return changed, false, nil
return changed, nil
}
// Invalidate block checksum.
@ -441,7 +441,7 @@ func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed bool, re
// Increment number of operations until snapshot is required.
if err := f.incrementOpN(); err != nil {
return false, false, errors.Wrap(err, "incrementing")
return false, errors.Wrap(err, "incrementing")
}
// Get the row from cache or fragment.storage.
@ -449,12 +449,11 @@ func (f *Fragment) unprotectedClearBit(rowID, columnID uint64) (changed bool, re
row.ClearBit(columnID)
// Update the cache.
c := row.Count()
f.cache.Add(rowID, c)
f.cache.Add(rowID, row.Count())
f.stats.Count("clearBit", 1, 1.0)
return changed, c > 0, nil
return changed, nil
}
func (f *Fragment) bit(rowID, columnID uint64) (bool, error) {
@ -502,7 +501,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
@ -1286,7 +1285,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(viewTimeKey{name: ViewStandard})
view, err := field.CreateViewIfNotExists(ViewStandard)
if err != nil {
t.Fatal(err)
}
@ -922,7 +922,7 @@ func TestFragment_RankCache_Persistence(t *testing.T) {
}
// Create view.
view, err := field.CreateViewIfNotExists(viewTimeKey{name: ViewStandard})
view, err := field.CreateViewIfNotExists(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(viewTimeKey{name: v})
_, err := field.CreateViewIfNotExists(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(viewTimeKey{name: view})
v, err := f.CreateViewIfNotExists(view)
if err != nil {
return errors.Wrap(err, "creating view")
}

View file

@ -671,7 +671,6 @@ 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{} }
@ -700,13 +699,6 @@ 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"`
@ -1831,12 +1823,6 @@ 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
}
@ -2534,10 +2520,6 @@ 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
}
@ -5557,35 +5539,6 @@ 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:])
@ -6728,70 +6681,70 @@ var (
func init() { proto.RegisterFile("private.proto", fileDescriptorPrivate) }
var fileDescriptorPrivate = []byte{
// 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,
// 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,
}

View file

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

View file

@ -453,7 +453,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(viewTimeKey{name: obj.View})
_, _, err := f.createViewIfNotExistsBase(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(viewTimeKey{name: view})
v, err := f.CreateViewIfNotExists(view)
if err != nil {
panic(err)
}

27
time.go
View file

@ -79,33 +79,28 @@ 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) viewTimeKey {
func viewByTimeUnit(name string, t time.Time, unit rune) string {
switch unit {
case 'Y':
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("2006")), quantum: unit}
return fmt.Sprintf("%s_%s", name, t.Format("2006"))
case 'M':
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("200601")), quantum: unit}
return fmt.Sprintf("%s_%s", name, t.Format("200601"))
case 'D':
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("20060102")), quantum: unit}
return fmt.Sprintf("%s_%s", name, t.Format("20060102"))
case 'H':
return viewTimeKey{name: fmt.Sprintf("%s_%s", name, t.Format("2006010215")), quantum: unit}
return fmt.Sprintf("%s_%s", name, t.Format("2006010215"))
default:
return viewTimeKey{}
return ""
}
}
// viewsByTime returns a list of views for a given timestamp.
func viewsByTime(name string, t time.Time, q TimeQuantum) []viewTimeKey {
a := make([]viewTimeKey, 0, len(q))
func viewsByTime(name string, t time.Time, q TimeQuantum) []string {
a := make([]string, 0, len(q))
for _, unit := range q {
view := viewByTimeUnit(name, t, unit)
if view.name == "" {
if view == "" {
continue
}
a = append(a, view)
@ -114,7 +109,7 @@ func viewsByTime(name string, t time.Time, q TimeQuantum) []viewTimeKey {
}
// viewsByTimeRange returns a list of views to traverse to query a time range.
func viewsByTimeRange(name string, start, end time.Time, q TimeQuantum) []viewTimeKey {
func viewsByTimeRange(name string, start, end time.Time, q TimeQuantum) []string {
t := start
// Save flags for performance.
@ -123,7 +118,7 @@ func viewsByTimeRange(name string, start, end time.Time, q TimeQuantum) []viewTi
hasDay := q.HasDay()
hasHour := q.HasHour()
var results []viewTimeKey
var results []string
// 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.name != "F_2000" {
t.Fatalf("unexpected name: %s", s.name)
if s := viewByTimeUnit("F", ts, 'Y'); s != "F_2000" {
t.Fatalf("unexpected name: %s", s)
}
})
t.Run("M", func(t *testing.T) {
if s := viewByTimeUnit("F", ts, 'M'); s.name != "F_200001" {
t.Fatalf("unexpected name: %s", s.name)
if s := viewByTimeUnit("F", ts, 'M'); s != "F_200001" {
t.Fatalf("unexpected name: %s", s)
}
})
t.Run("D", func(t *testing.T) {
if s := viewByTimeUnit("F", ts, 'D'); s.name != "F_20000102" {
t.Fatalf("unexpected name: %s", s.name)
if s := viewByTimeUnit("F", ts, 'D'); s != "F_20000102" {
t.Fatalf("unexpected name: %s", s)
}
})
t.Run("H", func(t *testing.T) {
if s := viewByTimeUnit("F", ts, 'H'); s.name != "F_2000010203" {
t.Fatalf("unexpected name: %s", s.name)
if s := viewByTimeUnit("F", ts, 'H'); s != "F_2000010203" {
t.Fatalf("unexpected name: %s", s)
}
})
}

View file

@ -59,7 +59,7 @@ type View struct {
broadcaster Broadcaster
stats StatsClient
viewType rune
viewType string
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, remaining bool, err error) {
func (v *View) clearBit(rowID, columnID uint64) (changed bool, err error) {
slice := columnID / SliceWidth
frag, found := v.fragments[slice]
if !found {
return false, false, nil
return false, nil
}
return frag.clearBit(rowID, columnID)
}