diff --git a/kv/kv.go b/kv/kv.go index dcafc8dbc9..acf6df9897 100644 --- a/kv/kv.go +++ b/kv/kv.go @@ -74,6 +74,8 @@ type Transaction interface { SetOption(opt Option, val interface{}) // DelOption deletes an option. DelOption(opt Option) + // IsReadOnly checks if the transaction has only performed read operations. + IsReadOnly() bool } // Snapshot defines the interface for the snapshot fetched from KV store. diff --git a/store/hbase/txn.go b/store/hbase/txn.go index 8f4e8ac04f..dab14ef045 100644 --- a/store/hbase/txn.go +++ b/store/hbase/txn.go @@ -36,6 +36,7 @@ type hbaseTxn struct { tid uint64 valid bool version kv.Version // commit version + dirty bool } func newHbaseTxn(t themis.Txn, storeName string) *hbaseTxn { @@ -57,6 +58,7 @@ func (txn *hbaseTxn) Get(k kv.Key) ([]byte, error) { func (txn *hbaseTxn) Set(k kv.Key, v []byte) error { log.Debugf("[kv] set %q txn:%d", k, txn.tid) + txn.dirty = true return txn.us.Set(k, v) } @@ -71,6 +73,7 @@ func (txn *hbaseTxn) Seek(k kv.Key) (kv.Iterator, error) { func (txn *hbaseTxn) Delete(k kv.Key) error { log.Debugf("[kv] delete %q txn:%d", k, txn.tid) + txn.dirty = true return txn.us.Delete(k) } @@ -154,3 +157,7 @@ func (txn *hbaseTxn) LockKeys(keys ...kv.Key) error { } return nil } + +func (txn *hbaseTxn) IsReadOnly() bool { + return !txn.dirty +} diff --git a/store/localstore/txn.go b/store/localstore/txn.go index a3267490c4..b88f1e83ac 100644 --- a/store/localstore/txn.go +++ b/store/localstore/txn.go @@ -33,6 +33,7 @@ type dbTxn struct { valid bool version kv.Version // commit version lockedKeys map[string]struct{} // origin version in snapshot + dirty bool } func newTxn(s *dbStore, ver kv.Version) *dbTxn { @@ -57,6 +58,7 @@ func (txn *dbTxn) Get(k kv.Key) ([]byte, error) { func (txn *dbTxn) Set(k kv.Key, data []byte) error { log.Debugf("[kv] set key:%q, txn:%d", k, txn.tid) + txn.dirty = true return txn.us.Set(k, data) } @@ -71,6 +73,7 @@ func (txn *dbTxn) Seek(k kv.Key) (kv.Iterator, error) { func (txn *dbTxn) Delete(k kv.Key) error { log.Debugf("[kv] delete key:%q, txn:%d", k, txn.tid) + txn.dirty = true return txn.us.Delete(k) } @@ -132,3 +135,7 @@ func (txn *dbTxn) LockKeys(keys ...kv.Key) error { } return nil } + +func (txn *dbTxn) IsReadOnly() bool { + return !txn.dirty +}