You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.8 KiB
150 lines
3.8 KiB
// 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 |
|
}
|
|
|