mirror of
https://github.com/gogrlx/bitcask.git
synced 2026-04-16 18:14:57 -07:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d9bfbb408 | ||
|
|
d8a48f9eea | ||
|
|
65e7877bdf | ||
|
|
5711478dd6 | ||
|
|
336795285e | ||
|
|
7fba9bd4b7 | ||
|
|
e117ffd2e9 |
@@ -12,11 +12,3 @@ steps:
|
|||||||
settings:
|
settings:
|
||||||
token:
|
token:
|
||||||
from_secret: codecov-token
|
from_secret: codecov-token
|
||||||
|
|
||||||
- name: notify
|
|
||||||
image: plugins/webhook
|
|
||||||
urls: https://msgbus.mills.io/ci.mills.io
|
|
||||||
when:
|
|
||||||
status:
|
|
||||||
- success
|
|
||||||
- failure
|
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ builds:
|
|||||||
binary: bitcask
|
binary: bitcask
|
||||||
main: ./cmd/bitcask
|
main: ./cmd/bitcask
|
||||||
flags: -tags "static_build"
|
flags: -tags "static_build"
|
||||||
ldflags: -w -X .Version={{.Version}} -X .Commit={{.Commit}}
|
ldflags: -w -X github.com/prologic/bitcask/internal.Version={{.Version}} -X github.com/prologic/bitcask/internal.Commit={{.Commit}}
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
-
|
-
|
||||||
binary: bitcaskd
|
binary: bitcaskd
|
||||||
main: ./cmd/bitcaskd
|
main: ./cmd/bitcaskd
|
||||||
flags: -tags "static_build"
|
flags: -tags "static_build"
|
||||||
ldflags: -w -X .Version={{.Version}} -X .Commit={{.Commit}}
|
ldflags: -w -X github.com/prologic/bitcask/internal.Version={{.Version}} -X github.com/prologic/bitcask/internal.Commit={{.Commit}}
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
sign:
|
sign:
|
||||||
|
|||||||
1
Makefile
1
Makefile
@@ -25,6 +25,7 @@ generate:
|
|||||||
|
|
||||||
install: build
|
install: build
|
||||||
@go install ./cmd/bitcask/...
|
@go install ./cmd/bitcask/...
|
||||||
|
@go install ./cmd/bitcaskd/...
|
||||||
|
|
||||||
image:
|
image:
|
||||||
@docker build -t prologic/bitcask .
|
@docker build -t prologic/bitcask .
|
||||||
|
|||||||
22
bitcask.go
22
bitcask.go
@@ -1,7 +1,7 @@
|
|||||||
package bitcask
|
package bitcask
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -15,6 +15,14 @@ import (
|
|||||||
"github.com/prologic/bitcask/internal"
|
"github.com/prologic/bitcask/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrKeyNotFound = errors.New("error: key not found")
|
||||||
|
ErrKeyTooLarge = errors.New("error: key too large")
|
||||||
|
ErrValueTooLarge = errors.New("error: value too large")
|
||||||
|
ErrChecksumFailed = errors.New("error: checksum failed")
|
||||||
|
ErrDatabaseLocked = errors.New("error: database locked")
|
||||||
|
)
|
||||||
|
|
||||||
type Bitcask struct {
|
type Bitcask struct {
|
||||||
*flock.Flock
|
*flock.Flock
|
||||||
|
|
||||||
@@ -49,7 +57,7 @@ func (b *Bitcask) Get(key string) ([]byte, error) {
|
|||||||
|
|
||||||
item, ok := b.keydir.Get(key)
|
item, ok := b.keydir.Get(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error: key not found %s", key)
|
return nil, ErrKeyNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.FileID == b.curr.FileID() {
|
if item.FileID == b.curr.FileID() {
|
||||||
@@ -65,7 +73,7 @@ func (b *Bitcask) Get(key string) ([]byte, error) {
|
|||||||
|
|
||||||
checksum := crc32.ChecksumIEEE(e.Value)
|
checksum := crc32.ChecksumIEEE(e.Value)
|
||||||
if checksum != e.Checksum {
|
if checksum != e.Checksum {
|
||||||
return nil, fmt.Errorf("error: checksum falied %s %d != %d", key, e.Checksum, checksum)
|
return nil, ErrChecksumFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.Value, nil
|
return e.Value, nil
|
||||||
@@ -73,10 +81,10 @@ func (b *Bitcask) Get(key string) ([]byte, error) {
|
|||||||
|
|
||||||
func (b *Bitcask) Put(key string, value []byte) error {
|
func (b *Bitcask) Put(key string, value []byte) error {
|
||||||
if len(key) > b.config.MaxKeySize {
|
if len(key) > b.config.MaxKeySize {
|
||||||
return fmt.Errorf("error: key too large %d > %d", len(key), b.config.MaxKeySize)
|
return ErrKeyTooLarge
|
||||||
}
|
}
|
||||||
if len(value) > b.config.MaxValueSize {
|
if len(value) > b.config.MaxValueSize {
|
||||||
return fmt.Errorf("error: value too large %d > %d", len(value), b.config.MaxValueSize)
|
return ErrValueTooLarge
|
||||||
}
|
}
|
||||||
|
|
||||||
offset, err := b.put(key, value)
|
offset, err := b.put(key, value)
|
||||||
@@ -346,7 +354,7 @@ func Open(path string, options ...option) (*Bitcask, error) {
|
|||||||
|
|
||||||
bitcask := &Bitcask{
|
bitcask := &Bitcask{
|
||||||
Flock: flock.New(filepath.Join(path, "lock")),
|
Flock: flock.New(filepath.Join(path, "lock")),
|
||||||
config: NewDefaultConfig(),
|
config: newDefaultConfig(),
|
||||||
path: path,
|
path: path,
|
||||||
curr: curr,
|
curr: curr,
|
||||||
keydir: keydir,
|
keydir: keydir,
|
||||||
@@ -369,7 +377,7 @@ func Open(path string, options ...option) (*Bitcask, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !locked {
|
if !locked {
|
||||||
return nil, fmt.Errorf("error: database locked %s", path)
|
return nil, ErrDatabaseLocked
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitcask, nil
|
return bitcask, nil
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func TestAll(t *testing.T) {
|
|||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
_, err = db.Get("foo")
|
_, err = db.Get("foo")
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
assert.Equal("error: key not found foo", err.Error())
|
assert.Equal(ErrKeyNotFound, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Sync", func(t *testing.T) {
|
t.Run("Sync", func(t *testing.T) {
|
||||||
@@ -92,7 +92,7 @@ func TestDeletedKeys(t *testing.T) {
|
|||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
_, err = db.Get("foo")
|
_, err = db.Get("foo")
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
assert.Equal("error: key not found foo", err.Error())
|
assert.Equal(ErrKeyNotFound, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Sync", func(t *testing.T) {
|
t.Run("Sync", func(t *testing.T) {
|
||||||
@@ -120,7 +120,7 @@ func TestDeletedKeys(t *testing.T) {
|
|||||||
t.Run("Get", func(t *testing.T) {
|
t.Run("Get", func(t *testing.T) {
|
||||||
_, err = db.Get("foo")
|
_, err = db.Get("foo")
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
assert.Equal("error: key not found foo", err.Error())
|
assert.Equal(ErrKeyNotFound, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Close", func(t *testing.T) {
|
t.Run("Close", func(t *testing.T) {
|
||||||
@@ -148,7 +148,7 @@ func TestMaxKeySize(t *testing.T) {
|
|||||||
value := []byte("foobar")
|
value := []byte("foobar")
|
||||||
err = db.Put(key, value)
|
err = db.Put(key, value)
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
assert.Equal("error: key too large 17 > 16", err.Error())
|
assert.Equal(ErrKeyTooLarge, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ func TestMaxValueSize(t *testing.T) {
|
|||||||
value := []byte(strings.Repeat(" ", 17))
|
value := []byte(strings.Repeat(" ", 17))
|
||||||
err = db.Put(key, value)
|
err = db.Put(key, value)
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
assert.Equal("error: value too large 17 > 16", err.Error())
|
assert.Equal(ErrValueTooLarge, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +387,7 @@ func TestLocking(t *testing.T) {
|
|||||||
|
|
||||||
_, err = Open(testdir)
|
_, err = Open(testdir)
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
assert.Equal(fmt.Sprintf("error: database locked %s", testdir), err.Error())
|
assert.Equal(ErrDatabaseLocked, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type benchmarkTestCase struct {
|
type benchmarkTestCase struct {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type config struct {
|
|||||||
MaxValueSize int
|
MaxValueSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultConfig() *config {
|
func newDefaultConfig() *config {
|
||||||
return &config{
|
return &config{
|
||||||
MaxDatafileSize: DefaultMaxDatafileSize,
|
MaxDatafileSize: DefaultMaxDatafileSize,
|
||||||
MaxKeySize: DefaultMaxKeySize,
|
MaxKeySize: DefaultMaxKeySize,
|
||||||
|
|||||||
Reference in New Issue
Block a user