diff --git a/HISTORY.md b/HISTORY.md index bb16b3ad9..cdd5c77e9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,6 +5,11 @@ * Add transaction `get_pinned` and `multi_get` to C API. * Add two-phase commit support to C API. * Add `rocksdb_transaction_get_writebatch_wi` and `rocksdb_transaction_rebuild_from_writebatch` to C API. +* Add SingleDelete for DB in C API +* Add User Defined Timestamp in C API. + * `rocksdb_comparator_with_ts_create` to create timestamp aware comparator + * Put, Get, Delete, SingleDelete, MultiGet APIs has corresponding timestamp aware APIs with suffix `with_ts` + * And Add C API's for Transaction, SstFileWriter, Compaction as mentioned [here](https://github.com/facebook/rocksdb/wiki/User-defined-Timestamp-(Experimental)) ### New Features * Add FileSystem::ReadAsync API in io_tracing diff --git a/db/c.cc b/db/c.cc index 38c76ea26..2abf320a0 100644 --- a/db/c.cc +++ b/db/c.cc @@ -139,14 +139,25 @@ struct rocksdb_readoptions_t { // stack variables to set pointers to in ReadOptions Slice upper_bound; Slice lower_bound; + Slice timestamp; + Slice iter_start_ts; +}; +struct rocksdb_writeoptions_t { + WriteOptions rep; +}; +struct rocksdb_options_t { + Options rep; }; -struct rocksdb_writeoptions_t { WriteOptions rep; }; -struct rocksdb_options_t { Options rep; }; struct rocksdb_compactoptions_t { CompactRangeOptions rep; + Slice full_history_ts_low; +}; +struct rocksdb_block_based_table_options_t { + BlockBasedTableOptions rep; +}; +struct rocksdb_cuckoo_table_options_t { + CuckooTableOptions rep; }; -struct rocksdb_block_based_table_options_t { BlockBasedTableOptions rep; }; -struct rocksdb_cuckoo_table_options_t { CuckooTableOptions rep; }; struct rocksdb_seqfile_t { SequentialFile* rep; }; struct rocksdb_randomfile_t { RandomAccessFile* rep; }; struct rocksdb_writablefile_t { WritableFile* rep; }; @@ -267,11 +278,18 @@ struct rocksdb_compactionfilterfactory_t : public CompactionFilterFactory { struct rocksdb_comparator_t : public Comparator { void* state_; void (*destructor_)(void*); - int (*compare_)( - void*, - const char* a, size_t alen, - const char* b, size_t blen); + int (*compare_)(void*, const char* a, size_t alen, const char* b, + size_t blen); const char* (*name_)(void*); + int (*compare_ts_)(void*, const char* a_ts, size_t a_tslen, const char* b_ts, + size_t b_tslen); + int (*compare_without_ts_)(void*, const char* a, size_t alen, + unsigned char a_has_ts, const char* b, size_t blen, + unsigned char b_has_ts); + + rocksdb_comparator_t() : Comparator() {} + + rocksdb_comparator_t(size_t ts_size) : Comparator(ts_size) {} ~rocksdb_comparator_t() override { (*destructor_)(state_); } @@ -279,6 +297,23 @@ struct rocksdb_comparator_t : public Comparator { return (*compare_)(state_, a.data(), a.size(), b.data(), b.size()); } + int CompareTimestamp(const Slice& a_ts, const Slice& b_ts) const override { + if (compare_ts_ == nullptr) { + return 0; + } + return (*compare_ts_)(state_, a_ts.data(), a_ts.size(), b_ts.data(), + b_ts.size()); + } + + int CompareWithoutTimestamp(const Slice& a, bool a_has_ts, const Slice& b, + bool b_has_ts) const override { + if (compare_without_ts_ == nullptr) { + return Compare(a, b); + } + return (*compare_without_ts_)(state_, a.data(), a.size(), a_has_ts, + b.data(), b.size(), b_has_ts); + } + const char* Name() const override { return (*name_)(state_); } // No-ops since the C binding does not support key shortening methods. @@ -787,6 +822,40 @@ void rocksdb_options_set_uint64add_merge_operator(rocksdb_options_t* opt) { ROCKSDB_NAMESPACE::MergeOperators::CreateUInt64AddOperator(); } +rocksdb_t* rocksdb_open_and_trim_history( + const rocksdb_options_t* db_options, const char* name, + int num_column_families, const char* const* column_family_names, + const rocksdb_options_t* const* column_family_options, + rocksdb_column_family_handle_t** column_family_handles, char* trim_ts, + size_t trim_tslen, char** errptr) { + std::vector column_families; + for (int i = 0; i < num_column_families; i++) { + column_families.push_back(ColumnFamilyDescriptor( + std::string(column_family_names[i]), + ColumnFamilyOptions(column_family_options[i]->rep))); + } + + std::string trim_ts_(trim_ts, trim_tslen); + + DB* db; + std::vector handles; + if (SaveError(errptr, DB::OpenAndTrimHistory( + DBOptions(db_options->rep), std::string(name), + column_families, &handles, &db, trim_ts_))) { + return nullptr; + } + + for (size_t i = 0; i < handles.size(); i++) { + rocksdb_column_family_handle_t* c_handle = + new rocksdb_column_family_handle_t; + c_handle->rep = handles[i]; + column_family_handles[i] = c_handle; + } + rocksdb_t* result = new rocksdb_t; + result->rep = db; + return result; +} + rocksdb_t* rocksdb_open_column_families( const rocksdb_options_t* db_options, const char* name, int num_column_families, const char* const* column_family_names, @@ -985,23 +1054,35 @@ void rocksdb_put( db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen))); } -void rocksdb_put_cf( - rocksdb_t* db, - const rocksdb_writeoptions_t* options, - rocksdb_column_family_handle_t* column_family, - const char* key, size_t keylen, - const char* val, size_t vallen, - char** errptr) { +void rocksdb_put_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, + const char* key, size_t keylen, const char* val, + size_t vallen, char** errptr) { + SaveError(errptr, db->rep->Put(options->rep, column_family->rep, + Slice(key, keylen), Slice(val, vallen))); +} + +void rocksdb_put_with_ts(rocksdb_t* db, const rocksdb_writeoptions_t* options, + const char* key, size_t keylen, const char* ts, + size_t tslen, const char* val, size_t vallen, + char** errptr) { + SaveError(errptr, db->rep->Put(options->rep, Slice(key, keylen), + Slice(ts, tslen), Slice(val, vallen))); +} + +void rocksdb_put_cf_with_ts(rocksdb_t* db, + const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, + const char* key, size_t keylen, const char* ts, + size_t tslen, const char* val, size_t vallen, + char** errptr) { SaveError(errptr, - db->rep->Put(options->rep, column_family->rep, - Slice(key, keylen), Slice(val, vallen))); + db->rep->Put(options->rep, column_family->rep, Slice(key, keylen), + Slice(ts, tslen), Slice(val, vallen))); } -void rocksdb_delete( - rocksdb_t* db, - const rocksdb_writeoptions_t* options, - const char* key, size_t keylen, - char** errptr) { +void rocksdb_delete(rocksdb_t* db, const rocksdb_writeoptions_t* options, + const char* key, size_t keylen, char** errptr) { SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen))); } @@ -1012,7 +1093,77 @@ void rocksdb_delete_cf( const char* key, size_t keylen, char** errptr) { SaveError(errptr, db->rep->Delete(options->rep, column_family->rep, - Slice(key, keylen))); + Slice(key, keylen))); +} + +void rocksdb_delete_with_ts(rocksdb_t* db, + const rocksdb_writeoptions_t* options, + const char* key, size_t keylen, const char* ts, + size_t tslen, char** errptr) { + SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen), + Slice(ts, tslen))); +} + +void rocksdb_delete_cf_with_ts(rocksdb_t* db, + const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, + const char* key, size_t keylen, const char* ts, + size_t tslen, char** errptr) { + SaveError(errptr, db->rep->Delete(options->rep, column_family->rep, + Slice(key, keylen), Slice(ts, tslen))); +} + +void rocksdb_singledelete(rocksdb_t* db, const rocksdb_writeoptions_t* options, + const char* key, size_t keylen, char** errptr) { + SaveError(errptr, db->rep->SingleDelete(options->rep, Slice(key, keylen))); +} + +void rocksdb_singledelete_cf(rocksdb_t* db, + const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, + const char* key, size_t keylen, char** errptr) { + SaveError(errptr, db->rep->SingleDelete(options->rep, column_family->rep, + Slice(key, keylen))); +} + +void rocksdb_singledelete_with_ts(rocksdb_t* db, + const rocksdb_writeoptions_t* options, + const char* key, size_t keylen, + const char* ts, size_t tslen, char** errptr) { + SaveError(errptr, db->rep->SingleDelete(options->rep, Slice(key, keylen), + Slice(ts, tslen))); +} + +void rocksdb_singledelete_cf_with_ts( + rocksdb_t* db, const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, const char* key, + size_t keylen, const char* ts, size_t tslen, char** errptr) { + SaveError(errptr, + db->rep->SingleDelete(options->rep, column_family->rep, + Slice(key, keylen), Slice(ts, tslen))); +} + +void rocksdb_increase_full_history_ts_low( + rocksdb_t* db, rocksdb_column_family_handle_t* column_family, + const char* ts_low, size_t ts_lowlen, char** errptr) { + std::string ts(ts_low, ts_lowlen); + SaveError(errptr, db->rep->IncreaseFullHistoryTsLow(column_family->rep, ts)); +} + +char* rocksdb_get_full_history_ts_low( + rocksdb_t* db, rocksdb_column_family_handle_t* column_family, + size_t* ts_len, char** errptr) { + char* result = nullptr; + std::string tmp; + Status s = db->rep->GetFullHistoryTsLow(column_family->rep, &tmp); + if (s.ok()) { + *ts_len = tmp.size(); + result = CopyString(tmp); + } else { + *ts_len = 0; + SaveError(errptr, s); + } + return result; } void rocksdb_delete_range_cf(rocksdb_t* db, @@ -1026,23 +1177,17 @@ void rocksdb_delete_range_cf(rocksdb_t* db, Slice(end_key, end_key_len))); } -void rocksdb_merge( - rocksdb_t* db, - const rocksdb_writeoptions_t* options, - const char* key, size_t keylen, - const char* val, size_t vallen, - char** errptr) { - SaveError(errptr, - db->rep->Merge(options->rep, Slice(key, keylen), Slice(val, vallen))); +void rocksdb_merge(rocksdb_t* db, const rocksdb_writeoptions_t* options, + const char* key, size_t keylen, const char* val, + size_t vallen, char** errptr) { + SaveError(errptr, db->rep->Merge(options->rep, Slice(key, keylen), + Slice(val, vallen))); } -void rocksdb_merge_cf( - rocksdb_t* db, - const rocksdb_writeoptions_t* options, - rocksdb_column_family_handle_t* column_family, - const char* key, size_t keylen, - const char* val, size_t vallen, - char** errptr) { +void rocksdb_merge_cf(rocksdb_t* db, const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, + const char* key, size_t keylen, const char* val, + size_t vallen, char** errptr) { SaveError(errptr, db->rep->Merge(options->rep, column_family->rep, Slice(key, keylen), Slice(val, vallen))); @@ -1100,13 +1245,57 @@ char* rocksdb_get_cf( return result; } -void rocksdb_multi_get( - rocksdb_t* db, - const rocksdb_readoptions_t* options, - size_t num_keys, const char* const* keys_list, - const size_t* keys_list_sizes, - char** values_list, size_t* values_list_sizes, - char** errs) { +char* rocksdb_get_with_ts(rocksdb_t* db, const rocksdb_readoptions_t* options, + const char* key, size_t keylen, size_t* vallen, + char** ts, size_t* tslen, char** errptr) { + char* result = nullptr; + std::string tmp_val; + std::string tmp_ts; + Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp_val, &tmp_ts); + if (s.ok()) { + *vallen = tmp_val.size(); + result = CopyString(tmp_val); + *tslen = tmp_ts.size(); + *ts = CopyString(tmp_ts); + } else { + *vallen = 0; + *tslen = 0; + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + } + return result; +} + +char* rocksdb_get_cf_with_ts(rocksdb_t* db, + const rocksdb_readoptions_t* options, + rocksdb_column_family_handle_t* column_family, + const char* key, size_t keylen, size_t* vallen, + char** ts, size_t* tslen, char** errptr) { + char* result = nullptr; + std::string tmp; + std::string tmp_ts; + Status s = db->rep->Get(options->rep, column_family->rep, Slice(key, keylen), + &tmp, &tmp_ts); + if (s.ok()) { + *vallen = tmp.size(); + result = CopyString(tmp); + *tslen = tmp_ts.size(); + *ts = CopyString(tmp_ts); + } else { + *vallen = 0; + *tslen = 0; + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + } + return result; +} + +void rocksdb_multi_get(rocksdb_t* db, const rocksdb_readoptions_t* options, + size_t num_keys, const char* const* keys_list, + const size_t* keys_list_sizes, char** values_list, + size_t* values_list_sizes, char** errs) { std::vector keys(num_keys); for (size_t i = 0; i < num_keys; i++) { keys[i] = Slice(keys_list[i], keys_list_sizes[i]); @@ -1130,14 +1319,81 @@ void rocksdb_multi_get( } } +void rocksdb_multi_get_with_ts(rocksdb_t* db, + const rocksdb_readoptions_t* options, + size_t num_keys, const char* const* keys_list, + const size_t* keys_list_sizes, + char** values_list, size_t* values_list_sizes, + char** timestamp_list, + size_t* timestamp_list_sizes, char** errs) { + std::vector keys(num_keys); + for (size_t i = 0; i < num_keys; i++) { + keys[i] = Slice(keys_list[i], keys_list_sizes[i]); + } + std::vector values(num_keys); + std::vector timestamps(num_keys); + std::vector statuses = + db->rep->MultiGet(options->rep, keys, &values, ×tamps); + for (size_t i = 0; i < num_keys; i++) { + if (statuses[i].ok()) { + values_list[i] = CopyString(values[i]); + values_list_sizes[i] = values[i].size(); + timestamp_list[i] = CopyString(timestamps[i]); + timestamp_list_sizes[i] = timestamps[i].size(); + errs[i] = nullptr; + } else { + values_list[i] = nullptr; + values_list_sizes[i] = 0; + timestamp_list[i] = nullptr; + timestamp_list_sizes[i] = 0; + if (!statuses[i].IsNotFound()) { + errs[i] = strdup(statuses[i].ToString().c_str()); + } else { + errs[i] = nullptr; + } + } + } +} + void rocksdb_multi_get_cf( - rocksdb_t* db, - const rocksdb_readoptions_t* options, + rocksdb_t* db, const rocksdb_readoptions_t* options, const rocksdb_column_family_handle_t* const* column_families, size_t num_keys, const char* const* keys_list, - const size_t* keys_list_sizes, - char** values_list, size_t* values_list_sizes, - char** errs) { + const size_t* keys_list_sizes, char** values_list, + size_t* values_list_sizes, char** errs) { + std::vector keys(num_keys); + std::vector cfs(num_keys); + for (size_t i = 0; i < num_keys; i++) { + keys[i] = Slice(keys_list[i], keys_list_sizes[i]); + cfs[i] = column_families[i]->rep; + } + std::vector values(num_keys); + std::vector statuses = + db->rep->MultiGet(options->rep, cfs, keys, &values); + for (size_t i = 0; i < num_keys; i++) { + if (statuses[i].ok()) { + values_list[i] = CopyString(values[i]); + values_list_sizes[i] = values[i].size(); + errs[i] = nullptr; + } else { + values_list[i] = nullptr; + values_list_sizes[i] = 0; + if (!statuses[i].IsNotFound()) { + errs[i] = strdup(statuses[i].ToString().c_str()); + } else { + errs[i] = nullptr; + } + } + } +} + +void rocksdb_multi_get_cf_with_ts( + rocksdb_t* db, const rocksdb_readoptions_t* options, + const rocksdb_column_family_handle_t* const* column_families, + size_t num_keys, const char* const* keys_list, + const size_t* keys_list_sizes, char** values_list, + size_t* values_list_sizes, char** timestamps_list, + size_t* timestamps_list_sizes, char** errs) { std::vector keys(num_keys); std::vector cfs(num_keys); for (size_t i = 0; i < num_keys; i++) { @@ -1145,15 +1401,21 @@ void rocksdb_multi_get_cf( cfs[i] = column_families[i]->rep; } std::vector values(num_keys); - std::vector statuses = db->rep->MultiGet(options->rep, cfs, keys, &values); + std::vector timestamps(num_keys); + std::vector statuses = + db->rep->MultiGet(options->rep, cfs, keys, &values, ×tamps); for (size_t i = 0; i < num_keys; i++) { if (statuses[i].ok()) { values_list[i] = CopyString(values[i]); values_list_sizes[i] = values[i].size(); + timestamps_list[i] = CopyString(timestamps[i]); + timestamps_list_sizes[i] = timestamps[i].size(); errs[i] = nullptr; } else { values_list[i] = nullptr; values_list_sizes[i] = 0; + timestamps_list[i] = nullptr; + timestamps_list_sizes[i] = 0; if (!statuses[i].IsNotFound()) { errs[i] = strdup(statuses[i].ToString().c_str()); } else { @@ -1591,6 +1853,13 @@ const char* rocksdb_iter_value(const rocksdb_iterator_t* iter, size_t* vlen) { return s.data(); } +const char* rocksdb_iter_timestamp(const rocksdb_iterator_t* iter, + size_t* tslen) { + Slice s = iter->rep->timestamp(); + *tslen = s.size(); + return s.data(); +} + void rocksdb_iter_get_error(const rocksdb_iterator_t* iter, char** errptr) { SaveError(errptr, iter->rep->status()); } @@ -1606,39 +1875,37 @@ rocksdb_writebatch_t* rocksdb_writebatch_create_from(const char* rep, return b; } -void rocksdb_writebatch_destroy(rocksdb_writebatch_t* b) { - delete b; -} +void rocksdb_writebatch_destroy(rocksdb_writebatch_t* b) { delete b; } -void rocksdb_writebatch_clear(rocksdb_writebatch_t* b) { - b->rep.Clear(); -} +void rocksdb_writebatch_clear(rocksdb_writebatch_t* b) { b->rep.Clear(); } -int rocksdb_writebatch_count(rocksdb_writebatch_t* b) { - return b->rep.Count(); -} +int rocksdb_writebatch_count(rocksdb_writebatch_t* b) { return b->rep.Count(); } -void rocksdb_writebatch_put( - rocksdb_writebatch_t* b, - const char* key, size_t klen, - const char* val, size_t vlen) { +void rocksdb_writebatch_put(rocksdb_writebatch_t* b, const char* key, + size_t klen, const char* val, size_t vlen) { b->rep.Put(Slice(key, klen), Slice(val, vlen)); } -void rocksdb_writebatch_put_cf( - rocksdb_writebatch_t* b, - rocksdb_column_family_handle_t* column_family, - const char* key, size_t klen, - const char* val, size_t vlen) { +void rocksdb_writebatch_put_cf(rocksdb_writebatch_t* b, + rocksdb_column_family_handle_t* column_family, + const char* key, size_t klen, const char* val, + size_t vlen) { b->rep.Put(column_family->rep, Slice(key, klen), Slice(val, vlen)); } -void rocksdb_writebatch_putv( - rocksdb_writebatch_t* b, - int num_keys, const char* const* keys_list, - const size_t* keys_list_sizes, - int num_values, const char* const* values_list, - const size_t* values_list_sizes) { +void rocksdb_writebatch_put_cf_with_ts( + rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family, + const char* key, size_t klen, const char* ts, size_t tslen, const char* val, + size_t vlen) { + b->rep.Put(column_family->rep, Slice(key, klen), Slice(ts, tslen), + Slice(val, vlen)); +} + +void rocksdb_writebatch_putv(rocksdb_writebatch_t* b, int num_keys, + const char* const* keys_list, + const size_t* keys_list_sizes, int num_values, + const char* const* values_list, + const size_t* values_list_sizes) { std::vector key_slices(num_keys); for (int i = 0; i < num_keys; i++) { key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]); @@ -1651,13 +1918,12 @@ void rocksdb_writebatch_putv( SliceParts(value_slices.data(), num_values)); } -void rocksdb_writebatch_putv_cf( - rocksdb_writebatch_t* b, - rocksdb_column_family_handle_t* column_family, - int num_keys, const char* const* keys_list, - const size_t* keys_list_sizes, - int num_values, const char* const* values_list, - const size_t* values_list_sizes) { +void rocksdb_writebatch_putv_cf(rocksdb_writebatch_t* b, + rocksdb_column_family_handle_t* column_family, + int num_keys, const char* const* keys_list, + const size_t* keys_list_sizes, int num_values, + const char* const* values_list, + const size_t* values_list_sizes) { std::vector key_slices(num_keys); for (int i = 0; i < num_keys; i++) { key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]); @@ -1670,10 +1936,8 @@ void rocksdb_writebatch_putv_cf( SliceParts(value_slices.data(), num_values)); } -void rocksdb_writebatch_merge( - rocksdb_writebatch_t* b, - const char* key, size_t klen, - const char* val, size_t vlen) { +void rocksdb_writebatch_merge(rocksdb_writebatch_t* b, const char* key, + size_t klen, const char* val, size_t vlen) { b->rep.Merge(Slice(key, klen), Slice(val, vlen)); } @@ -1740,16 +2004,27 @@ void rocksdb_writebatch_delete_cf( b->rep.Delete(column_family->rep, Slice(key, klen)); } +void rocksdb_writebatch_delete_cf_with_ts( + rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family, + const char* key, size_t klen, const char* ts, size_t tslen) { + b->rep.Delete(column_family->rep, Slice(key, klen), Slice(ts, tslen)); +} + void rocksdb_writebatch_singledelete_cf( rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family, const char* key, size_t klen) { b->rep.SingleDelete(column_family->rep, Slice(key, klen)); } -void rocksdb_writebatch_deletev( - rocksdb_writebatch_t* b, - int num_keys, const char* const* keys_list, - const size_t* keys_list_sizes) { +void rocksdb_writebatch_singledelete_cf_with_ts( + rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family, + const char* key, size_t klen, const char* ts, size_t tslen) { + b->rep.SingleDelete(column_family->rep, Slice(key, klen), Slice(ts, tslen)); +} + +void rocksdb_writebatch_deletev(rocksdb_writebatch_t* b, int num_keys, + const char* const* keys_list, + const size_t* keys_list_sizes) { std::vector key_slices(num_keys); for (int i = 0; i < num_keys; i++) { key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]); @@ -1758,10 +2033,8 @@ void rocksdb_writebatch_deletev( } void rocksdb_writebatch_deletev_cf( - rocksdb_writebatch_t* b, - rocksdb_column_family_handle_t* column_family, - int num_keys, const char* const* keys_list, - const size_t* keys_list_sizes) { + rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family, + int num_keys, const char* const* keys_list, const size_t* keys_list_sizes) { std::vector key_slices(num_keys); for (int i = 0; i < num_keys; i++) { key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]); @@ -3795,11 +4068,31 @@ rocksdb_comparator_t* rocksdb_comparator_create( result->destructor_ = destructor; result->compare_ = compare; result->name_ = name; + result->compare_ts_ = nullptr; + result->compare_without_ts_ = nullptr; return result; } -void rocksdb_comparator_destroy(rocksdb_comparator_t* cmp) { - delete cmp; +void rocksdb_comparator_destroy(rocksdb_comparator_t* cmp) { delete cmp; } + +rocksdb_comparator_t* rocksdb_comparator_with_ts_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + int (*compare_ts)(void*, const char* a_ts, size_t a_tslen, const char* b_ts, + size_t b_tslen), + int (*compare_without_ts)(void*, const char* a, size_t alen, + unsigned char a_has_ts, const char* b, + size_t blen, unsigned char b_has_ts), + const char* (*name)(void*), size_t timestamp_size) { + rocksdb_comparator_t* result = new rocksdb_comparator_t(timestamp_size); + result->state_ = state; + result->destructor_ = destructor; + result->compare_ = compare; + result->compare_ts_ = compare_ts; + result->compare_without_ts_ = compare_without_ts; + result->name_ = name; + return result; } void rocksdb_filterpolicy_destroy(rocksdb_filterpolicy_t* filter) { @@ -4087,6 +4380,28 @@ rocksdb_readoptions_get_io_timeout(rocksdb_readoptions_t* opt) { return opt->rep.io_timeout.count(); } +void rocksdb_readoptions_set_timestamp(rocksdb_readoptions_t* opt, + const char* ts, size_t tslen) { + if (ts == nullptr) { + opt->timestamp = Slice(); + opt->rep.timestamp = nullptr; + } else { + opt->timestamp = Slice(ts, tslen); + opt->rep.timestamp = &opt->timestamp; + } +} + +void rocksdb_readoptions_set_iter_start_ts(rocksdb_readoptions_t* opt, + const char* ts, size_t tslen) { + if (ts == nullptr) { + opt->iter_start_ts = Slice(); + opt->rep.iter_start_ts = nullptr; + } else { + opt->iter_start_ts = Slice(ts, tslen); + opt->rep.iter_start_ts = &opt->iter_start_ts; + } +} + rocksdb_writeoptions_t* rocksdb_writeoptions_create() { return new rocksdb_writeoptions_t; } @@ -4104,7 +4419,8 @@ unsigned char rocksdb_writeoptions_get_sync(rocksdb_writeoptions_t* opt) { return opt->rep.sync; } -void rocksdb_writeoptions_disable_WAL(rocksdb_writeoptions_t* opt, int disable) { +void rocksdb_writeoptions_disable_WAL(rocksdb_writeoptions_t* opt, + int disable) { opt->rep.disableWAL = disable; } @@ -4114,8 +4430,7 @@ unsigned char rocksdb_writeoptions_get_disable_WAL( } void rocksdb_writeoptions_set_ignore_missing_column_families( - rocksdb_writeoptions_t* opt, - unsigned char v) { + rocksdb_writeoptions_t* opt, unsigned char v) { opt->rep.ignore_missing_column_families = v; } @@ -4124,9 +4439,8 @@ unsigned char rocksdb_writeoptions_get_ignore_missing_column_families( return opt->rep.ignore_missing_column_families; } -void rocksdb_writeoptions_set_no_slowdown( - rocksdb_writeoptions_t* opt, - unsigned char v) { +void rocksdb_writeoptions_set_no_slowdown(rocksdb_writeoptions_t* opt, + unsigned char v) { opt->rep.no_slowdown = v; } @@ -4135,9 +4449,8 @@ unsigned char rocksdb_writeoptions_get_no_slowdown( return opt->rep.no_slowdown; } -void rocksdb_writeoptions_set_low_pri( - rocksdb_writeoptions_t* opt, - unsigned char v) { +void rocksdb_writeoptions_set_low_pri(rocksdb_writeoptions_t* opt, + unsigned char v) { opt->rep.low_pri = v; } @@ -4202,6 +4515,17 @@ int rocksdb_compactoptions_get_target_level(rocksdb_compactoptions_t* opt) { return opt->rep.target_level; } +void rocksdb_compactoptions_set_full_history_ts_low( + rocksdb_compactoptions_t* opt, char* ts, size_t tslen) { + if (ts == nullptr) { + opt->full_history_ts_low = Slice(); + opt->rep.full_history_ts_low = nullptr; + } else { + opt->full_history_ts_low = Slice(ts, tslen); + opt->rep.full_history_ts_low = &opt->full_history_ts_low; + } +} + rocksdb_flushoptions_t* rocksdb_flushoptions_create() { return new rocksdb_flushoptions_t; } @@ -4423,6 +4747,15 @@ void rocksdb_sstfilewriter_put(rocksdb_sstfilewriter_t* writer, const char* key, SaveError(errptr, writer->rep->Put(Slice(key, keylen), Slice(val, vallen))); } +void rocksdb_sstfilewriter_put_with_ts(rocksdb_sstfilewriter_t* writer, + const char* key, size_t keylen, + const char* ts, size_t tslen, + const char* val, size_t vallen, + char** errptr) { + SaveError(errptr, writer->rep->Put(Slice(key, keylen), Slice(ts, tslen), + Slice(val, vallen))); +} + void rocksdb_sstfilewriter_merge(rocksdb_sstfilewriter_t* writer, const char* key, size_t keylen, const char* val, size_t vallen, @@ -4436,13 +4769,20 @@ void rocksdb_sstfilewriter_delete(rocksdb_sstfilewriter_t* writer, SaveError(errptr, writer->rep->Delete(Slice(key, keylen))); } +void rocksdb_sstfilewriter_delete_with_ts(rocksdb_sstfilewriter_t* writer, + const char* key, size_t keylen, + const char* ts, size_t tslen, + char** errptr) { + SaveError(errptr, writer->rep->Delete(Slice(key, keylen), Slice(ts, tslen))); +} + void rocksdb_sstfilewriter_finish(rocksdb_sstfilewriter_t* writer, char** errptr) { SaveError(errptr, writer->rep->Finish(nullptr)); } void rocksdb_sstfilewriter_file_size(rocksdb_sstfilewriter_t* writer, - uint64_t* file_size) { + uint64_t* file_size) { *file_size = writer->rep->FileSize(); } @@ -4482,8 +4822,7 @@ void rocksdb_ingestexternalfileoptions_set_allow_blocking_flush( } void rocksdb_ingestexternalfileoptions_set_ingest_behind( - rocksdb_ingestexternalfileoptions_t* opt, - unsigned char ingest_behind) { + rocksdb_ingestexternalfileoptions_t* opt, unsigned char ingest_behind) { opt->rep.ingest_behind = ingest_behind; } @@ -5444,6 +5783,16 @@ void rocksdb_transaction_put_cf(rocksdb_transaction_t* txn, Slice(val, vlen))); } +void rocksdb_transaction_set_commit_timestamp(rocksdb_transaction_t* txn, + uint64_t commit_timestamp) { + txn->rep->SetCommitTimestamp(commit_timestamp); +} + +void rocksdb_transaction_set_read_timestamp_for_validation( + rocksdb_transaction_t* txn, uint64_t read_timestamp) { + txn->rep->SetReadTimestampForValidation(read_timestamp); +} + // Put a key outside a transaction void rocksdb_transactiondb_put(rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options, diff --git a/include/rocksdb/c.h b/include/rocksdb/c.h index 5f3691b9d..a1f1b5363 100644 --- a/include/rocksdb/c.h +++ b/include/rocksdb/c.h @@ -211,6 +211,52 @@ extern ROCKSDB_LIBRARY_API void rocksdb_backup_engine_info_destroy( extern ROCKSDB_LIBRARY_API void rocksdb_backup_engine_close( rocksdb_backup_engine_t* be); +extern ROCKSDB_LIBRARY_API void rocksdb_put_with_ts( + rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key, + size_t keylen, const char* ts, size_t tslen, const char* val, size_t vallen, + char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_put_cf_with_ts( + rocksdb_t* db, const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, const char* key, + size_t keylen, const char* ts, size_t tslen, const char* val, size_t vallen, + char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_delete_with_ts( + rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key, + size_t keylen, const char* ts, size_t tslen, char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_delete_cf_with_ts( + rocksdb_t* db, const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, const char* key, + size_t keylen, const char* ts, size_t tslen, char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_singledelete( + rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key, + size_t keylen, char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_cf( + rocksdb_t* db, const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, const char* key, + size_t keylen, char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_with_ts( + rocksdb_t* db, const rocksdb_writeoptions_t* options, const char* key, + size_t keylen, const char* ts, size_t tslen, char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_singledelete_cf_with_ts( + rocksdb_t* db, const rocksdb_writeoptions_t* options, + rocksdb_column_family_handle_t* column_family, const char* key, + size_t keylen, const char* ts, size_t tslen, char** errptr); + +extern ROCKSDB_LIBRARY_API void rocksdb_increase_full_history_ts_low( + rocksdb_t* db, rocksdb_column_family_handle_t* column_family, + const char* ts_low, size_t ts_lowlen, char** errptr); + +extern ROCKSDB_LIBRARY_API char* rocksdb_get_full_history_ts_low( + rocksdb_t* db, rocksdb_column_family_handle_t* column_family, + size_t* ts_lowlen, char** errptr); + /* BackupEngineOptions */ extern ROCKSDB_LIBRARY_API rocksdb_backup_engine_options_t* @@ -315,6 +361,13 @@ extern ROCKSDB_LIBRARY_API void rocksdb_checkpoint_create( extern ROCKSDB_LIBRARY_API void rocksdb_checkpoint_object_destroy( rocksdb_checkpoint_t* checkpoint); +extern ROCKSDB_LIBRARY_API rocksdb_t* rocksdb_open_and_trim_history( + const rocksdb_options_t* options, const char* name, int num_column_families, + const char* const* column_family_names, + const rocksdb_options_t* const* column_family_options, + rocksdb_column_family_handle_t** column_family_handles, char* trim_ts, + size_t trim_tslen, char** errptr); + extern ROCKSDB_LIBRARY_API rocksdb_t* rocksdb_open_column_families( const rocksdb_options_t* options, const char* name, int num_column_families, const char* const* column_family_names, @@ -411,11 +464,20 @@ extern ROCKSDB_LIBRARY_API char* rocksdb_get( rocksdb_t* db, const rocksdb_readoptions_t* options, const char* key, size_t keylen, size_t* vallen, char** errptr); +extern ROCKSDB_LIBRARY_API char* rocksdb_get_with_ts( + rocksdb_t* db, const rocksdb_readoptions_t* options, const char* key, + size_t keylen, size_t* vallen, char** ts, size_t* tslen, char** errptr); + extern ROCKSDB_LIBRARY_API char* rocksdb_get_cf( rocksdb_t* db, const rocksdb_readoptions_t* options, rocksdb_column_family_handle_t* column_family, const char* key, size_t keylen, size_t* vallen, char** errptr); +extern ROCKSDB_LIBRARY_API char* rocksdb_get_cf_with_ts( + rocksdb_t* db, const rocksdb_readoptions_t* options, + rocksdb_column_family_handle_t* column_family, const char* key, + size_t keylen, size_t* vallen, char** ts, size_t* tslen, char** errptr); + // if values_list[i] == NULL and errs[i] == NULL, // then we got status.IsNotFound(), which we will not return. // all errors except status status.ok() and status.IsNotFound() are returned. @@ -432,6 +494,12 @@ extern ROCKSDB_LIBRARY_API void rocksdb_multi_get( const char* const* keys_list, const size_t* keys_list_sizes, char** values_list, size_t* values_list_sizes, char** errs); +extern ROCKSDB_LIBRARY_API void rocksdb_multi_get_with_ts( + rocksdb_t* db, const rocksdb_readoptions_t* options, size_t num_keys, + const char* const* keys_list, const size_t* keys_list_sizes, + char** values_list, size_t* values_list_sizes, char** timestamp_list, + size_t* timestamp_list_sizes, char** errs); + extern ROCKSDB_LIBRARY_API void rocksdb_multi_get_cf( rocksdb_t* db, const rocksdb_readoptions_t* options, const rocksdb_column_family_handle_t* const* column_families, @@ -439,6 +507,14 @@ extern ROCKSDB_LIBRARY_API void rocksdb_multi_get_cf( const size_t* keys_list_sizes, char** values_list, size_t* values_list_sizes, char** errs); +extern ROCKSDB_LIBRARY_API void rocksdb_multi_get_cf_with_ts( + rocksdb_t* db, const rocksdb_readoptions_t* options, + const rocksdb_column_family_handle_t* const* column_families, + size_t num_keys, const char* const* keys_list, + const size_t* keys_list_sizes, char** values_list, + size_t* values_list_sizes, char** timestamps_list, + size_t* timestamps_list_sizes, char** errs); + // The MultiGet API that improves performance by batching operations // in the read path for greater efficiency. Currently, only the block based // table format with full filters are supported. Other table formats such @@ -608,6 +684,8 @@ extern ROCKSDB_LIBRARY_API const char* rocksdb_iter_key( const rocksdb_iterator_t*, size_t* klen); extern ROCKSDB_LIBRARY_API const char* rocksdb_iter_value( const rocksdb_iterator_t*, size_t* vlen); +extern ROCKSDB_LIBRARY_API const char* rocksdb_iter_timestamp( + const rocksdb_iterator_t*, size_t* tslen); extern ROCKSDB_LIBRARY_API void rocksdb_iter_get_error( const rocksdb_iterator_t*, char** errptr); @@ -637,6 +715,10 @@ extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put(rocksdb_writebatch_t*, extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put_cf( rocksdb_writebatch_t*, rocksdb_column_family_handle_t* column_family, const char* key, size_t klen, const char* val, size_t vlen); +extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_put_cf_with_ts( + rocksdb_writebatch_t*, rocksdb_column_family_handle_t* column_family, + const char* key, size_t klen, const char* ts, size_t tslen, const char* val, + size_t vlen); extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_putv( rocksdb_writebatch_t* b, int num_keys, const char* const* keys_list, const size_t* keys_list_sizes, int num_values, @@ -671,9 +753,15 @@ extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_singledelete( extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_delete_cf( rocksdb_writebatch_t*, rocksdb_column_family_handle_t* column_family, const char* key, size_t klen); +extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_delete_cf_with_ts( + rocksdb_writebatch_t*, rocksdb_column_family_handle_t* column_family, + const char* key, size_t klen, const char* ts, size_t tslen); extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_singledelete_cf( rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family, const char* key, size_t klen); +extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_singledelete_cf_with_ts( + rocksdb_writebatch_t* b, rocksdb_column_family_handle_t* column_family, + const char* key, size_t klen, const char* ts, size_t tslen); extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_deletev( rocksdb_writebatch_t* b, int num_keys, const char* const* keys_list, const size_t* keys_list_sizes); @@ -1616,6 +1704,18 @@ extern ROCKSDB_LIBRARY_API rocksdb_comparator_t* rocksdb_comparator_create( extern ROCKSDB_LIBRARY_API void rocksdb_comparator_destroy( rocksdb_comparator_t*); +extern ROCKSDB_LIBRARY_API rocksdb_comparator_t* +rocksdb_comparator_with_ts_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + int (*compare_ts)(void*, const char* a_ts, size_t a_tslen, const char* b_ts, + size_t b_tslen), + int (*compare_without_ts)(void*, const char* a, size_t alen, + unsigned char a_has_ts, const char* b, + size_t blen, unsigned char b_has_ts), + const char* (*name)(void*), size_t timestamp_size); + /* Filter policy */ extern ROCKSDB_LIBRARY_API void rocksdb_filterpolicy_destroy( @@ -1719,6 +1819,10 @@ extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_io_timeout( rocksdb_readoptions_t*, uint64_t microseconds); extern ROCKSDB_LIBRARY_API uint64_t rocksdb_readoptions_get_io_timeout(rocksdb_readoptions_t*); +extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_timestamp( + rocksdb_readoptions_t*, const char* ts, size_t tslen); +extern ROCKSDB_LIBRARY_API void rocksdb_readoptions_set_iter_start_ts( + rocksdb_readoptions_t*, const char* ts, size_t tslen); /* Write options */ @@ -1780,6 +1884,8 @@ extern ROCKSDB_LIBRARY_API void rocksdb_compactoptions_set_target_level( rocksdb_compactoptions_t*, int); extern ROCKSDB_LIBRARY_API int rocksdb_compactoptions_get_target_level( rocksdb_compactoptions_t*); +extern ROCKSDB_LIBRARY_API void rocksdb_compactoptions_set_full_history_ts_low( + rocksdb_compactoptions_t*, char* ts, size_t tslen); /* Flush options */ @@ -1886,12 +1992,19 @@ extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_add( extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_put( rocksdb_sstfilewriter_t* writer, const char* key, size_t keylen, const char* val, size_t vallen, char** errptr); +extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_put_with_ts( + rocksdb_sstfilewriter_t* writer, const char* key, size_t keylen, + const char* ts, size_t tslen, const char* val, size_t vallen, + char** errptr); extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_merge( rocksdb_sstfilewriter_t* writer, const char* key, size_t keylen, const char* val, size_t vallen, char** errptr); extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_delete( rocksdb_sstfilewriter_t* writer, const char* key, size_t keylen, char** errptr); +extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_delete_with_ts( + rocksdb_sstfilewriter_t* writer, const char* key, size_t keylen, + const char* ts, size_t tslen, char** errptr); extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_finish( rocksdb_sstfilewriter_t* writer, char** errptr); extern ROCKSDB_LIBRARY_API void rocksdb_sstfilewriter_file_size( @@ -1917,8 +2030,7 @@ rocksdb_ingestexternalfileoptions_set_allow_blocking_flush( unsigned char allow_blocking_flush); extern ROCKSDB_LIBRARY_API void rocksdb_ingestexternalfileoptions_set_ingest_behind( - rocksdb_ingestexternalfileoptions_t* opt, - unsigned char ingest_behind); + rocksdb_ingestexternalfileoptions_t* opt, unsigned char ingest_behind); extern ROCKSDB_LIBRARY_API void rocksdb_ingestexternalfileoptions_destroy( rocksdb_ingestexternalfileoptions_t* opt); @@ -2123,6 +2235,13 @@ extern ROCKSDB_LIBRARY_API void rocksdb_transaction_rebuild_from_writebatch( extern ROCKSDB_LIBRARY_API void rocksdb_transaction_rebuild_from_writebatch_wi( rocksdb_transaction_t* txn, rocksdb_writebatch_wi_t* wi, char** errptr); +extern ROCKSDB_LIBRARY_API void rocksdb_transaction_set_commit_timestamp( + rocksdb_transaction_t* txn, uint64_t commit_timestamp); + +extern ROCKSDB_LIBRARY_API void +rocksdb_transaction_set_read_timestamp_for_validation( + rocksdb_transaction_t* txn, uint64_t read_timestamp); + // This snapshot should be freed using rocksdb_free extern ROCKSDB_LIBRARY_API const rocksdb_snapshot_t* rocksdb_transaction_get_snapshot(rocksdb_transaction_t* txn);