github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/store/tikv/txn.go (about) 1 // Copyright 2016 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 tikv 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/tidb/kv" 22 ) 23 24 var ( 25 _ kv.Transaction = (*tikvTxn)(nil) 26 ) 27 28 // tikvTxn implements kv.Transaction. 29 type tikvTxn struct { 30 us kv.UnionStore 31 store *tikvStore // for connection to region. 32 startTS uint64 33 commitTS uint64 34 valid bool 35 lockKeys [][]byte 36 dirty bool 37 // FIXME: only doPrewrite, this variable only for lock key test. 38 // If find better way to test lock then delete it. 39 DONOTCOMMIT bool 40 } 41 42 func newTiKVTxn(store *tikvStore) (*tikvTxn, error) { 43 startTS, err := store.oracle.GetTimestamp() 44 if err != nil { 45 return nil, errors.Trace(err) 46 } 47 ver := kv.NewVersion(startTS) 48 return &tikvTxn{ 49 us: kv.NewUnionStore(newTiKVSnapshot(store, ver)), 50 store: store, 51 startTS: startTS, 52 valid: true, 53 }, nil 54 } 55 56 // Implement transaction interface. 57 func (txn *tikvTxn) Get(k kv.Key) ([]byte, error) { 58 log.Debugf("Get key[%q] txn[%d]", k, txn.StartTS()) 59 ret, err := txn.us.Get(k) 60 if err != nil { 61 return nil, errors.Trace(err) 62 } 63 return ret, nil 64 } 65 66 func (txn *tikvTxn) Set(k kv.Key, v []byte) error { 67 log.Debugf("Set key[%q] txn[%d]", k, txn.StartTS()) 68 txn.dirty = true 69 return txn.us.Set(k, v) 70 } 71 72 func (txn *tikvTxn) String() string { 73 return fmt.Sprintf("%d", txn.StartTS()) 74 } 75 76 func (txn *tikvTxn) Seek(k kv.Key) (kv.Iterator, error) { 77 log.Debugf("Seek key[%q] txn[%d]", k, txn.StartTS()) 78 return txn.us.Seek(k) 79 } 80 81 // SeekReverse creates a reversed Iterator positioned on the first entry which key is less than k. 82 func (txn *tikvTxn) SeekReverse(k kv.Key) (kv.Iterator, error) { 83 log.Debugf("SeekReverse key[%q] txn[%d]", k, txn.StartTS()) 84 return txn.us.SeekReverse(k) 85 } 86 87 func (txn *tikvTxn) Delete(k kv.Key) error { 88 log.Debugf("Delete key[%q] txn[%d]", k, txn.StartTS()) 89 txn.dirty = true 90 return txn.us.Delete(k) 91 } 92 93 func (txn *tikvTxn) SetOption(opt kv.Option, val interface{}) { 94 txn.us.SetOption(opt, val) 95 } 96 97 func (txn *tikvTxn) DelOption(opt kv.Option) { 98 txn.us.DelOption(opt) 99 } 100 101 func (txn *tikvTxn) Commit() error { 102 if !txn.valid { 103 return kv.ErrInvalidTxn 104 } 105 defer txn.close() 106 107 log.Debugf("[kv] start to commit txn %d", txn.StartTS()) 108 if err := txn.us.CheckLazyConditionPairs(); err != nil { 109 return errors.Trace(err) 110 } 111 112 committer, err := newTxnCommitter(txn) 113 if err != nil { 114 return errors.Trace(err) 115 } 116 if committer == nil { 117 return nil 118 } 119 err = committer.Commit() 120 if err != nil { 121 return errors.Trace(err) 122 } 123 log.Debugf("[kv] finish commit txn %d", txn.StartTS()) 124 return nil 125 } 126 127 func (txn *tikvTxn) close() error { 128 txn.us.Release() 129 txn.valid = false 130 return nil 131 } 132 133 func (txn *tikvTxn) Rollback() error { 134 if !txn.valid { 135 return kv.ErrInvalidTxn 136 } 137 log.Warnf("[kv] Rollback txn %d", txn.StartTS()) 138 return nil 139 } 140 141 func (txn *tikvTxn) LockKeys(keys ...kv.Key) error { 142 for _, key := range keys { 143 txn.lockKeys = append(txn.lockKeys, key) 144 } 145 return nil 146 } 147 148 func (txn *tikvTxn) GetClient() kv.Client { 149 return &CopClient{ 150 store: txn.store, 151 } 152 } 153 154 func (txn *tikvTxn) IsReadOnly() bool { 155 return !txn.dirty 156 } 157 158 func (txn *tikvTxn) StartTS() uint64 { 159 return txn.startTS 160 }