github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/store/hbase/txn.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 "fmt" 18 19 "github.com/insionng/yougam/libraries/juju/errors" 20 "github.com/insionng/yougam/libraries/ngaut/log" 21 "github.com/insionng/yougam/libraries/pingcap/go-hbase" 22 "github.com/insionng/yougam/libraries/pingcap/go-themis" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/kv" 24 ) 25 26 var ( 27 _ kv.Transaction = (*hbaseTxn)(nil) 28 ) 29 30 // dbTxn implements kv.Transacton. It is not thread safe. 31 type hbaseTxn struct { 32 us kv.UnionStore 33 txn themis.Txn 34 store *hbaseStore // for commit 35 storeName string 36 tid uint64 37 valid bool 38 version kv.Version // commit version 39 dirty bool 40 } 41 42 func newHbaseTxn(t themis.Txn, storeName string) *hbaseTxn { 43 return &hbaseTxn{ 44 txn: t, 45 valid: true, 46 storeName: storeName, 47 tid: t.GetStartTS(), 48 us: kv.NewUnionStore(newHbaseSnapshot(t, storeName)), 49 } 50 } 51 52 // Implement transaction interface 53 54 func (txn *hbaseTxn) Get(k kv.Key) ([]byte, error) { 55 log.Debugf("[kv] get key:%q, txn:%d", k, txn.tid) 56 return txn.us.Get(k) 57 } 58 59 func (txn *hbaseTxn) Set(k kv.Key, v []byte) error { 60 log.Debugf("[kv] set %q txn:%d", k, txn.tid) 61 txn.dirty = true 62 return txn.us.Set(k, v) 63 } 64 65 func (txn *hbaseTxn) String() string { 66 return fmt.Sprintf("%d", txn.tid) 67 } 68 69 func (txn *hbaseTxn) Seek(k kv.Key) (kv.Iterator, error) { 70 log.Debugf("[kv] seek %q txn:%d", k, txn.tid) 71 return txn.us.Seek(k) 72 } 73 74 func (txn *hbaseTxn) SeekReverse(k kv.Key) (kv.Iterator, error) { 75 log.Debugf("[kv] seek prev %q txn:%d", k, txn.tid) 76 return txn.us.SeekReverse(k) 77 } 78 79 func (txn *hbaseTxn) Delete(k kv.Key) error { 80 log.Debugf("[kv] delete %q txn:%d", k, txn.tid) 81 txn.dirty = true 82 return txn.us.Delete(k) 83 } 84 85 func (txn *hbaseTxn) SetOption(opt kv.Option, val interface{}) { 86 txn.us.SetOption(opt, val) 87 } 88 89 func (txn *hbaseTxn) DelOption(opt kv.Option) { 90 txn.us.DelOption(opt) 91 } 92 93 func (txn *hbaseTxn) doCommit() error { 94 if err := txn.us.CheckLazyConditionPairs(); err != nil { 95 return errors.Trace(err) 96 } 97 98 err := txn.us.WalkBuffer(func(k kv.Key, v []byte) error { 99 row := append([]byte(nil), k...) 100 if len(v) == 0 { // Deleted marker 101 d := hbase.NewDelete(row) 102 d.AddStringColumn(hbaseColFamily, hbaseQualifier) 103 err := txn.txn.Delete(txn.storeName, d) 104 if err != nil { 105 return errors.Trace(err) 106 } 107 } else { 108 val := append([]byte(nil), v...) 109 p := hbase.NewPut(row) 110 p.AddValue(hbaseColFamilyBytes, hbaseQualifierBytes, val) 111 txn.txn.Put(txn.storeName, p) 112 } 113 return nil 114 }) 115 116 if err != nil { 117 return errors.Trace(err) 118 } 119 120 err = txn.txn.Commit() 121 if err != nil { 122 log.Error(err) 123 return errors.Trace(err) 124 } 125 126 txn.version = kv.NewVersion(txn.txn.GetCommitTS()) 127 log.Debugf("[kv] commit successfully, txn.version:%d", txn.version.Ver) 128 return nil 129 } 130 131 func (txn *hbaseTxn) Commit() error { 132 if !txn.valid { 133 return kv.ErrInvalidTxn 134 } 135 log.Debugf("[kv] start to commit txn %d", txn.tid) 136 defer func() { 137 txn.close() 138 }() 139 return txn.doCommit() 140 } 141 142 func (txn *hbaseTxn) close() error { 143 txn.us.Release() 144 txn.valid = false 145 return nil 146 } 147 148 //if fail, themis auto rollback 149 func (txn *hbaseTxn) Rollback() error { 150 if !txn.valid { 151 return kv.ErrInvalidTxn 152 } 153 log.Warnf("[kv] Rollback txn %d", txn.tid) 154 return txn.close() 155 } 156 157 func (txn *hbaseTxn) LockKeys(keys ...kv.Key) error { 158 for _, key := range keys { 159 if err := txn.txn.LockRow(txn.storeName, key); err != nil { 160 return errors.Trace(err) 161 } 162 } 163 return nil 164 } 165 166 func (txn *hbaseTxn) IsReadOnly() bool { 167 return !txn.dirty 168 } 169 170 func (txn *hbaseTxn) StartTS() uint64 { 171 return txn.tid 172 } 173 174 func (txn *hbaseTxn) GetClient() kv.Client { 175 return &hbaseClient{} 176 } 177 178 type hbaseClient struct { 179 } 180 181 func (c *hbaseClient) SupportRequestType(reqType, subType int64) bool { 182 return false 183 } 184 185 func (c *hbaseClient) Send(req *kv.Request) kv.Response { 186 return nil 187 }