diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..1b422df5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,21 @@ +name: CI +on: [push, pull_request] +jobs: + test: + strategy: + matrix: + go-version: [1.14.x, 1.20.x, 1.21.x] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.go-version }} + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.55 + - run: go vet ./... + - run: go test -short -timeout 1h ./... + - run: go test -timeout 30m -race -run "TestDB_(Concurrent|GoleveldbIssue74)" ./leveldb diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a92ab7f5..00000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go - -before_install: - - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.46.2 - -go: - - 1.14.x - - 1.18.x - - tip - -script: - - go vet ./... - - golangci-lint run - - go test -short -timeout 1h ./... - - go test -timeout 30m -race -run "TestDB_(Concurrent|GoleveldbIssue74)" ./leveldb diff --git a/README.md b/README.md index 113bb1b8..e89427bc 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,19 @@ This is an implementation of the [LevelDB key/value database](https://github.com/google/leveldb) in the [Go programming language](https://go.dev). -[![Build Status](https://app.travis-ci.com/syndtr/goleveldb.svg?branch=master)](https://app.travis-ci.com/syndtr/goleveldb) +[![Build Status](https://github.com/syndtr/goleveldb/actions/workflows/ci.yml/badge.svg)](https://github.com/syndtr/goleveldb/actions) -Installation ------------ +## Installation - go get github.com/syndtr/goleveldb/leveldb + go get github.com/syndtr/goleveldb/leveldb -Requirements ------------ +## Requirements -* Need at least `go1.14` or newer. +- Need at least `go1.14` or newer. -Usage ------------ +## Usage Create or open a database: + ```go // The returned DB instance is safe for concurrent use. Which mean that all // DB's methods may be called concurrently from multiple goroutine. @@ -24,7 +22,9 @@ db, err := leveldb.OpenFile("path/to/db", nil) defer db.Close() ... ``` + Read or modify the database content: + ```go // Remember that the contents of the returned slice should not be modified. data, err := db.Get([]byte("key"), nil) @@ -36,6 +36,7 @@ err = db.Delete([]byte("key"), nil) ``` Iterate over database content: + ```go iter := db.NewIterator(nil, nil) for iter.Next() { @@ -49,7 +50,9 @@ iter.Release() err = iter.Error() ... ``` + Seek-then-Iterate: + ```go iter := db.NewIterator(nil, nil) for ok := iter.Seek(key); ok; ok = iter.Next() { @@ -60,7 +63,9 @@ iter.Release() err = iter.Error() ... ``` + Iterate over subset of database content: + ```go iter := db.NewIterator(&util.Range{Start: []byte("foo"), Limit: []byte("xoo")}, nil) for iter.Next() { @@ -71,7 +76,9 @@ iter.Release() err = iter.Error() ... ``` + Iterate over subset of database content with a particular prefix: + ```go iter := db.NewIterator(util.BytesPrefix([]byte("foo-")), nil) for iter.Next() { @@ -82,7 +89,9 @@ iter.Release() err = iter.Error() ... ``` + Batch writes: + ```go batch := new(leveldb.Batch) batch.Put([]byte("foo"), []byte("value")) @@ -91,7 +100,9 @@ batch.Delete([]byte("baz")) err = db.Write(batch, nil) ... ``` + Use bloom filter: + ```go o := &opt.Options{ Filter: filter.NewBloomFilter(10), @@ -101,7 +112,7 @@ db, err := leveldb.OpenFile("path/to/db", o) defer db.Close() ... ``` -Documentation ------------ + +## Documentation You can read package documentation [here](https://pkg.go.dev/github.com/syndtr/goleveldb). diff --git a/go.sum b/go.sum index 89f1075c..0d1d7d7e 100644 --- a/go.sum +++ b/go.sum @@ -93,7 +93,6 @@ golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/leveldb/db.go b/leveldb/db.go index b2724cd9..43bd05db 100644 --- a/leveldb/db.go +++ b/leveldb/db.go @@ -931,6 +931,7 @@ func (db *DB) GetSnapshot() (*Snapshot, error) { // GetProperty returns value of the given property name. // // Property names: +// // leveldb.num-files-at-level{n} // Returns the number of files at level 'n'. // leveldb.stats diff --git a/leveldb/doc.go b/leveldb/doc.go index be768e57..ecd6c492 100644 --- a/leveldb/doc.go +++ b/leveldb/doc.go @@ -40,6 +40,7 @@ // ... // // Iterate over subset of database content with a particular prefix: +// // iter := db.NewIterator(util.BytesPrefix([]byte("foo-")), nil) // for iter.Next() { // // Use key/value. @@ -51,25 +52,25 @@ // // Seek-then-Iterate: // -// iter := db.NewIterator(nil, nil) -// for ok := iter.Seek(key); ok; ok = iter.Next() { -// // Use key/value. -// ... -// } -// iter.Release() -// err = iter.Error() -// ... +// iter := db.NewIterator(nil, nil) +// for ok := iter.Seek(key); ok; ok = iter.Next() { +// // Use key/value. +// ... +// } +// iter.Release() +// err = iter.Error() +// ... // // Iterate over subset of database content: // -// iter := db.NewIterator(&util.Range{Start: []byte("foo"), Limit: []byte("xoo")}, nil) -// for iter.Next() { -// // Use key/value. -// ... -// } -// iter.Release() -// err = iter.Error() -// ... +// iter := db.NewIterator(&util.Range{Start: []byte("foo"), Limit: []byte("xoo")}, nil) +// for iter.Next() { +// // Use key/value. +// ... +// } +// iter.Release() +// err = iter.Error() +// ... // // Batch writes: // diff --git a/leveldb/journal/journal.go b/leveldb/journal/journal.go index f7f8b540..14033606 100644 --- a/leveldb/journal/journal.go +++ b/leveldb/journal/journal.go @@ -25,6 +25,7 @@ // Neither Readers or Writers are safe to use concurrently. // // Example code: +// // func read(r io.Reader) ([]string, error) { // var ss []string // journals := journal.NewReader(r, nil, true, true) diff --git a/leveldb/opt/options.go b/leveldb/opt/options.go index 48fb0416..77477dea 100644 --- a/leveldb/opt/options.go +++ b/leveldb/opt/options.go @@ -78,16 +78,16 @@ func (p *passthroughCacher) New(capacity int) cache.Cacher { // // Shared cache example: // -// fileCache := opt.NewLRU(500) -// blockCache := opt.NewLRU(8 * opt.MiB) -// options := &opt.Options{ -// OpenFilesCacher: fileCache, -// BlockCacher: blockCache, -// } -// db1, err1 := leveldb.OpenFile("path/to/db1", options) -// ... -// db2, err2 := leveldb.OpenFile("path/to/db2", options) -// ... +// fileCache := opt.NewLRU(500) +// blockCache := opt.NewLRU(8 * opt.MiB) +// options := &opt.Options{ +// OpenFilesCacher: fileCache, +// BlockCacher: blockCache, +// } +// db1, err1 := leveldb.OpenFile("path/to/db1", options) +// ... +// db2, err2 := leveldb.OpenFile("path/to/db2", options) +// ... func PassthroughCacher(x cache.Cacher) Cacher { return &passthroughCacher{x} } diff --git a/leveldb/storage/file_storage.go b/leveldb/storage/file_storage.go index 3c5e70a0..bebddb1c 100644 --- a/leveldb/storage/file_storage.go +++ b/leveldb/storage/file_storage.go @@ -126,7 +126,7 @@ func OpenFile(path string, readOnly bool) (Storage, error) { if err != nil { return nil, err } - logSize, err = logw.Seek(0, os.SEEK_END) + logSize, err = logw.Seek(0, io.SeekEnd) if err != nil { logw.Close() return nil, err diff --git a/manualtest/dbstress/main.go b/manualtest/dbstress/main.go index 3e2c8d77..05b7ab25 100644 --- a/manualtest/dbstress/main.go +++ b/manualtest/dbstress/main.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "flag" "fmt" + "io" "log" mrand "math/rand" "net/http" @@ -162,7 +163,7 @@ func (ts *testingStorage) scanTable(fd storage.FileDesc, checksum bool) (corrupt } defer r.Close() - size, err := r.Seek(0, os.SEEK_END) + size, err := r.Seek(0, io.SeekEnd) if err != nil { return false, err }