Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ You'll need to build [RocksDB](https://github.com/facebook/rocksdb) v5.16+ on yo

After that, you can install gorocksdb using the following command:

CGO_CFLAGS="-I/path/to/rocksdb/include" \
CGO_CFLAGS="-I/path/to/rocksdb/include -DUSE_USER_DEFINED_TIMESTAMP" \
CGO_LDFLAGS="-L/path/to/rocksdb -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4 -lzstd" \
go get github.com/tecbot/gorocksdb

Expand Down
27 changes: 27 additions & 0 deletions column_family_ts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//go:build rocksdb_user_timestamp
// +build rocksdb_user_timestamp

package gorocksdb

/*
#cgo CFLAGS: -DUSE_USER_DEFINED_TIMESTAMP
#include "rocksdb/c.h"
*/
import "C"

// EnableUserDefinedTimestamp turns the feature on/off for this column‑family
// *before* the CF is created. It maps straight to
// rocksdb_column_family_options_enable_user_defined_timestamp().
func (opts *ColumnFamilyOptions) EnableUserDefinedTimestamp(enable bool) {
var flag C.uchar
if enable {
flag = 1
}
C.rocksdb_column_family_options_enable_user_defined_timestamp(opts.c, flag)
}

// SetTimestampSize sets the fixed length (in bytes) of the timestamp slice
// RocksDB will expect. Most users pick 8 for uint64 epoch microseconds.
func (opts *ColumnFamilyOptions) SetTimestampSize(size int) {
C.rocksdb_column_family_options_set_timestamp_size(opts.c, C.size_t(size))
}
85 changes: 85 additions & 0 deletions db_ts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//go:build rocksdb_user_timestamp
// +build rocksdb_user_timestamp

package gorocksdb

/*
#cgo CFLAGS: -DUSE_USER_DEFINED_TIMESTAMP
#include "rocksdb/c.h"
#include "gorocksdb.h"
*/
import "C"
import (
"errors"
"unsafe"
)

// PutCFWithTS stores the given key/value pair in the specified column family
// while attaching an explicit timestamp (ts).
func (db *DB) PutCFWithTS(
wo *WriteOptions,
cf *ColumnFamilyHandle,
key, ts, value []byte,
) error {
cErr := C.gorocksdb_put_cf_with_ts(
db.c, wo.c, cf.c,
byteSliceToChar(key), C.size_t(len(key)),
byteSliceToChar(ts), C.size_t(len(ts)),
byteSliceToChar(value), C.size_t(len(value)))
return convertErr(cErr)
}

// PutWithTS is the default‑CF convenience wrapper.
func (db *DB) PutWithTS(wo *WriteOptions, key, ts, value []byte) error {
return db.PutCFWithTS(wo, db.defaultCF, key, ts, value)
}

// DeleteCFWithTS marks the given key as deleted with the supplied timestamp.
// The semantics mirror PutCFWithTS but create a tombstone instead of a value.
func (db *DB) DeleteCFWithTS(
wo *WriteOptions,
cf *ColumnFamilyHandle,
key, ts []byte,
) error {
cErr := C.gorocksdb_delete_cf_with_ts(
db.c, wo.c, cf.c,
byteSliceToChar(key), C.size_t(len(key)),
byteSliceToChar(ts), C.size_t(len(ts)))
return convertErr(cErr)
}

// DeleteWithTS is the default‑CF convenience wrapper.
func (db *DB) DeleteWithTS(wo *WriteOptions, key, ts []byte) error {
return db.DeleteCFWithTS(wo, db.defaultCF, key, ts)
}

// IncreaseFullHistoryTsLow raises RocksDB’s low‑water mark for full‑history
// retention for the specified column family.
func (db *DB) IncreaseFullHistoryTsLow(cf *ColumnFamilyHandle, ts []byte) error {
cErr := C.gorocksdb_increase_full_history_ts_low(
db.c, cf.c,
byteSliceToChar(ts), C.size_t(len(ts)))
return convertErr(cErr)
}

// byteSliceToChar safely converts a nil‑able Go []byte to *C.char.
func byteSliceToChar(b []byte) *C.char {
if len(b) == 0 {
return nil
}
return (*C.char)(unsafe.Pointer(&b[0]))
}

// convertErr frees a rocksdb_status_t* and converts it to Go error
func convertErr(st *C.rocksdb_status_t) error {
if st == nil {
return nil
}
defer C.rocksdb_status_destroy(st)

if C.rocksdb_status_code(st) == C.rocksdb_status_code_t(0) {
return nil
}
msg := C.GoString(C.rocksdb_status_to_string(st))
return errors.New(msg)
}
27 changes: 27 additions & 0 deletions gorocksdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,30 @@ rocksdb_slicetransform_t* gorocksdb_slicetransform_create(uintptr_t idx) {
(unsigned char (*)(void*, const char*, size_t))(gorocksdb_slicetransform_in_range),
(const char* (*)(void*))(gorocksdb_slicetransform_name));
}

/* gorocksdb.c */
rocksdb_status_t* gorocksdb_put_cf_with_ts(
rocksdb_t* db,
const rocksdb_writeoptions_t* options,
rocksdb_column_family_handle_t* cf,
const char* key, size_t keylen,
const char* ts, size_t tslen,
const char* val, size_t vallen) {
return rocksdb_put_cf_with_ts(db, options, cf, key, keylen, ts, tslen, val, vallen);
}

rocksdb_status_t* gorocksdb_increase_full_history_ts_low(
rocksdb_t* db,
rocksdb_column_family_handle_t* cf,
const char* ts, size_t tslen) {
return rocksdb_increase_full_history_ts_low(db, cf, ts, tslen);
}

rocksdb_status_t* gorocksdb_delete_cf_with_ts(
rocksdb_t* db,
const rocksdb_writeoptions_t* options,
rocksdb_column_family_handle_t* cf,
const char* key, size_t keylen,
const char* ts, size_t tslen) {
return rocksdb_delete_cf_with_ts(db, options, cf, key, keylen, ts, tslen);
}
21 changes: 21 additions & 0 deletions gorocksdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,24 @@ extern void gorocksdb_mergeoperator_delete_value(void* state, const char* v, siz
/* Slice Transform */

extern rocksdb_slicetransform_t* gorocksdb_slicetransform_create(uintptr_t idx);

/* gorocksdb.h */
extern rocksdb_status_t* gorocksdb_put_cf_with_ts(
rocksdb_t* db,
const rocksdb_writeoptions_t* options,
rocksdb_column_family_handle_t* cf,
const char* key, size_t keylen,
const char* ts, size_t tslen,
const char* val, size_t vallen);

extern rocksdb_status_t* gorocksdb_increase_full_history_ts_low(
rocksdb_t* db,
rocksdb_column_family_handle_t* cf,
const char* ts, size_t tslen);

extern rocksdb_status_t* gorocksdb_delete_cf_with_ts(
rocksdb_t*, const rocksdb_writeoptions_t*,
rocksdb_column_family_handle_t*,
const char* key, size_t keylen,
const char* ts, size_t tslen);