github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/store/hbase/snapshot.go (about)

     1  // Copyright 2015 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package hbasekv
    15  
    16  import (
    17  	"github.com/insionng/yougam/libraries/juju/errors"
    18  	"github.com/insionng/yougam/libraries/pingcap/go-hbase"
    19  	"github.com/insionng/yougam/libraries/pingcap/go-themis"
    20  	"github.com/insionng/yougam/libraries/pingcap/tidb/kv"
    21  )
    22  
    23  var (
    24  	_ kv.Snapshot = (*hbaseSnapshot)(nil)
    25  	_ kv.Iterator = (*hbaseIter)(nil)
    26  )
    27  
    28  // hbaseBatchSize is used for go-themis Scanner.
    29  const hbaseBatchSize = 1000
    30  
    31  // hbaseSnapshot implements MvccSnapshot interface.
    32  type hbaseSnapshot struct {
    33  	txn       themis.Txn
    34  	storeName string
    35  }
    36  
    37  // newHBaseSnapshot creates a snapshot of an HBase store.
    38  func newHbaseSnapshot(txn themis.Txn, storeName string) *hbaseSnapshot {
    39  	return &hbaseSnapshot{
    40  		txn:       txn,
    41  		storeName: storeName,
    42  	}
    43  }
    44  
    45  // Get gets the value for key k from snapshot.
    46  func (s *hbaseSnapshot) Get(k kv.Key) ([]byte, error) {
    47  	g := hbase.NewGet([]byte(k))
    48  	g.AddColumn(hbaseColFamilyBytes, hbaseQualifierBytes)
    49  	v, err := internalGet(s, g)
    50  	if err != nil {
    51  		return nil, errors.Trace(err)
    52  	}
    53  	return v, nil
    54  }
    55  
    56  // BatchGet implements kv.Snapshot.BatchGet interface.
    57  func (s *hbaseSnapshot) BatchGet(keys []kv.Key) (map[string][]byte, error) {
    58  	gets := make([]*hbase.Get, len(keys))
    59  	for i, key := range keys {
    60  		g := hbase.NewGet(key)
    61  		g.AddColumn(hbaseColFamilyBytes, hbaseQualifierBytes)
    62  		gets[i] = g
    63  	}
    64  	rows, err := s.txn.Gets(s.storeName, gets)
    65  	if err != nil {
    66  		return nil, errors.Trace(err)
    67  	}
    68  
    69  	m := make(map[string][]byte, len(rows))
    70  	for _, r := range rows {
    71  		k := string(r.Row)
    72  		v := r.Columns[hbaseFmlAndQual].Value
    73  		m[k] = v
    74  	}
    75  	return m, nil
    76  }
    77  
    78  func internalGet(s *hbaseSnapshot, g *hbase.Get) ([]byte, error) {
    79  	r, err := s.txn.Get(s.storeName, g)
    80  	if err != nil {
    81  		return nil, errors.Trace(err)
    82  	}
    83  	if r == nil || len(r.Columns) == 0 {
    84  		return nil, errors.Trace(kv.ErrNotExist)
    85  	}
    86  	return r.Columns[hbaseFmlAndQual].Value, nil
    87  }
    88  
    89  func (s *hbaseSnapshot) Seek(k kv.Key) (kv.Iterator, error) {
    90  	scanner := s.txn.GetScanner([]byte(s.storeName), []byte(k), nil, hbaseBatchSize)
    91  	return newInnerScanner(scanner), nil
    92  }
    93  
    94  func (s *hbaseSnapshot) SeekReverse(k kv.Key) (kv.Iterator, error) {
    95  	return nil, kv.ErrNotImplemented
    96  }
    97  
    98  func newInnerScanner(scanner *themis.ThemisScanner) kv.Iterator {
    99  	it := &hbaseIter{
   100  		ThemisScanner: scanner,
   101  	}
   102  	it.Next()
   103  	return it
   104  }
   105  
   106  func (s *hbaseSnapshot) Release() {
   107  	if s.txn != nil {
   108  		s.txn.Release()
   109  		s.txn = nil
   110  	}
   111  }
   112  
   113  type hbaseIter struct {
   114  	*themis.ThemisScanner
   115  	rs *hbase.ResultRow
   116  }
   117  
   118  func (it *hbaseIter) Next() error {
   119  	it.rs = it.ThemisScanner.Next()
   120  	return nil
   121  }
   122  
   123  func (it *hbaseIter) Valid() bool {
   124  	if it.rs == nil || len(it.rs.Columns) == 0 {
   125  		return false
   126  	}
   127  	if it.ThemisScanner.Closed() {
   128  		return false
   129  	}
   130  	return true
   131  }
   132  
   133  func (it *hbaseIter) Key() kv.Key {
   134  	return it.rs.Row
   135  }
   136  
   137  func (it *hbaseIter) Value() []byte {
   138  	return it.rs.Columns[hbaseFmlAndQual].Value
   139  }
   140  
   141  func (it *hbaseIter) Close() {
   142  	if it.ThemisScanner != nil {
   143  		it.ThemisScanner.Close()
   144  		it.ThemisScanner = nil
   145  	}
   146  	it.rs = nil
   147  }