Skip to content

Commit a395cb9

Browse files
committed
firewaldb: single implementation of BBolt DBExecutor
The `kvStores` and `privacyMapDB` types have very similar looking `Update` and `View` methods. Instead of the duplication, here we let things be more generic by defining a generic `kvdbExecutor` which has Update and View methods defined.
1 parent 62723bd commit a395cb9

File tree

3 files changed

+66
-90
lines changed

3 files changed

+66
-90
lines changed

firewalldb/kvdb_store.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package firewalldb
2+
3+
import (
4+
"context"
5+
6+
"go.etcd.io/bbolt"
7+
)
8+
9+
// kvdbExecutor is a concrete implementation of the DBExecutor interface that
10+
// uses a bbolt database as its backing store.
11+
type kvdbExecutor[T any] struct {
12+
db *bbolt.DB
13+
wrapTx func(tx *bbolt.Tx) T
14+
}
15+
16+
// Update opens a database read/write transaction and executes the function f
17+
// with the transaction passed as a parameter. After f exits, if f did not
18+
// error, the transaction is committed. Otherwise, if f did error, the
19+
// transaction is rolled back. If the rollback fails, the original error
20+
// returned by f is still returned. If the commit fails, the commit error is
21+
// returned.
22+
//
23+
// NOTE: this is part of the DBExecutor interface.
24+
func (e *kvdbExecutor[T]) Update(ctx context.Context,
25+
fn func(ctx context.Context, tx T) error) error {
26+
27+
return e.db.Update(func(tx *bbolt.Tx) error {
28+
return fn(ctx, e.wrapTx(tx))
29+
})
30+
}
31+
32+
// View opens a database read transaction and executes the function f with the
33+
// transaction passed as a parameter. After f exits, the transaction is rolled
34+
// back. If f errors, its error is returned, not a rollback error (if any
35+
// occur).
36+
//
37+
// NOTE: this is part of the DBExecutor interface.
38+
func (e *kvdbExecutor[T]) View(ctx context.Context,
39+
fn func(ctx context.Context, tx T) error) error {
40+
41+
return e.db.View(func(tx *bbolt.Tx) error {
42+
return fn(ctx, e.wrapTx(tx))
43+
})
44+
}

firewalldb/kvstores.go

