Skip to content

Commit 24a1bbe

Browse files
authored
Merge pull request #7 from letterbeezps/dev
add read only tx
2 parents 6565cff + 766e16e commit 24a1bbe

File tree

5 files changed

+68
-56
lines changed

5 files changed

+68
-56
lines changed

cmd/example/mvcc/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
func main() {
1111
db := mv.NewMVCC()
12-
tx, err := db.Begin()
12+
tx, err := db.Begin(false)
1313
if err != nil {
1414
log.Fatal(err)
1515
}

mvcc/error.go

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ import "errors"
44

55
var (
66
ErrorSerialization = errors.New("serialization")
7+
ErrorReadOnly = errors.New("can't update with read only tx")
78
)

mvcc/mvcc.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ func NewMVCC() *MVCC {
2020
}
2121
}
2222

23-
func (m *MVCC) Begin() (*TX, error) {
23+
func (m *MVCC) Begin(readOnly bool) (*TX, error) {
2424
tx := &TX{
2525
Lock: m.Lock,
2626
Engine: m.Engine,
2727
}
28-
err := tx.Begin()
28+
err := tx.Begin(readOnly)
2929
if err != nil {
3030
return nil, errors.Wrap(err, "tx begin")
3131
}

mvcc/tx.go

+17-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ type TX struct {
1717
State *TxState
1818
}
1919

20-
func (tx *TX) Begin() error {
20+
func (tx *TX) Begin(readOnly bool) error {
2121
tx.Lock.Lock()
2222
defer tx.Lock.Unlock()
2323

@@ -35,14 +35,16 @@ func (tx *TX) Begin() error {
3535
}
3636
tx.State = &TxState{
3737
TxID: txId,
38-
ReadOnly: false,
38+
ReadOnly: readOnly,
3939
ActiveTx: active,
4040
}
41-
activeKey, err := encodeTxActiveKey(txId)
42-
if err != nil {
43-
return errors.Wrap(err, fmt.Sprintf("getTxActiveKey with %d", txId))
41+
if !readOnly {
42+
activeKey, err := encodeTxActiveKey(txId)
43+
if err != nil {
44+
return errors.Wrap(err, fmt.Sprintf("getTxActiveKey with %d", txId))
45+
}
46+
tx.Engine.Set(activeKey, []byte{})
4447
}
45-
tx.Engine.Set(activeKey, []byte{})
4648
return nil
4749
}
4850

@@ -64,7 +66,9 @@ func (tx *TX) scanActive() (map[TXID]struct{}, error) {
6466
}
6567

6668
func (tx *TX) Write(key string, value []byte) error {
67-
69+
if tx.State.ReadOnly {
70+
return errors.Wrap(ErrorReadOnly, fmt.Sprintf("tx with id %d is read only", tx.State.TxID))
71+
}
6872
miniTxID := tx.State.TxID + 1
6973
for id := range tx.State.ActiveTx {
7074
if id < miniTxID {
@@ -115,6 +119,9 @@ func (tx *TX) Delete(key string) error {
115119
}
116120

117121
func (tx *TX) Commit() error {
122+
if tx.State.ReadOnly {
123+
return errors.Wrap(ErrorReadOnly, fmt.Sprintf("tx with id %d is read only, not need commit", tx.State.TxID))
124+
}
118125
startKey, err := encodeTxWriteKey(tx.State.TxID, "")
119126
if err != nil {
120127
return errors.Wrap(err, fmt.Sprintf("encodeTxWriteKey with id: %d", tx.State.TxID))
@@ -141,6 +148,9 @@ func (tx *TX) Commit() error {
141148
}
142149

143150
func (tx *TX) RollBack() error {
151+
if tx.State.ReadOnly {
152+
return errors.Wrap(ErrorReadOnly, fmt.Sprintf("tx with id %d is read only, not need rollback", tx.State.TxID))
153+
}
144154
startKey, err := encodeTxWriteKey(tx.State.TxID, "")
145155
if err != nil {
146156
return errors.Wrap(err, fmt.Sprintf("encodeTxWriteKey with id: %d", tx.State.TxID))

mvcc/tx_test.go

+47-46
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@ func Test_TxBegin(t *testing.T) {
1919
Engine: memory.NewMemory(),
2020
}
2121

22-
tx1, err := mvcc.Begin()
22+
tx1, err := mvcc.Begin(false)
2323
assert.Nil(t, err)
2424
assert.Equal(t, TXID(1), tx1.State.TxID)
2525
assert.Equal(t, map[TXID]struct{}{}, tx1.State.ActiveTx)
2626

27-
tx2, err := mvcc.Begin()
27+
tx2, err := mvcc.Begin(false)
2828
assert.Nil(t, err)
2929
assert.Equal(t, TXID(2), tx2.State.TxID)
3030
assert.Equal(t, map[TXID]struct{}{
3131
TXID(1): {},
3232
}, tx2.State.ActiveTx)
3333

34-
tx3, err := mvcc.Begin()
34+
tx3, err := mvcc.Begin(false)
3535
assert.Nil(t, err)
3636
assert.Equal(t, TXID(3), tx3.State.TxID)
3737
assert.Equal(t, map[TXID]struct{}{
@@ -42,7 +42,7 @@ func Test_TxBegin(t *testing.T) {
4242
err = tx2.Commit()
4343
assert.Nil(t, err)
4444

45-
tx4, err := mvcc.Begin()
45+
tx4, err := mvcc.Begin(false)
4646
assert.Nil(t, err)
4747
assert.Equal(t, TXID(4), tx4.State.TxID)
4848
assert.Equal(t, map[TXID]struct{}{
@@ -57,18 +57,18 @@ func Test_GetSet(t *testing.T) {
5757
Engine: memory.NewMemory(),
5858
}
5959

60-
tx1, err := mvcc.Begin()
60+
tx1, err := mvcc.Begin(false)
6161

6262
assert.Nil(t, err)
6363
assert.Nil(t, tx1.Set("a", []byte{1}))
6464
assert.Nil(t, tx1.Set("b", []byte{1}))
6565
assert.Nil(t, tx1.Commit())
6666

67-
tx2, err := mvcc.Begin()
67+
tx2, err := mvcc.Begin(false)
6868
assert.Nil(t, err)
69-
tx3, err := mvcc.Begin()
69+
tx3, err := mvcc.Begin(false)
7070
assert.Nil(t, err)
71-
tx4, err := mvcc.Begin()
71+
tx4, err := mvcc.Begin(false)
7272
assert.Nil(t, err)
7373

7474
assert.Nil(t, tx2.Set("a", []byte{2}))
@@ -90,7 +90,7 @@ func Test_GetSet(t *testing.T) {
9090
assert.Nil(t, err)
9191
assert.Equal(t, []byte{3}, ret) // tx2 can see it's self
9292

93-
tx5, err := mvcc.Begin()
93+
tx5, err := mvcc.Begin(false)
9494
assert.Nil(t, err)
9595
ret, err = tx5.Get("a")
9696
assert.Nil(t, err)
@@ -108,7 +108,7 @@ func Test_GetSet(t *testing.T) {
108108
assert.Nil(t, tx3.Commit())
109109

110110
// all txs are commited, so tx6 can see the latest data version
111-
tx6, err := mvcc.Begin()
111+
tx6, err := mvcc.Begin(true)
112112
assert.Nil(t, err)
113113
ret, err = tx6.Get("a")
114114
assert.Nil(t, err)
@@ -129,18 +129,18 @@ func Test_delete_conflict(t *testing.T) {
129129
Engine: memory.NewMemory(),
130130
}
131131

132-
tx1, err := mvcc.Begin()
132+
tx1, err := mvcc.Begin(false)
133133
assert.Nil(t, err)
134134
assert.Nil(t, tx1.Set("a", []byte{1}))
135135

136-
tx2, err := mvcc.Begin()
136+
tx2, err := mvcc.Begin(false)
137137
assert.Nil(t, err)
138138

139-
tx3, err := mvcc.Begin()
139+
tx3, err := mvcc.Begin(false)
140140
assert.Nil(t, err)
141141
assert.Nil(t, tx3.Set("c", []byte{3}))
142142

143-
tx4, err := mvcc.Begin()
143+
tx4, err := mvcc.Begin(false)
144144
assert.Nil(t, err)
145145
assert.Nil(t, tx4.Set("d", []byte{4}))
146146
assert.Nil(t, tx4.Commit())
@@ -157,24 +157,24 @@ func Test_get_isolation(t *testing.T) {
157157
Engine: memory.NewMemory(),
158158
}
159159

160-
tx1, err := mvcc.Begin()
160+
tx1, err := mvcc.Begin(false)
161161
assert.Nil(t, err)
162162
assert.Nil(t, tx1.Set("a", []byte{1}))
163163
assert.Nil(t, tx1.Set("b", []byte{1}))
164164
assert.Nil(t, tx1.Set("d", []byte{1}))
165165
assert.Nil(t, tx1.Set("e", []byte{1}))
166166
assert.Nil(t, tx1.Commit())
167167

168-
tx2, err := mvcc.Begin()
168+
tx2, err := mvcc.Begin(false)
169169
assert.Nil(t, err)
170170
assert.Nil(t, tx2.Set("a", []byte{2}))
171171
assert.Nil(t, tx2.Delete("b"))
172172
assert.Nil(t, tx2.Set("c", []byte{2}))
173173

174-
tx3, err := mvcc.Begin()
174+
tx3, err := mvcc.Begin(true)
175175
assert.Nil(t, err)
176176

177-
tx4, err := mvcc.Begin()
177+
tx4, err := mvcc.Begin(false)
178178
assert.Nil(t, err)
179179
assert.Nil(t, tx4.Set("d", []byte{4}))
180180
assert.Nil(t, tx2.Delete("e"))
@@ -200,15 +200,15 @@ func Test_get_isolation(t *testing.T) {
200200
assert.Nil(t, err)
201201
assert.Equal(t, []byte{}, ret)
202202

203-
assert.Nil(t, tx3.RollBack())
203+
assert.ErrorIs(t, tx3.RollBack(), ErrorReadOnly)
204204
}
205205

206206
func Test_set(t *testing.T) {
207207
mvcc := MVCC{
208208
Lock: &sync.Mutex{},
209209
Engine: memory.NewMemory(),
210210
}
211-
tx0, err := mvcc.Begin()
211+
tx0, err := mvcc.Begin(false)
212212
assert.Nil(t, err)
213213
assert.Nil(t, tx0.Set("a", []byte{0}))
214214
assert.Nil(t, tx0.Set("a", []byte{0}))
@@ -220,13 +220,13 @@ func Test_set_conflict(t *testing.T) {
220220
Lock: &sync.Mutex{},
221221
Engine: memory.NewMemory(),
222222
}
223-
tx1, err := mvcc.Begin()
223+
tx1, err := mvcc.Begin(false)
224224
assert.Nil(t, err)
225-
tx2, err := mvcc.Begin()
225+
tx2, err := mvcc.Begin(false)
226226
assert.Nil(t, err)
227-
tx3, err := mvcc.Begin()
227+
tx3, err := mvcc.Begin(false)
228228
assert.Nil(t, err)
229-
tx4, err := mvcc.Begin()
229+
tx4, err := mvcc.Begin(false)
230230
assert.Nil(t, err)
231231

232232
assert.Nil(t, tx1.Set("a", []byte{1}))
@@ -244,19 +244,19 @@ func Test_rollback(t *testing.T) {
244244
Lock: &sync.Mutex{},
245245
Engine: memory.NewMemory(),
246246
}
247-
tx0, err := mvcc.Begin()
247+
tx0, err := mvcc.Begin(false)
248248
assert.Nil(t, err)
249249
assert.Nil(t, tx0.Set("a", []byte{0}))
250250
assert.Nil(t, tx0.Set("b", []byte{0}))
251251
assert.Nil(t, tx0.Set("c", []byte{0}))
252252
assert.Nil(t, tx0.Set("d", []byte{0}))
253253
assert.Nil(t, tx0.Commit())
254254

255-
tx1, err := mvcc.Begin()
255+
tx1, err := mvcc.Begin(false)
256256
assert.Nil(t, err)
257-
tx2, err := mvcc.Begin()
257+
tx2, err := mvcc.Begin(false)
258258
assert.Nil(t, err)
259-
tx3, err := mvcc.Begin()
259+
tx3, err := mvcc.Begin(false)
260260
assert.Nil(t, err)
261261

262262
assert.Nil(t, tx1.Set("a", []byte{1}))
@@ -269,7 +269,7 @@ func Test_rollback(t *testing.T) {
269269

270270
assert.Nil(t, tx2.RollBack())
271271

272-
tx4, err := mvcc.Begin()
272+
tx4, err := mvcc.Begin(true)
273273
assert.Nil(t, err)
274274
ret, err := tx4.Get("a")
275275
assert.Nil(t, err)
@@ -289,7 +289,7 @@ func Test_rollback(t *testing.T) {
289289
assert.Nil(t, tx1.Commit())
290290
assert.Nil(t, tx3.Commit())
291291

292-
tx5, err := mvcc.Begin()
292+
tx5, err := mvcc.Begin(true)
293293
assert.Nil(t, err)
294294
ret, err = tx5.Get("a")
295295
assert.Nil(t, err)
@@ -310,11 +310,11 @@ func Test_dirty_write(t *testing.T) {
310310
Lock: &sync.Mutex{},
311311
Engine: memory.NewMemory(),
312312
}
313-
tx1, err := mvcc.Begin()
313+
tx1, err := mvcc.Begin(false)
314314
assert.Nil(t, err)
315315
assert.Nil(t, tx1.Set("a", []byte{0}))
316316

317-
tx2, err := mvcc.Begin()
317+
tx2, err := mvcc.Begin(false)
318318
assert.Nil(t, err)
319319
assert.ErrorIs(t, tx2.Set("a", []byte{1}), ErrorSerialization)
320320
}
@@ -324,11 +324,11 @@ func Test_dirty_read(t *testing.T) {
324324
Lock: &sync.Mutex{},
325325
Engine: memory.NewMemory(),
326326
}
327-
tx1, err := mvcc.Begin()
327+
tx1, err := mvcc.Begin(false)
328328
assert.Nil(t, err)
329329
assert.Nil(t, tx1.Set("a", []byte{0}))
330330

331-
tx2, err := mvcc.Begin()
331+
tx2, err := mvcc.Begin(false)
332332
assert.Nil(t, err)
333333
ret, err := tx2.Get("a")
334334
assert.Nil(t, err)
@@ -340,9 +340,9 @@ func Test_lost_update(t *testing.T) {
340340
Lock: &sync.Mutex{},
341341
Engine: memory.NewMemory(),
342342
}
343-
tx1, err := mvcc.Begin()
343+
tx1, err := mvcc.Begin(false)
344344
assert.Nil(t, err)
345-
tx2, err := mvcc.Begin()
345+
tx2, err := mvcc.Begin(false)
346346
assert.Nil(t, err)
347347

348348
_, err = tx1.Get("a")
@@ -353,21 +353,22 @@ func Test_lost_update(t *testing.T) {
353353
assert.Nil(t, tx1.Set("a", []byte{0}))
354354
assert.ErrorIs(t, tx2.Set("a", []byte{1}), ErrorSerialization)
355355
assert.Nil(t, tx1.Commit())
356+
assert.Nil(t, tx2.RollBack())
356357
}
357358

358-
func Test_fuzzt_read(t *testing.T) {
359+
func Test_fuzzy_read(t *testing.T) {
359360
mvcc := MVCC{
360361
Lock: &sync.Mutex{},
361362
Engine: memory.NewMemory(),
362363
}
363-
tx0, err := mvcc.Begin()
364+
tx0, err := mvcc.Begin(false)
364365
assert.Nil(t, err)
365366
assert.Nil(t, tx0.Set("a", []byte{0}))
366367
assert.Nil(t, tx0.Commit())
367368

368-
tx1, err := mvcc.Begin()
369+
tx1, err := mvcc.Begin(false)
369370
assert.Nil(t, err)
370-
tx2, err := mvcc.Begin()
371+
tx2, err := mvcc.Begin(false)
371372
assert.Nil(t, err)
372373

373374
ret, err := tx2.Get("a")
@@ -388,15 +389,15 @@ func Test_read_skew(t *testing.T) {
388389
Lock: &sync.Mutex{},
389390
Engine: memory.NewMemory(),
390391
}
391-
tx0, err := mvcc.Begin()
392+
tx0, err := mvcc.Begin(false)
392393
assert.Nil(t, err)
393394
assert.Nil(t, tx0.Set("a", []byte{0}))
394395
assert.Nil(t, tx0.Set("b", []byte{0}))
395396
assert.Nil(t, tx0.Commit())
396397

397-
tx1, err := mvcc.Begin()
398+
tx1, err := mvcc.Begin(true)
398399
assert.Nil(t, err)
399-
tx2, err := mvcc.Begin()
400+
tx2, err := mvcc.Begin(false)
400401
assert.Nil(t, err)
401402

402403
ret, err := tx1.Get("a")
@@ -418,15 +419,15 @@ func Test_write_skew(t *testing.T) {
418419
Lock: &sync.Mutex{},
419420
Engine: memory.NewMemory(),
420421
}
421-
tx0, err := mvcc.Begin()
422+
tx0, err := mvcc.Begin(false)
422423
assert.Nil(t, err)
423424
assert.Nil(t, tx0.Set("a", []byte{0}))
424425
assert.Nil(t, tx0.Set("b", []byte{0}))
425426
assert.Nil(t, tx0.Commit())
426427

427-
tx1, err := mvcc.Begin()
428+
tx1, err := mvcc.Begin(false)
428429
assert.Nil(t, err)
429-
tx2, err := mvcc.Begin()
430+
tx2, err := mvcc.Begin(false)
430431
assert.Nil(t, err)
431432

432433
ret, err := tx1.Get("a")

0 commit comments

Comments
 (0)