memstore/list/vector_party.go (121 lines of code) (raw):
// Copyright (c) 2017-2018 Uber Technologies, Inc.
//
// 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 list
import (
"github.com/uber/aresdb/memstore/common"
"github.com/uber/aresdb/memstore/vectors"
"unsafe"
)
// baseVectorParty is the shared struct for live store list vp and archive store
// list vp. Some difference between normal base vp and list base vp:
// 1. There is no mode concept for list vp. therefore nonDefaultValueCount does not make sense for
// list vp.
// 2. There is no default value concept for list at least for now, so we will not store default value.
type baseVectorParty struct {
// offset is a pair of uint32 [offset, length]. therefore its length is 2 * length of vp.
offsets *vectors.Vector
// length of vp.
length int
// DataType of values. We need it since for mode 0 vector party, we cannot
// get data type from values vector. Also we store it on disk anyway.
dataType common.DataType
reporter HostMemoryChangeReporter
//convenient function to call child class to retrieve data
getDataValueFn func(int) common.DataValue
}
// GetOffsetLength returns the <offset, length> pair at ith row.
func (vp *baseVectorParty) GetOffsetLength(row int) (offset uint32, length uint32, valid bool) {
if vp.offsets == nil || row < 0 || row >= vp.length {
return
}
offset = *(*uint32)(vp.offsets.GetValue(2 * row))
length = *(*uint32)(vp.offsets.GetValue(2*row + 1))
valid = !(length == 0 && offset == 0)
return
}
// SetOffsetLength update offset/length for nth fow
func (vp *baseVectorParty) SetOffsetLength(row int, offset, length unsafe.Pointer) {
if offset != nil && length != nil {
vp.offsets.SetValue(2*row+1, length)
if *(*uint32)(length) == 0 {
zeroValueOffset := common.ZeroLengthArrayFlag
vp.offsets.SetValue(2*row, unsafe.Pointer(&zeroValueOffset))
} else {
vp.offsets.SetValue(2*row, offset)
}
} else {
var zero uint32 = 0
vp.offsets.SetValue(2*row, unsafe.Pointer(&zero))
vp.offsets.SetValue(2*row+1, unsafe.Pointer(&zero))
}
}
// GetElemCount return the number of element for value in n-th row
func (vp *baseVectorParty) GetElemCount(row int) uint32 {
if vp.offsets == nil || row < 0 || row >= vp.length {
return 0
}
return *(*uint32)(vp.offsets.GetValue(2*row + 1))
}
// GetValidity get validity of given offset.
func (vp *baseVectorParty) GetValidity(row int) bool {
_, _, valid := vp.GetOffsetLength(row)
return valid
}
// IsList tells whether this vp is list vp. And user can later on cast it to proper interface.
func (vp *baseVectorParty) IsList() bool {
return true
}
// GetDataType returns the element date type of this vp.
func (vp *baseVectorParty) GetDataType() common.DataType {
return vp.dataType
}
// GetLength returns the length of the vp.
func (vp *baseVectorParty) GetLength() int {
return vp.length
}
// Slice vector party into human readable SlicedVector format. For now just return an
// empty slice.
func (vp *baseVectorParty) Slice(startRow, numRows int) common.SlicedVector {
size := vp.length - startRow
if size < 0 {
size = 0
}
if size > numRows {
size = numRows
}
vector := common.SlicedVector{
Values: make([]interface{}, size),
Counts: make([]int, size),
}
for i := 0; i < size; i++ {
vector.Values[i] = vp.getDataValueFn(startRow + i).ConvertToHumanReadable(vp.dataType)
vector.Counts[i] = i + 1
}
return vector
}
// Check whether two vector parties are equal (used only in unit tests)
// Check common properties like data type and length.
// leftVP is vp underneath
func (vp *baseVectorParty) equals(other common.VectorParty, leftVP common.ListVectorParty) bool {
if !other.IsList() {
return false
}
if vp.GetDataType() != other.GetDataType() {
return false
}
if vp.GetLength() != other.GetLength() {
return false
}
rightVP := other.AsList()
for i := 0; i < other.GetLength(); i++ {
leftValue, leftValid := leftVP.GetListValue(i)
rightValue, rightValid := rightVP.GetListValue(i)
if !leftValid && !rightValid {
continue
}
if leftValid != rightValid || !arrayValueCompare(vp.GetDataType(), leftValue, rightValue) {
return false
}
}
return true
}
func arrayValueCompare(dataType common.DataType, left, right unsafe.Pointer) bool {
lReader := common.NewArrayValueReader(dataType, left)
rReader := common.NewArrayValueReader(dataType, right)
if lReader.GetLength() != rReader.GetLength() {
return false
}
itemType := common.GetElementDataType(dataType)
cmpFunc := common.GetCompareFunc(itemType)
for i := 0; i < lReader.GetLength(); i++ {
if itemType == common.Bool {
if lReader.GetBool(i) != rReader.GetBool(i) {
return false
}
} else {
if cmpFunc(lReader.Get(i), rReader.Get(i)) != 0 {
return false
}
}
}
return true
}
// GetNonDefaultValueCount get Number of non-default values stored. Since we
// count all list values as valid values, it should be equal to the length of
// the vp. If in future we want to get a count of non default element value
// count, we may need to scan all the old element values when overwriting.
func (vp *baseVectorParty) GetNonDefaultValueCount() int {
return vp.length
}