Lines changed: 12 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -107,62 +107,28 @@ type RulesDB interface {
107107
func (db *DB) GetKVStores(rule string, groupID session.ID,
108108
feature string) KVStores {
109109

110-
return &kvStores{
111-
db: db.DB,
112-
ruleName: rule,
113-
groupID: groupID,
114-
featureName: feature,
110+
return &kvdbExecutor[KVStoreTx]{
111+
db: db.DB,
112+
wrapTx: func(tx *bbolt.Tx) KVStoreTx {
113+
return &kvStoreTx{
114+
boltTx: tx,
115+
kvStores: &kvStores{
116+
ruleName: rule,
117+
groupID: groupID,
118+
featureName: feature,
119+
},
120+
}
121+
},
115122
}
116123
}
117124

118125
// kvStores implements the rules.KVStores interface.
119126
type kvStores struct {
120-
db *bbolt.DB
121127
ruleName string
122128
groupID session.ID
123129
featureName string
124130
}
125131

126-
// Update opens a database read/write transaction and executes the function f
127-
// with the transaction passed as a parameter. After f exits, if f did not
128-
// error, the transaction is committed. Otherwise, if f did error, the
129-
// transaction is rolled back. If the rollback fails, the original error
130-
// returned by f is still returned. If the commit fails, the commit error is
131-
// returned.
132-
//
133-
// NOTE: this is part of the KVStores interface.
134-
func (s *kvStores) Update(ctx context.Context, fn func(ctx context.Context,
135-
tx KVStoreTx) error) error {
136-
137-
return s.db.Update(func(tx *bbolt.Tx) error {
138-
boltTx := &kvStoreTx{
139-
boltTx: tx,
140-
kvStores: s,
141-
}
142-
143-
return fn(ctx, boltTx)
144-
})
145-
}
146-
147-
// View opens a database read transaction and executes the function f with the
148-
// transaction passed as a parameter. After f exits, the transaction is rolled
149-
// back. If f errors, its error is returned, not a rollback error (if any
150-
// occur).
151-
//
152-
// NOTE: this is part of the KVStores interface.
153-
func (s *kvStores) View(ctx context.Context, fn func(ctx context.Context,
154-
tx KVStoreTx) error) error {
155-
156-
return s.db.View(func(tx *bbolt.Tx) error {
157-
boltTx := &kvStoreTx{
158-
boltTx: tx,
159-
kvStores: s,
160-
}
161-
162-
return fn(ctx, boltTx)
163-
})
164-
}
165-
166132
// getBucketFunc defines the signature of the bucket creation/fetching function
167133
// required by kvStoreTx. If create is true, then all the bucket (and all
168134
// buckets leading up to the bucket) should be created if they do not already

firewalldb/privacy_mapper.go

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,16 @@ type NewPrivacyMapDB func(groupID session.ID) PrivacyMapDB
4242
// PrivacyDB constructs a PrivacyMapDB that will be indexed under the given
4343
// group ID key.
4444
func (db *DB) PrivacyDB(groupID session.ID) PrivacyMapDB {
45-
return &privacyMapDB{
46-
db: db,
47-
groupID: groupID,
45+
return &kvdbExecutor[PrivacyMapTx]{
46+
db: db.DB,
47+
wrapTx: func(tx *bbolt.Tx) PrivacyMapTx {
48+
return &privacyMapTx{
49+
boltTx: tx,
50+
privacyMapDB: &privacyMapDB{
51+
groupID: groupID,
52+
},
53+
}
54+
},
4855
}
4956
}
5057

@@ -74,50 +81,9 @@ type PrivacyMapTx interface {
7481

7582
// privacyMapDB is an implementation of PrivacyMapDB.
7683
type privacyMapDB struct {
77-
db *DB
7884
groupID session.ID
7985
}
8086

81-
// Update opens a database read/write transaction and executes the function f
82-
// with the transaction passed as a parameter. After f exits, if f did not
83-
// error, the transaction is committed. Otherwise, if f did error, the
84-
// transaction is rolled back. If the rollback fails, the original error
85-
// returned by f is still returned. If the commit fails, the commit error is
86-
// returned.
87-
//
88-
// NOTE: this is part of the PrivacyMapDB interface.
89-
func (p *privacyMapDB) Update(ctx context.Context, fn func(ctx context.Context,
90-
tx PrivacyMapTx) error) error {
91-
92-
return p.db.Update(func(tx *bbolt.Tx) error {
93-
boltTx := &privacyMapTx{
94-
privacyMapDB: p,
95-
boltTx: tx,
96-
}
97-
98-
return fn(ctx, boltTx)
99-
})
100-
}
101-
102-
// View opens a database read transaction and executes the function f with the
103-
// transaction passed as a parameter. After f exits, the transaction is rolled
104-
// back. If f errors, its error is returned, not a rollback error (if any
105-
// occur).
106-
//
107-
// NOTE: this is part of the PrivacyMapDB interface.
108-
func (p *privacyMapDB) View(ctx context.Context, fn func(ctx context.Context,
109-
tx PrivacyMapTx) error) error {
110-
111-
return p.db.View(func(tx *bbolt.Tx) error {
112-
boltTx := &privacyMapTx{
113-
privacyMapDB: p,
114-
boltTx: tx,
115-
}
116-
117-
return fn(ctx, boltTx)
118-
})
119-
}
120-
12187
// privacyMapTx is an implementation of PrivacyMapTx.
12288
type privacyMapTx struct {
12389
*privacyMapDB

0 commit comments

Comments
 (0)