Skip to content

Commit 96c3854

Browse files
authored
Merge pull request #57 from ucwong/dev
pebble engine added & test
2 parents 744100e + 0942222 commit 96c3854

File tree

7 files changed

+811
-31
lines changed

7 files changed

+811
-31
lines changed

.gitignore

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
# Binaries for programs and plugins
2-
*.exe
3-
*.exe~
4-
*.dll
5-
*.so
6-
*.dylib
7-
8-
# Test binary, built with `go test -c`
9-
*.test
10-
11-
# Output of the go coverage tool, specifically when used with LiteIDE
12-
*.out
13-
14-
# Dependency directories (remove the comment below to include it)
15-
# vendor/
16-
*.badger*
17-
.badger
18-
*.bolt*
19-
.bolt
20-
*.leveldb*
21-
.leveldb
22-
.ha
23-
*.ha*
24-
*.sh
25-
coverage.*
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
8+
# Test binary, built with `go test -c`
9+
*.test
10+
11+
# Output of the go coverage tool, specifically when used with LiteIDE
12+
*.out
13+
14+
# Dependency directories (remove the comment below to include it)
15+
# vendor/
16+
*.badger*
17+
.badger
18+
*.bolt*
19+
.bolt
20+
*.leveldb*
21+
.leveldb
22+
.ha
23+
*.ha*
24+
*.sh
25+
coverage.*
26+
.golang-kv

go.mod

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@ module github.com/ucwong/golang-kv
33
go 1.19
44

55
require (
6+
github.com/cockroachdb/pebble v0.0.0-20230209222158-0568b5fd3d14
67
github.com/dgraph-io/badger/v3 v3.0.0-20221216181207-499b1424621c
78
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
89
github.com/ucwong/go-ttlmap v1.0.2-0.20221020173635-331e7ddde2bb
910
go.etcd.io/bbolt v1.3.7-0.20230211214749-46437cea06b7
1011
)
1112

