blob: 30557af7df46cbdea3a623c072f82e77a69d36df [file]
// Copyright 2015-present Basho 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 riak
import (
"fmt"
"time"
rpbRiak "github.com/basho/riak-go-client/rpb/riak"
rpbRiakKV "github.com/basho/riak-go-client/rpb/riak_kv"
)
// Link is used to represent a Riak KV object link, which is a one way link to another object within
// Riak
type Link struct {
Bucket string
Key string
Tag string
}
// Pair is used to store user defined meta data with a key and value
type Pair struct {
Key string
Value string
}
// Object structure used for representing a KV Riak object
type Object struct {
BucketType string
Bucket string
Key string
IsTombstone bool
Value []byte
ContentType string
Charset string
ContentEncoding string
VTag string
LastModified time.Time
UserMeta []*Pair
Indexes map[string][]string
Links []*Link
VClock []byte
}
// HasIndexes is a bool check to determine if the object contains any secondary indexes for searching
func (o *Object) HasIndexes() bool {
return len(o.Indexes) > 0
}
// HasUserMeta is a bool check to determine if the object contains any user defined meta data
func (o *Object) HasUserMeta() bool {
return len(o.UserMeta) > 0
}
// HasLinks is a bool check to determine if the object contains any links
func (o *Object) HasLinks() bool {
return len(o.Links) > 0
}
// AddToIntIndex adds the object to the specified secondary index with the integer value to be used
// for index searches
func (o *Object) AddToIntIndex(indexName string, indexValue int) {
o.AddToIndex(indexName, fmt.Sprintf("%v", indexValue))
}
// AddToIndex adds the object to the specified secondary index with the string value to be used for
// index searches
func (o *Object) AddToIndex(indexName string, indexValue string) {
if o.Indexes == nil {
o.Indexes = make(map[string][]string)
}
if o.Indexes[indexName] == nil {
o.Indexes[indexName] = make([]string, 1)
o.Indexes[indexName][0] = indexValue
} else {
o.Indexes[indexName] = append(o.Indexes[indexName], indexValue)
}
}
func fromRpbContent(rpbContent *rpbRiakKV.RpbContent) (ro *Object, err error) {
// NB: ro = "Riak Object"
ro = &Object{
IsTombstone: rpbContent.GetDeleted(),
}
if ro.IsTombstone {
ro.Value = nil
} else {
ro.Value = rpbContent.GetValue()
}
ro.ContentType = string(rpbContent.GetContentType())
ro.Charset = string(rpbContent.GetCharset())
ro.ContentEncoding = string(rpbContent.GetContentEncoding())
ro.VTag = string(rpbContent.GetVtag())
ro.LastModified = time.Unix(int64(rpbContent.GetLastMod()), int64(rpbContent.GetLastModUsecs()))
rpbUserMeta := rpbContent.GetUsermeta()
if len(rpbUserMeta) > 0 {
ro.UserMeta = make([]*Pair, len(rpbUserMeta))
for i, userMeta := range rpbUserMeta {
ro.UserMeta[i] = &Pair{
Key: string(userMeta.Key),
Value: string(userMeta.Value),
}
}
}
rpbIndexes := rpbContent.GetIndexes()
if len(rpbIndexes) > 0 {
ro.Indexes = make(map[string][]string)
for _, index := range rpbIndexes {
indexName := string(index.Key)
indexValue := string(index.Value)
if ro.Indexes[indexName] == nil {
ro.Indexes[indexName] = make([]string, 1)
ro.Indexes[indexName][0] = indexValue
} else {
ro.Indexes[indexName] = append(ro.Indexes[indexName], indexValue)
}
}
}
rpbLinks := rpbContent.GetLinks()
if len(rpbLinks) > 0 {
ro.Links = make([]*Link, len(rpbLinks))
for i, link := range rpbLinks {
ro.Links[i] = &Link{
Bucket: string(link.Bucket),
Key: string(link.Key),
Tag: string(link.Tag),
}
}
}
return
}
func toRpbContent(ro *Object) (*rpbRiakKV.RpbContent, error) {
rpbContent := &rpbRiakKV.RpbContent{
Value: ro.Value,
ContentType: rpbBytes(ro.ContentType),
Charset: rpbBytes(ro.Charset),
ContentEncoding: rpbBytes(ro.ContentEncoding),
}
if ro.HasIndexes() {
count := 0
for _, idxValues := range ro.Indexes {
count += len(idxValues)
}
idx := 0
rpbIndexes := make([]*rpbRiak.RpbPair, count)
for idxName, idxValues := range ro.Indexes {
idxNameBytes := []byte(idxName)
for _, idxVal := range idxValues {
pair := &rpbRiak.RpbPair{
Key: idxNameBytes,
Value: []byte(idxVal),
}
rpbIndexes[idx] = pair
idx++
}
}
rpbContent.Indexes = rpbIndexes
}
if ro.HasUserMeta() {
rpbUserMeta := make([]*rpbRiak.RpbPair, len(ro.UserMeta))
for i, userMeta := range ro.UserMeta {
rpbUserMeta[i] = &rpbRiak.RpbPair{
Key: []byte(userMeta.Key),
Value: []byte(userMeta.Value),
}
}
rpbContent.Usermeta = rpbUserMeta
}
if ro.HasLinks() {
rpbLinks := make([]*rpbRiakKV.RpbLink, len(ro.Links))
for i, link := range ro.Links {
rpbLinks[i] = &rpbRiakKV.RpbLink{
Bucket: []byte(link.Bucket),
Key: []byte(link.Key),
Tag: []byte(link.Tag),
}
}
rpbContent.Links = rpbLinks
}
return rpbContent, nil
}