...
1
2
3
4
5 package storage
6
7 import (
8 "context"
9 "errors"
10 "math/rand"
11 "sync"
12 )
13
14
15
16
17
18 type Mem struct {
19 mu sync.RWMutex
20 table map[string]string
21 }
22
23
24 type memTx struct {
25 m *Mem
26 writes []Write
27 }
28
29
30
31 var errRetry = errors.New("retry")
32
33
34 func (m *Mem) ReadOnly(ctx context.Context, f func(context.Context, Transaction) error) error {
35 tx := &memTx{m: m}
36 for {
37 err := func() error {
38 m.mu.Lock()
39 defer m.mu.Unlock()
40
41 if err := f(ctx, tx); err != nil {
42 return err
43 }
44
45 if rand.Intn(10) == 0 {
46 return errRetry
47 }
48 return nil
49 }()
50 if err != errRetry {
51 return err
52 }
53 }
54 }
55
56
57 func (m *Mem) ReadWrite(ctx context.Context, f func(context.Context, Transaction) error) error {
58 tx := &memTx{m: m}
59 for {
60 err := func() error {
61 m.mu.Lock()
62 defer m.mu.Unlock()
63
64 tx.writes = []Write{}
65 if err := f(ctx, tx); err != nil {
66 return err
67 }
68
69 if rand.Intn(10) == 0 {
70 return errRetry
71 }
72 if m.table == nil {
73 m.table = make(map[string]string)
74 }
75 for _, w := range tx.writes {
76 if w.Value == "" {
77 delete(m.table, w.Key)
78 } else {
79 m.table[w.Key] = w.Value
80 }
81 }
82 return nil
83 }()
84 if err != errRetry {
85 return err
86 }
87 }
88 }
89
90
91 func (tx *memTx) ReadValues(ctx context.Context, keys []string) ([]string, error) {
92 vals := make([]string, len(keys))
93 for i, key := range keys {
94 vals[i] = tx.m.table[key]
95 }
96 return vals, nil
97 }
98
99
100 func (tx *memTx) ReadValue(ctx context.Context, key string) (string, error) {
101 return tx.m.table[key], nil
102 }
103
104
105
106
107
108 func (tx *memTx) BufferWrites(list []Write) error {
109 if tx.writes == nil {
110 panic("BufferWrite on read-only transaction")
111 }
112 tx.writes = append(tx.writes, list...)
113 return nil
114 }
115
View as plain text