diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..52e07ba --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,67 @@ +name: Continuous integration + +on: [push, pull_request] + +defaults: + run: + shell: bash + +jobs: + test: + strategy: + matrix: + os: [ubuntu-20.04, ubuntu-18.04, macos-11.0, macos-10.15] + go: [1.16.x, 1.15.x, 1.14.x, 1.13.x] + name: Go ${{ matrix.go }} tests @ ${{ matrix.os }} + runs-on: ${{ matrix.os }} + steps: + - name: Install Linux dependencies + if: startsWith(matrix.os, 'ubuntu-') + run: | + sudo apt-get update + sudo apt-get install -yq librocksdb-dev + + - name: Install MacOS dependencies + if: startsWith(matrix.os, 'macos-') + run: | + brew install rocksdb + + - name: Install Golang ${{ matrix.go }} + id: install-golang + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + - run: go version + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Cache Golang modules + uses: actions/cache@v2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Test v5 + if: startsWith(matrix.os, 'ubuntu-') + run: go test -v + + - name: Test v6.16 or later + if: startsWith(matrix.os, 'macos-') + run: go test -v -tags rocksdb_6_16 + + golangci: + name: lint + runs-on: ubuntu-20.04 + steps: + - name: Install Linux dependencies + run: | + sudo apt-get update + sudo apt-get install -yq librocksdb-dev + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: v1.38 diff --git a/checkpoint_test.go b/checkpoint_test.go index 1ea10fd..d90d47e 100644 --- a/checkpoint_test.go +++ b/checkpoint_test.go @@ -41,8 +41,8 @@ func TestCheckpoint(t *testing.T) { opts := NewDefaultOptions() opts.SetCreateIfMissing(true) dbCheck, err = OpenDb(opts, dir) - defer dbCheck.Close() ensure.Nil(t, err) + defer dbCheck.Close() // test keys var value *Slice diff --git a/db.go b/db.go index 64735c6..5764f7c 100755 --- a/db.go +++ b/db.go @@ -577,89 +577,6 @@ func (db *DB) DropColumnFamily(c *ColumnFamilyHandle) error { return nil } -// GetApproximateSizes returns the approximate number of bytes of file system -// space used by one or more key ranges. -// -// The keys counted will begin at Range.Start and end on the key before -// Range.Limit. -func (db *DB) GetApproximateSizes(ranges []Range) []uint64 { - sizes := make([]uint64, len(ranges)) - if len(ranges) == 0 { - return sizes - } - - cStarts := make([]*C.char, len(ranges)) - cLimits := make([]*C.char, len(ranges)) - cStartLens := make([]C.size_t, len(ranges)) - cLimitLens := make([]C.size_t, len(ranges)) - for i, r := range ranges { - cStarts[i] = (*C.char)(C.CBytes(r.Start)) - cStartLens[i] = C.size_t(len(r.Start)) - cLimits[i] = (*C.char)(C.CBytes(r.Limit)) - cLimitLens[i] = C.size_t(len(r.Limit)) - } - - defer func() { - for i := range ranges { - C.free(unsafe.Pointer(cStarts[i])) - C.free(unsafe.Pointer(cLimits[i])) - } - }() - - C.rocksdb_approximate_sizes( - db.c, - C.int(len(ranges)), - &cStarts[0], - &cStartLens[0], - &cLimits[0], - &cLimitLens[0], - (*C.uint64_t)(&sizes[0])) - - return sizes -} - -// GetApproximateSizesCF returns the approximate number of bytes of file system -// space used by one or more key ranges in the column family. -// -// The keys counted will begin at Range.Start and end on the key before -// Range.Limit. -func (db *DB) GetApproximateSizesCF(cf *ColumnFamilyHandle, ranges []Range) []uint64 { - sizes := make([]uint64, len(ranges)) - if len(ranges) == 0 { - return sizes - } - - cStarts := make([]*C.char, len(ranges)) - cLimits := make([]*C.char, len(ranges)) - cStartLens := make([]C.size_t, len(ranges)) - cLimitLens := make([]C.size_t, len(ranges)) - for i, r := range ranges { - cStarts[i] = (*C.char)(C.CBytes(r.Start)) - cStartLens[i] = C.size_t(len(r.Start)) - cLimits[i] = (*C.char)(C.CBytes(r.Limit)) - cLimitLens[i] = C.size_t(len(r.Limit)) - } - - defer func() { - for i := range ranges { - C.free(unsafe.Pointer(cStarts[i])) - C.free(unsafe.Pointer(cLimits[i])) - } - }() - - C.rocksdb_approximate_sizes_cf( - db.c, - cf.c, - C.int(len(ranges)), - &cStarts[0], - &cStartLens[0], - &cLimits[0], - &cLimitLens[0], - (*C.uint64_t)(&sizes[0])) - - return sizes -} - // SetOptions dynamically changes options through the SetOptions API. func (db *DB) SetOptions(keys, values []string) error { num_keys := len(keys) diff --git a/db_6.go b/db_6.go new file mode 100644 index 0000000..e599f93 --- /dev/null +++ b/db_6.go @@ -0,0 +1,91 @@ +// +build !rocksdb_6_16 + +package gorocksdb + +// #include +// #include "rocksdb/c.h" +import "C" +import "unsafe" + +// GetApproximateSizes returns the approximate number of bytes of file system +// space used by one or more key ranges. +// +// The keys counted will begin at Range.Start and end on the key before +// Range.Limit. +func (db *DB) GetApproximateSizes(ranges []Range) []uint64 { + sizes := make([]uint64, len(ranges)) + if len(ranges) == 0 { + return sizes + } + + cStarts := make([]*C.char, len(ranges)) + cLimits := make([]*C.char, len(ranges)) + cStartLens := make([]C.size_t, len(ranges)) + cLimitLens := make([]C.size_t, len(ranges)) + for i, r := range ranges { + cStarts[i] = (*C.char)(C.CBytes(r.Start)) + cStartLens[i] = C.size_t(len(r.Start)) + cLimits[i] = (*C.char)(C.CBytes(r.Limit)) + cLimitLens[i] = C.size_t(len(r.Limit)) + } + + defer func() { + for i := range ranges { + C.free(unsafe.Pointer(cStarts[i])) + C.free(unsafe.Pointer(cLimits[i])) + } + }() + + C.rocksdb_approximate_sizes( + db.c, + C.int(len(ranges)), + &cStarts[0], + &cStartLens[0], + &cLimits[0], + &cLimitLens[0], + (*C.uint64_t)(&sizes[0])) + + return sizes +} + +// GetApproximateSizesCF returns the approximate number of bytes of file system +// space used by one or more key ranges in the column family. +// +// The keys counted will begin at Range.Start and end on the key before +// Range.Limit. +func (db *DB) GetApproximateSizesCF(cf *ColumnFamilyHandle, ranges []Range) []uint64 { + sizes := make([]uint64, len(ranges)) + if len(ranges) == 0 { + return sizes + } + + cStarts := make([]*C.char, len(ranges)) + cLimits := make([]*C.char, len(ranges)) + cStartLens := make([]C.size_t, len(ranges)) + cLimitLens := make([]C.size_t, len(ranges)) + for i, r := range ranges { + cStarts[i] = (*C.char)(C.CBytes(r.Start)) + cStartLens[i] = C.size_t(len(r.Start)) + cLimits[i] = (*C.char)(C.CBytes(r.Limit)) + cLimitLens[i] = C.size_t(len(r.Limit)) + } + + defer func() { + for i := range ranges { + C.free(unsafe.Pointer(cStarts[i])) + C.free(unsafe.Pointer(cLimits[i])) + } + }() + + C.rocksdb_approximate_sizes_cf( + db.c, + cf.c, + C.int(len(ranges)), + &cStarts[0], + &cStartLens[0], + &cLimits[0], + &cLimitLens[0], + (*C.uint64_t)(&sizes[0])) + + return sizes +} diff --git a/db_6_16.go b/db_6_16.go new file mode 100644 index 0000000..756f9fc --- /dev/null +++ b/db_6_16.go @@ -0,0 +1,108 @@ +// +build rocksdb_6_16 + +package gorocksdb + +// #include +// #include "rocksdb/c.h" +import "C" +import ( + "errors" + "unsafe" +) + +// GetApproximateSizes returns the approximate number of bytes of file system +// space used by one or more key ranges. +// +// The keys counted will begin at Range.Start and end on the key before +// Range.Limit. +func (db *DB) GetApproximateSizes(ranges []Range) (sizes []uint64, err error) { + var cErr *C.char + sizes = make([]uint64, len(ranges)) + if len(ranges) == 0 { + return + } + + cStarts := make([]*C.char, len(ranges)) + cLimits := make([]*C.char, len(ranges)) + cStartLens := make([]C.size_t, len(ranges)) + cLimitLens := make([]C.size_t, len(ranges)) + for i, r := range ranges { + cStarts[i] = (*C.char)(C.CBytes(r.Start)) + cStartLens[i] = C.size_t(len(r.Start)) + cLimits[i] = (*C.char)(C.CBytes(r.Limit)) + cLimitLens[i] = C.size_t(len(r.Limit)) + } + + defer func() { + for i := range ranges { + C.free(unsafe.Pointer(cStarts[i])) + C.free(unsafe.Pointer(cLimits[i])) + } + }() + + C.rocksdb_approximate_sizes( + db.c, + C.int(len(ranges)), + &cStarts[0], + &cStartLens[0], + &cLimits[0], + &cLimitLens[0], + (*C.uint64_t)(&sizes[0]), + &cErr, + ) + if cErr != nil { + defer C.rocksdb_free(unsafe.Pointer(cErr)) + err = errors.New(C.GoString(cErr)) + } + + return +} + +// GetApproximateSizesCF returns the approximate number of bytes of file system +// space used by one or more key ranges in the column family. +// +// The keys counted will begin at Range.Start and end on the key before +// Range.Limit. +func (db *DB) GetApproximateSizesCF(cf *ColumnFamilyHandle, ranges []Range) (sizes []uint64, err error) { + var cErr *C.char + sizes = make([]uint64, len(ranges)) + if len(ranges) == 0 { + return + } + + cStarts := make([]*C.char, len(ranges)) + cLimits := make([]*C.char, len(ranges)) + cStartLens := make([]C.size_t, len(ranges)) + cLimitLens := make([]C.size_t, len(ranges)) + for i, r := range ranges { + cStarts[i] = (*C.char)(C.CBytes(r.Start)) + cStartLens[i] = C.size_t(len(r.Start)) + cLimits[i] = (*C.char)(C.CBytes(r.Limit)) + cLimitLens[i] = C.size_t(len(r.Limit)) + } + + defer func() { + for i := range ranges { + C.free(unsafe.Pointer(cStarts[i])) + C.free(unsafe.Pointer(cLimits[i])) + } + }() + + C.rocksdb_approximate_sizes_cf( + db.c, + cf.c, + C.int(len(ranges)), + &cStarts[0], + &cStartLens[0], + &cLimits[0], + &cLimitLens[0], + (*C.uint64_t)(&sizes[0]), + &cErr, + ) + if cErr != nil { + defer C.rocksdb_free(unsafe.Pointer(cErr)) + err = errors.New(C.GoString(cErr)) + } + + return +} diff --git a/db_6_16_test.go b/db_6_16_test.go new file mode 100644 index 0000000..6deace3 --- /dev/null +++ b/db_6_16_test.go @@ -0,0 +1,54 @@ +// +build rocksdb_6_16 + +package gorocksdb + +import ( + "testing" + + "github.com/facebookgo/ensure" +) + +func TestDBGetApproximateSizes(t *testing.T) { + db := newTestDB(t, "TestDBGetApproximateSizes", nil) + defer db.Close() + + // no ranges + sizes, err := db.GetApproximateSizes(nil) + ensure.Nil(t, err) + ensure.DeepEqual(t, len(sizes), 0) + + // range will nil start and limit + sizes, err = db.GetApproximateSizes([]Range{{Start: nil, Limit: nil}}) + ensure.Nil(t, err) + ensure.DeepEqual(t, sizes, []uint64{0}) + + // valid range + sizes, err = db.GetApproximateSizes([]Range{{Start: []byte{0x00}, Limit: []byte{0xFF}}}) + ensure.Nil(t, err) + ensure.DeepEqual(t, sizes, []uint64{0}) +} + +func TestDBGetApproximateSizesCF(t *testing.T) { + db := newTestDB(t, "TestDBGetApproximateSizesCF", nil) + defer db.Close() + + o := NewDefaultOptions() + + cf, err := db.CreateColumnFamily(o, "other") + ensure.Nil(t, err) + + // no ranges + sizes, err := db.GetApproximateSizesCF(cf, nil) + ensure.Nil(t, err) + ensure.DeepEqual(t, len(sizes), 0) + + // range will nil start and limit + sizes, err = db.GetApproximateSizesCF(cf, []Range{{Start: nil, Limit: nil}}) + ensure.Nil(t, err) + ensure.DeepEqual(t, sizes, []uint64{0}) + + // valid range + sizes, err = db.GetApproximateSizesCF(cf, []Range{{Start: []byte{0x00}, Limit: []byte{0xFF}}}) + ensure.Nil(t, err) + ensure.DeepEqual(t, sizes, []uint64{0}) +} diff --git a/db_6_test.go b/db_6_test.go new file mode 100644 index 0000000..3c5ca62 --- /dev/null +++ b/db_6_test.go @@ -0,0 +1,48 @@ +// +build !rocksdb_6_16 + +package gorocksdb + +import ( + "testing" + + "github.com/facebookgo/ensure" +) + +func TestDBGetApproximateSizes(t *testing.T) { + db := newTestDB(t, "TestDBGetApproximateSizes", nil) + defer db.Close() + + // no ranges + sizes := db.GetApproximateSizes(nil) + ensure.DeepEqual(t, len(sizes), 0) + + // range will nil start and limit + sizes = db.GetApproximateSizes([]Range{{Start: nil, Limit: nil}}) + ensure.DeepEqual(t, sizes, []uint64{0}) + + // valid range + sizes = db.GetApproximateSizes([]Range{{Start: []byte{0x00}, Limit: []byte{0xFF}}}) + ensure.DeepEqual(t, sizes, []uint64{0}) +} + +func TestDBGetApproximateSizesCF(t *testing.T) { + db := newTestDB(t, "TestDBGetApproximateSizesCF", nil) + defer db.Close() + + o := NewDefaultOptions() + + cf, err := db.CreateColumnFamily(o, "other") + ensure.Nil(t, err) + + // no ranges + sizes := db.GetApproximateSizesCF(cf, nil) + ensure.DeepEqual(t, len(sizes), 0) + + // range will nil start and limit + sizes = db.GetApproximateSizesCF(cf, []Range{{Start: nil, Limit: nil}}) + ensure.DeepEqual(t, sizes, []uint64{0}) + + // valid range + sizes = db.GetApproximateSizesCF(cf, []Range{{Start: []byte{0x00}, Limit: []byte{0xFF}}}) + ensure.DeepEqual(t, sizes, []uint64{0}) +} diff --git a/db_test.go b/db_test.go index 4ccc7aa..87696d5 100755 --- a/db_test.go +++ b/db_test.go @@ -204,42 +204,3 @@ func TestDBMultiGet(t *testing.T) { ensure.DeepEqual(t, values[2].Data(), givenVal2) ensure.DeepEqual(t, values[3].Data(), givenVal3) } - -func TestDBGetApproximateSizes(t *testing.T) { - db := newTestDB(t, "TestDBGetApproximateSizes", nil) - defer db.Close() - - // no ranges - sizes := db.GetApproximateSizes(nil) - ensure.DeepEqual(t, len(sizes), 0) - - // range will nil start and limit - sizes = db.GetApproximateSizes([]Range{{Start: nil, Limit: nil}}) - ensure.DeepEqual(t, sizes, []uint64{0}) - - // valid range - sizes = db.GetApproximateSizes([]Range{{Start: []byte{0x00}, Limit: []byte{0xFF}}}) - ensure.DeepEqual(t, sizes, []uint64{0}) -} - -func TestDBGetApproximateSizesCF(t *testing.T) { - db := newTestDB(t, "TestDBGetApproximateSizesCF", nil) - defer db.Close() - - o := NewDefaultOptions() - - cf, err := db.CreateColumnFamily(o, "other") - ensure.Nil(t, err) - - // no ranges - sizes := db.GetApproximateSizesCF(cf, nil) - ensure.DeepEqual(t, len(sizes), 0) - - // range will nil start and limit - sizes = db.GetApproximateSizesCF(cf, []Range{{Start: nil, Limit: nil}}) - ensure.DeepEqual(t, sizes, []uint64{0}) - - // valid range - sizes = db.GetApproximateSizesCF(cf, []Range{{Start: []byte{0x00}, Limit: []byte{0xFF}}}) - ensure.DeepEqual(t, sizes, []uint64{0}) -} diff --git a/slice_transform_test.go b/slice_transform_test.go index d60c732..28664f1 100644 --- a/slice_transform_test.go +++ b/slice_transform_test.go @@ -43,7 +43,7 @@ func TestNewNoopPrefixTransform(t *testing.T) { } type testSliceTransform struct { - initiated bool + // initiated bool } func (st *testSliceTransform) Name() string { return "gorocksdb.test" } diff --git a/util.go b/util.go index b6637ec..f994d3f 100644 --- a/util.go +++ b/util.go @@ -52,10 +52,10 @@ func cByteSlice(b []byte) *C.char { } // stringToChar returns *C.char from string. -func stringToChar(s string) *C.char { - ptrStr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - return (*C.char)(unsafe.Pointer(ptrStr.Data)) -} +// func stringToChar(s string) *C.char { +// ptrStr := (*reflect.StringHeader)(unsafe.Pointer(&s)) +// return (*C.char)(unsafe.Pointer(ptrStr.Data)) +// } // charSlice converts a C array of *char to a []*C.char. func charSlice(data **C.char, len C.int) []*C.char {