memstore/common/primary_key.go (70 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 common import ( "encoding/json" "unsafe" "github.com/uber/aresdb/utils" ) const ( BucketSize = 8 // log2(numHashes) log2NumHashes = 2 // number of hash functions NumHashes = 1 << log2NumHashes RecordIDBytes = int(unsafe.Sizeof(RecordID{})) ) // RecordID represents a record location with BatchID as the inflated vector id // and offset determines the offset of record inside the vector type RecordID struct { BatchID int32 `json:"batchID"` Index uint32 `json:"index"` } // Key represents the key for the item type Key []byte // PrimaryKeyData holds the data for transferring to GPU for query purposes type PrimaryKeyData struct { Data unsafe.Pointer NumBytes int Seeds [NumHashes]uint32 KeyBytes int NumBuckets int } // PrimaryKey is an interface for primary key index type PrimaryKey interface { // Find looks up a value given key Find(key Key) (RecordID, bool) // FindOrInsert find or insert a key value pair into FindOrInsert(key Key, value RecordID, eventTime uint32) (existingFound bool, recordID RecordID, err error) // Update updates a key with a new recordID. Return whether key exists in the primary key or not. Update(key Key, value RecordID) bool // Delete deletes a key if it exists Delete(key Key) // Update the cutoff event time. UpdateEventTimeCutoff(eventTimeCutoff uint32) // GetEventTimeCutoff returns the cutoff event time. GetEventTimeCutoff() uint32 // GetDataForTransfer locks the primary key for transferring data // the caller should unlock by calling UnlockAfterTransfer when done LockForTransfer() PrimaryKeyData // UnlockAfterTransfer unlocks primary key UnlockAfterTransfer() // Destruct clean up all existing resources used by primary key Destruct() // Size returns the current number of items. Size() uint // Capacity returns how many items current primary key can hold. Capacity() uint // AllocatedBytes returns the size of primary key in bytes. AllocatedBytes() uint } // MarshalPrimaryKey marshals a PrimaryKey into json. We cannot define MarshalJson for PrimaryKey // since pointer cannot be a receiver. func MarshalPrimaryKey(pk PrimaryKey) ([]byte, error) { if pk == nil { return nil, nil } return json.Marshal(map[string]interface{}{ "size": pk.Size(), "allocatedBytes": pk.AllocatedBytes(), "capacity": pk.Capacity(), "eventTimeCutoff": pk.GetEventTimeCutoff(), }) } // AppendPrimaryKeyBytes writes primary keys bytes into key buffer func AppendPrimaryKeyBytes(key []byte, primaryKeyValues DataValueIterator) ([]byte, error) { for !primaryKeyValues.done() { value := primaryKeyValues.read() if !value.Valid { return key, utils.StackError(nil, "Primary key cannot be null") } if value.IsBool { if value.BoolVal { key = append(key, byte(1)) } else { key = append(key, byte(0)) } } else { for i := 0; i < DataTypeBits(value.DataType)/8; i++ { key = append(key, *(*byte)(utils.MemAccess(value.OtherVal, i))) } } primaryKeyValues.next() } return key, nil }