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 }