151 lines
3.8 KiB
Go
Raw Normal View History

2019-04-22 02:59:20 +00:00
// Copyright (C) 2015 The GoHBase Authors. All rights reserved.
// This file is part of GoHBase.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.
package hrpc
import (
"context"
"github.com/golang/protobuf/proto"
"github.com/tsuna/gohbase/pb"
)
// Get represents a Get HBase call.
type Get struct {
base
baseQuery
// Don't return any KeyValue, just say whether the row key exists in the
// table or not.
existsOnly bool
skipbatch bool
}
// baseGet returns a Get struct with default values set.
func baseGet(ctx context.Context, table []byte, key []byte,
options ...func(Call) error) (*Get, error) {
g := &Get{
base: base{
key: key,
table: table,
ctx: ctx,
resultch: make(chan RPCResult, 1),
},
baseQuery: newBaseQuery(),
}
err := applyOptions(g, options...)
if err != nil {
return nil, err
}
return g, nil
}
// NewGet creates a new Get request for the given table and row key.
func NewGet(ctx context.Context, table, key []byte,
options ...func(Call) error) (*Get, error) {
return baseGet(ctx, table, key, options...)
}
// NewGetStr creates a new Get request for the given table and row key.
func NewGetStr(ctx context.Context, table, key string,
options ...func(Call) error) (*Get, error) {
return NewGet(ctx, []byte(table), []byte(key), options...)
}
// Name returns the name of this RPC call.
func (g *Get) Name() string {
return "Get"
}
// SkipBatch returns true if the Get request shouldn't be batched,
// but should be sent to Region Server right away.
func (g *Get) SkipBatch() bool {
return g.skipbatch
}
func (g *Get) setSkipBatch(v bool) {
g.skipbatch = v
}
// ExistsOnly makes this Get request not return any KeyValue, merely whether
// or not the given row key exists in the table.
func (g *Get) ExistsOnly() {
g.existsOnly = true
}
// ToProto converts this RPC into a protobuf message.
func (g *Get) ToProto() proto.Message {
get := &pb.GetRequest{
Region: g.regionSpecifier(),
Get: &pb.Get{
Row: g.key,
Column: familiesToColumn(g.families),
TimeRange: &pb.TimeRange{},
},
}
/* added support for limit number of cells per row */
if g.storeLimit != DefaultMaxResultsPerColumnFamily {
get.Get.StoreLimit = &g.storeLimit
}
if g.storeOffset != 0 {
get.Get.StoreOffset = &g.storeOffset
}
if g.maxVersions != DefaultMaxVersions {
get.Get.MaxVersions = &g.maxVersions
}
if g.fromTimestamp != MinTimestamp {
get.Get.TimeRange.From = &g.fromTimestamp
}
if g.toTimestamp != MaxTimestamp {
get.Get.TimeRange.To = &g.toTimestamp
}
if g.existsOnly {
get.Get.ExistenceOnly = proto.Bool(true)
}
get.Get.Filter = g.filter
return get
}
// NewResponse creates an empty protobuf message to read the response of this
// RPC.
func (g *Get) NewResponse() proto.Message {
return &pb.GetResponse{}
}
// DeserializeCellBlocks deserializes get result from cell blocks
func (g *Get) DeserializeCellBlocks(m proto.Message, b []byte) (uint32, error) {
resp := m.(*pb.GetResponse)
if resp.Result == nil {
// TODO: is this possible?
return 0, nil
}
cells, read, err := deserializeCellBlocks(b, uint32(resp.Result.GetAssociatedCellCount()))
if err != nil {
return 0, err
}
resp.Result.Cell = append(resp.Result.Cell, cells...)
return read, nil
}
// familiesToColumn takes a map from strings to lists of strings, and converts
// them into protobuf Columns
func familiesToColumn(families map[string][]string) []*pb.Column {
cols := make([]*pb.Column, len(families))
counter := 0
for family, qualifiers := range families {
bytequals := make([][]byte, len(qualifiers))
for i, qual := range qualifiers {
bytequals[i] = []byte(qual)
}
cols[counter] = &pb.Column{
Family: []byte(family),
Qualifier: bytequals,
}
counter++
}
return cols
}