1213
require (
14+
github.com/DataDog/zstd v1.4.5 // indirect
15+
github.com/beorn7/perks v1.0.1 // indirect
1316
github.com/cespare/xxhash/v2 v2.2.0 // indirect
17+
github.com/cockroachdb/errors v1.8.1 // indirect
18+
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect
19+
github.com/cockroachdb/redact v1.0.8 // indirect
20+
github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect
1421
github.com/dgraph-io/ristretto v0.1.1 // indirect
1522
github.com/dustin/go-humanize v1.0.0 // indirect
1623
github.com/gogo/protobuf v1.3.2 // indirect
@@ -19,9 +26,17 @@ require (
1926
github.com/golang/protobuf v1.5.2 // indirect
2027
github.com/golang/snappy v0.0.4 // indirect
2128
github.com/google/flatbuffers v22.11.23+incompatible // indirect
22-
github.com/klauspost/compress v1.15.13 // indirect
29+
github.com/klauspost/compress v1.15.15 // indirect
30+
github.com/kr/pretty v0.2.1 // indirect
31+
github.com/kr/text v0.2.0 // indirect
32+
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
2333
github.com/pkg/errors v0.9.1 // indirect
34+
github.com/prometheus/client_golang v1.12.0 // indirect
35+
github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect
36+
github.com/prometheus/common v0.32.1 // indirect
37+
github.com/prometheus/procfs v0.7.3 // indirect
2438
go.opencensus.io v0.24.0 // indirect
39+
golang.org/x/exp v0.0.0-20200513190911-00229845015e // indirect
2540
golang.org/x/net v0.4.0 // indirect
2641
golang.org/x/sys v0.4.0 // indirect
2742
google.golang.org/protobuf v1.28.1 // indirect

go.sum

Lines changed: 467 additions & 3 deletions
Large diffs are not rendered by default.

kv.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/ucwong/golang-kv/badger"
2020
"github.com/ucwong/golang-kv/bolt"
2121
"github.com/ucwong/golang-kv/leveldb"
22+
"github.com/ucwong/golang-kv/pebble"
2223
)
2324

2425
func Badger(path string, opt ...badger.BadgerOption) Bucket {
@@ -32,3 +33,7 @@ func Bolt(path string, opt ...bolt.BoltOption) Bucket {
3233
func LevelDB(path string, opt ...leveldb.LevelDBOption) Bucket {
3334
return leveldb.Open(path, opt...)
3435
}
36+
37+
func Pebble(path string, opt ...pebble.PebbleOption) Bucket {
38+
return pebble.Open(path, opt...)
39+
}

leveldb/leveldb.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ func (ldb *LevelDB) Get(k []byte) (v []byte) {
8181
return []byte(item.Value().(string))
8282
}
8383

84-
v1, _ := ldb.engine.Get(k, nil)
85-
v = v1
84+
v, _ = ldb.engine.Get(k, nil)
8685
return
8786
}
8887

pebble/pebble.go

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Copyright (C) 2023 ucwong
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>
15+
16+
package pebble
17+
18+
import (
19+
"bytes"
20+
//"fmt"
21+
"path/filepath"
22+
"sync"
23+
"time"
24+
25+
"github.com/cockroachdb/pebble"
26+
"github.com/ucwong/go-ttlmap"
27+
"github.com/ucwong/golang-kv/common"
28+
)
29+
30+
type Pebble struct {
31+
engine *pebble.DB
32+
ttl_map *ttlmap.Map
33+
wb *pebble.Batch
34+
once sync.Once
35+
}
36+
37+
type PebbleOption func(pebble.Options) pebble.Options
38+
39+
func Open(path string, opts ...PebbleOption) *Pebble {
40+
path = filepath.Join(path, common.GLOBAL_SPACE, ".pebble")
41+
db := &Pebble{}
42+
option := pebble.Options{}
43+
for _, op := range opts {
44+
option = op(option)
45+
}
46+
peb, err := pebble.Open(path, &option)
47+
if err != nil {
48+
return nil
49+
}
50+
db.engine = peb
51+
db.wb = new(pebble.Batch)
52+
53+
options := &ttlmap.Options{
54+
InitialCapacity: 1024 * 1024,
55+
OnWillExpire: func(key string, item ttlmap.Item) {
56+
//fmt.Printf("expired: [%s=%v]\n", key, item.Value())
57+
//b.Del([]byte(key))
58+
},
59+
OnWillEvict: func(key string, item ttlmap.Item) {
60+
//fmt.Printf("evicted: [%s=%v]\n", key, item.Value())
61+
//db.Del([]byte(key))
62+
db.engine.Delete([]byte(key), nil)
63+
},
64+
}
65+
db.ttl_map = ttlmap.New(options)
66+
return db
67+
}
68+
69+
func (peb *Pebble) Get(k []byte) (v []byte) {
70+
item, err := peb.ttl_map.Get(string(k))
71+
if err == nil {
72+
return []byte(item.Value().(string))
73+
}
74+
75+
v, closer, err := peb.engine.Get(k)
76+
if err == nil {
77+
defer closer.Close()
78+
}
79+
return
80+
}
81+
82+
func (peb *Pebble) Set(k, v []byte) (err error) {
83+
if _, err = peb.ttl_map.Delete(string(k)); err != nil {
84+
return
85+
}
86+
87+
err = peb.engine.Set(k, v, pebble.Sync)
88+
return
89+
}
90+
91+
func (peb *Pebble) Del(k []byte) (err error) {
92+
if _, err = peb.ttl_map.Delete(string(k)); err != nil {
93+
return
94+
}
95+
96+
err = peb.engine.Delete(k, nil)
97+
return
98+
}
99+
100+
func (peb *Pebble) Prefix(k []byte) (res [][]byte) {
101+
keyUpperBound := func(b []byte) []byte {
102+
end := make([]byte, len(b))
103+
copy(end, b)
104+
for i := len(end) - 1; i >= 0; i-- {
105+
end[i] = end[i] + 1
106+
if end[i] != 0 {
107+
return end[:i+1]
108+
}
109+
}
110+
return nil // no upper-bound
111+
}
112+
prefixIterOptions := func(prefix []byte) *pebble.IterOptions {
113+
return &pebble.IterOptions{
114+
LowerBound: prefix,
115+
UpperBound: keyUpperBound(prefix),
116+
}
117+
}
118+
119+
iter := peb.engine.NewIter(prefixIterOptions(k))
120+
defer iter.Close()
121+
for iter.First(); iter.Valid(); iter.Next() {
122+
res = append(res, common.SafeCopy(nil, iter.Value()))
123+
}
124+
return
125+
}
126+
127+
func (peb *Pebble) Suffix(k []byte) (res [][]byte) {
128+
iter := peb.engine.NewIter(nil)
129+
defer iter.Close()
130+
for iter.First(); iter.Valid(); iter.Next() {
131+
if bytes.HasSuffix(iter.Key(), k) {
132+
res = append(res, common.SafeCopy(nil, iter.Value()))
133+
}
134+
}
135+
return
136+
}
137+
138+
func (peb *Pebble) Range(start, limit []byte) (res [][]byte) {
139+
return
140+
}
141+
142+
func (peb *Pebble) Scan() (res [][]byte) {
143+
iter := peb.engine.NewIter(nil)
144+
defer iter.Close()
145+
for iter.First(); iter.Valid(); iter.Next() {
146+
res = append(res, common.SafeCopy(nil, iter.Value()))
147+
}
148+
return
149+
}
150+
151+
func (peb *Pebble) SetTTL(k, v []byte, expire time.Duration) (err error) {
152+
if err = peb.ttl_map.Set(string(k), ttlmap.NewItem(string(v), ttlmap.WithTTL(expire)), nil); err != nil {
153+
return
154+
}
155+
156+
err = peb.engine.Set(k, v, pebble.Sync)
157+
158+
if err != nil {
159+
// TODO
160+
peb.ttl_map.Delete(string(k))
161+
}
162+
163+
return
164+
}
165+
166+
func (peb *Pebble) Close() error {
167+
peb.once.Do(func() {
168+
peb.ttl_map.Drain()
169+
})
170+
return peb.engine.Close()
171+
}
172+
173+
func (peb *Pebble) BatchSet(kvs map[string][]byte) error {
174+
for k, v := range kvs {
175+
peb.wb.Set([]byte(k), v, nil)
176+
}
177+
peb.engine.Apply(peb.wb, nil)
178+
return peb.wb.SyncWait()
179+
}

0 commit comments

Comments
 (0)