]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rocksdb/db/c.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / db / c.cc
index e9f520e25c57953aae626084279b66e98dbfdd4f..a7e4360c67a6e20c27f2728cf14609728069d2d1 100644 (file)
 
 #include "rocksdb/c.h"
 
-#include <stdlib.h>
+#include <cstdlib>
+#include <map>
+#include <unordered_set>
+#include <vector>
+
 #include "port/port.h"
 #include "rocksdb/cache.h"
 #include "rocksdb/compaction_filter.h"
 #include "rocksdb/convenience.h"
 #include "rocksdb/db.h"
 #include "rocksdb/env.h"
+#include "rocksdb/experimental.h"
 #include "rocksdb/filter_policy.h"
 #include "rocksdb/iterator.h"
 #include "rocksdb/memtablerep.h"
 #include "rocksdb/merge_operator.h"
 #include "rocksdb/options.h"
+#include "rocksdb/perf_context.h"
 #include "rocksdb/rate_limiter.h"
 #include "rocksdb/slice_transform.h"
 #include "rocksdb/statistics.h"
 #include "rocksdb/status.h"
 #include "rocksdb/table.h"
 #include "rocksdb/universal_compaction.h"
-#include "rocksdb/utilities/backupable_db.h"
+#include "rocksdb/utilities/backup_engine.h"
 #include "rocksdb/utilities/checkpoint.h"
 #include "rocksdb/utilities/db_ttl.h"
 #include "rocksdb/utilities/memory_util.h"
 #include "rocksdb/utilities/optimistic_transaction_db.h"
+#include "rocksdb/utilities/options_util.h"
+#include "rocksdb/utilities/table_properties_collectors.h"
 #include "rocksdb/utilities/transaction.h"
 #include "rocksdb/utilities/transaction_db.h"
 #include "rocksdb/utilities/write_batch_with_index.h"
 #include "rocksdb/write_batch.h"
-#include "rocksdb/perf_context.h"
 #include "utilities/merge_operators.h"
 
-#include <vector>
-#include <unordered_set>
-#include <map>
-
-using ROCKSDB_NAMESPACE::BackupableDBOptions;
 using ROCKSDB_NAMESPACE::BackupEngine;
+using ROCKSDB_NAMESPACE::BackupEngineOptions;
 using ROCKSDB_NAMESPACE::BackupID;
 using ROCKSDB_NAMESPACE::BackupInfo;
 using ROCKSDB_NAMESPACE::BatchResult;
@@ -58,6 +61,7 @@ using ROCKSDB_NAMESPACE::Cache;
 using ROCKSDB_NAMESPACE::Checkpoint;
 using ROCKSDB_NAMESPACE::ColumnFamilyDescriptor;
 using ROCKSDB_NAMESPACE::ColumnFamilyHandle;
+using ROCKSDB_NAMESPACE::ColumnFamilyMetaData;
 using ROCKSDB_NAMESPACE::ColumnFamilyOptions;
 using ROCKSDB_NAMESPACE::CompactionFilter;
 using ROCKSDB_NAMESPACE::CompactionFilterFactory;
@@ -77,19 +81,25 @@ using ROCKSDB_NAMESPACE::FlushOptions;
 using ROCKSDB_NAMESPACE::InfoLogLevel;
 using ROCKSDB_NAMESPACE::IngestExternalFileOptions;
 using ROCKSDB_NAMESPACE::Iterator;
+using ROCKSDB_NAMESPACE::LevelMetaData;
 using ROCKSDB_NAMESPACE::LiveFileMetaData;
 using ROCKSDB_NAMESPACE::Logger;
+using ROCKSDB_NAMESPACE::LRUCacheOptions;
+using ROCKSDB_NAMESPACE::MemoryAllocator;
 using ROCKSDB_NAMESPACE::MemoryUtil;
 using ROCKSDB_NAMESPACE::MergeOperator;
 using ROCKSDB_NAMESPACE::NewBloomFilterPolicy;
+using ROCKSDB_NAMESPACE::NewCompactOnDeletionCollectorFactory;
 using ROCKSDB_NAMESPACE::NewGenericRateLimiter;
 using ROCKSDB_NAMESPACE::NewLRUCache;
+using ROCKSDB_NAMESPACE::NewRibbonFilterPolicy;
 using ROCKSDB_NAMESPACE::OptimisticTransactionDB;
 using ROCKSDB_NAMESPACE::OptimisticTransactionOptions;
 using ROCKSDB_NAMESPACE::Options;
 using ROCKSDB_NAMESPACE::PerfContext;
 using ROCKSDB_NAMESPACE::PerfLevel;
 using ROCKSDB_NAMESPACE::PinnableSlice;
+using ROCKSDB_NAMESPACE::PrepopulateBlobCache;
 using ROCKSDB_NAMESPACE::RandomAccessFile;
 using ROCKSDB_NAMESPACE::Range;
 using ROCKSDB_NAMESPACE::RateLimiter;
@@ -100,8 +110,10 @@ using ROCKSDB_NAMESPACE::Slice;
 using ROCKSDB_NAMESPACE::SliceParts;
 using ROCKSDB_NAMESPACE::SliceTransform;
 using ROCKSDB_NAMESPACE::Snapshot;
+using ROCKSDB_NAMESPACE::SstFileMetaData;
 using ROCKSDB_NAMESPACE::SstFileWriter;
 using ROCKSDB_NAMESPACE::Status;
+using ROCKSDB_NAMESPACE::TablePropertiesCollectorFactory;
 using ROCKSDB_NAMESPACE::Transaction;
 using ROCKSDB_NAMESPACE::TransactionDB;
 using ROCKSDB_NAMESPACE::TransactionDBOptions;
@@ -113,55 +125,125 @@ using ROCKSDB_NAMESPACE::WriteBatch;
 using ROCKSDB_NAMESPACE::WriteBatchWithIndex;
 using ROCKSDB_NAMESPACE::WriteOptions;
 
-using std::vector;
 using std::unordered_set;
+using std::vector;
 
 extern "C" {
 
-struct rocksdb_t                 { DB*               rep; };
-struct rocksdb_backup_engine_t   { BackupEngine*     rep; };
-struct rocksdb_backup_engine_info_t { std::vector<BackupInfo> rep; };
-struct rocksdb_restore_options_t { RestoreOptions rep; };
-struct rocksdb_iterator_t        { Iterator*         rep; };
-struct rocksdb_writebatch_t      { WriteBatch        rep; };
-struct rocksdb_writebatch_wi_t   { WriteBatchWithIndex* rep; };
-struct rocksdb_snapshot_t        { const Snapshot*   rep; };
-struct rocksdb_flushoptions_t    { FlushOptions      rep; };
-struct rocksdb_fifo_compaction_options_t { CompactionOptionsFIFO rep; };
+struct rocksdb_t {
+  DB* rep;
+};
+struct rocksdb_backup_engine_t {
+  BackupEngine* rep;
+};
+struct rocksdb_backup_engine_info_t {
+  std::vector<BackupInfo> rep;
+};
+struct rocksdb_restore_options_t {
+  RestoreOptions rep;
+};
+struct rocksdb_iterator_t {
+  Iterator* rep;
+};
+struct rocksdb_writebatch_t {
+  WriteBatch rep;
+};
+struct rocksdb_writebatch_wi_t {
+  WriteBatchWithIndex* rep;
+};
+struct rocksdb_snapshot_t {
+  const Snapshot* rep;
+};
+struct rocksdb_flushoptions_t {
+  FlushOptions rep;
+};
+struct rocksdb_fifo_compaction_options_t {
+  CompactionOptionsFIFO rep;
+};
 struct rocksdb_readoptions_t {
-   ReadOptions rep;
-   // stack variables to set pointers to in ReadOptions
-   Slice upper_bound;
-   Slice lower_bound;
+  ReadOptions rep;
+  // 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_seqfile_t {
+  SequentialFile* rep;
+};
+struct rocksdb_randomfile_t {
+  RandomAccessFile* rep;
+};
+struct rocksdb_writablefile_t {
+  WritableFile* rep;
+};
+struct rocksdb_wal_iterator_t {
+  TransactionLogIterator* rep;
+};
+struct rocksdb_wal_readoptions_t {
+  TransactionLogIterator::ReadOptions rep;
+};
+struct rocksdb_filelock_t {
+  FileLock* 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; };
-struct rocksdb_wal_iterator_t { TransactionLogIterator* rep; };
-struct rocksdb_wal_readoptions_t { TransactionLogIterator::ReadOptions rep; };
-struct rocksdb_filelock_t        { FileLock*         rep; };
 struct rocksdb_logger_t {
   std::shared_ptr<Logger> rep;
 };
+struct rocksdb_lru_cache_options_t {
+  LRUCacheOptions rep;
+};
+struct rocksdb_memory_allocator_t {
+  std::shared_ptr<MemoryAllocator> rep;
+};
 struct rocksdb_cache_t {
   std::shared_ptr<Cache> rep;
 };
-struct rocksdb_livefiles_t       { std::vector<LiveFileMetaData> rep; };
-struct rocksdb_column_family_handle_t  { ColumnFamilyHandle* rep; };
-struct rocksdb_envoptions_t      { EnvOptions        rep; };
-struct rocksdb_ingestexternalfileoptions_t  { IngestExternalFileOptions rep; };
-struct rocksdb_sstfilewriter_t   { SstFileWriter*    rep; };
+struct rocksdb_livefiles_t {
+  std::vector<LiveFileMetaData> rep;
+};
+struct rocksdb_column_family_handle_t {
+  ColumnFamilyHandle* rep;
+};
+struct rocksdb_column_family_metadata_t {
+  ColumnFamilyMetaData rep;
+};
+struct rocksdb_level_metadata_t {
+  const LevelMetaData* rep;
+};
+struct rocksdb_sst_file_metadata_t {
+  const SstFileMetaData* rep;
+};
+struct rocksdb_envoptions_t {
+  EnvOptions rep;
+};
+struct rocksdb_ingestexternalfileoptions_t {
+  IngestExternalFileOptions rep;
+};
+struct rocksdb_sstfilewriter_t {
+  SstFileWriter* rep;
+};
 struct rocksdb_ratelimiter_t {
   std::shared_ptr<RateLimiter> rep;
 };
-struct rocksdb_perfcontext_t     { PerfContext*      rep; };
+struct rocksdb_perfcontext_t {
+  PerfContext* rep;
+};
 struct rocksdb_pinnableslice_t {
   PinnableSlice rep;
 };
@@ -177,8 +259,8 @@ struct rocksdb_transaction_options_t {
 struct rocksdb_transaction_t {
   Transaction* rep;
 };
-struct rocksdb_backupable_db_options_t {
-  BackupableDBOptions rep;
+struct rocksdb_backup_engine_options_t {
+  BackupEngineOptions rep;
 };
 struct rocksdb_checkpoint_t {
   Checkpoint* rep;
@@ -197,13 +279,10 @@ struct rocksdb_compactionfiltercontext_t {
 struct rocksdb_compactionfilter_t : public CompactionFilter {
   void* state_;
   void (*destructor_)(void*);
-  unsigned char (*filter_)(
-      void*,
-      int level,
-      const char* key, size_t key_length,
-      const char* existing_value, size_t value_length,
-      char** new_value, size_t *new_value_length,
-      unsigned char* value_changed);
+  unsigned char (*filter_)(void*, int level, const char* key, size_t key_length,
+                           const char* existing_value, size_t value_length,
+                           char** new_value, size_t* new_value_length,
+                           unsigned char* value_changed);
   const char* (*name_)(void*);
   unsigned char ignore_snapshots_;
 
@@ -214,12 +293,10 @@ struct rocksdb_compactionfilter_t : public CompactionFilter {
     char* c_new_value = nullptr;
     size_t new_value_length = 0;
     unsigned char c_value_changed = 0;
-    unsigned char result = (*filter_)(
-        state_,
-        level,
-        key.data(), key.size(),
-        existing_value.data(), existing_value.size(),
-        &c_new_value, &new_value_length, &c_value_changed);
+    unsigned char result =
+        (*filter_)(state_, level, key.data(), key.size(), existing_value.data(),
+                   existing_value.size(), &c_new_value, &new_value_length,
+                   &c_value_changed);
     if (c_value_changed) {
       new_value->assign(c_new_value, new_value_length);
       *value_changed = true;
@@ -255,11 +332,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_); }
 
@@ -267,6 +351,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.
@@ -278,65 +379,26 @@ struct rocksdb_filterpolicy_t : public FilterPolicy {
   void* state_;
   void (*destructor_)(void*);
   const char* (*name_)(void*);
-  char* (*create_)(
-      void*,
-      const char* const* key_array, const size_t* key_length_array,
-      int num_keys,
-      size_t* filter_length);
-  unsigned char (*key_match_)(
-      void*,
-      const char* key, size_t length,
-      const char* filter, size_t filter_length);
-  void (*delete_filter_)(
-      void*,
-      const char* filter, size_t filter_length);
 
   ~rocksdb_filterpolicy_t() override { (*destructor_)(state_); }
 
   const char* Name() const override { return (*name_)(state_); }
-
-  void CreateFilter(const Slice* keys, int n, std::string* dst) const override {
-    std::vector<const char*> key_pointers(n);
-    std::vector<size_t> key_sizes(n);
-    for (int i = 0; i < n; i++) {
-      key_pointers[i] = keys[i].data();
-      key_sizes[i] = keys[i].size();
-    }
-    size_t len;
-    char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len);
-    dst->append(filter, len);
-
-    if (delete_filter_ != nullptr) {
-      (*delete_filter_)(state_, filter, len);
-    } else {
-      free(filter);
-    }
-  }
-
-  bool KeyMayMatch(const Slice& key, const Slice& filter) const override {
-    return (*key_match_)(state_, key.data(), key.size(),
-                         filter.data(), filter.size());
-  }
 };
 
 struct rocksdb_mergeoperator_t : public MergeOperator {
   void* state_;
   void (*destructor_)(void*);
   const char* (*name_)(void*);
-  char* (*full_merge_)(
-      void*,
-      const char* key, size_t key_length,
-      const char* existing_value, size_t existing_value_length,
-      const char* const* operands_list, const size_t* operands_list_length,
-      int num_operands,
-      unsigned char* success, size_t* new_value_length);
+  char* (*full_merge_)(void*, const char* key, size_t key_length,
+                       const char* existing_value, size_t existing_value_length,
+                       const char* const* operands_list,
+                       const size_t* operands_list_length, int num_operands,
+                       unsigned char* success, size_t* new_value_length);
   char* (*partial_merge_)(void*, const char* key, size_t key_length,
                           const char* const* operands_list,
                           const size_t* operands_list_length, int num_operands,
                           unsigned char* success, size_t* new_value_length);
-  void (*delete_value_)(
-      void*,
-      const char* value, size_t value_length);
+  void (*delete_value_)(void*, const char* value, size_t value_length);
 
   ~rocksdb_mergeoperator_t() override { (*destructor_)(state_); }
 
@@ -420,16 +482,10 @@ struct rocksdb_slicetransform_t : public SliceTransform {
   void* state_;
   void (*destructor_)(void*);
   const char* (*name_)(void*);
-  char* (*transform_)(
-      void*,
-      const char* key, size_t length,
-      size_t* dst_length);
-  unsigned char (*in_domain_)(
-      void*,
-      const char* key, size_t length);
-  unsigned char (*in_range_)(
-      void*,
-      const char* key, size_t length);
+  char* (*transform_)(void*, const char* key, size_t length,
+                      size_t* dst_length);
+  unsigned char (*in_domain_)(void*, const char* key, size_t length);
+  unsigned char (*in_range_)(void*, const char* key, size_t length);
 
   ~rocksdb_slicetransform_t() override { (*destructor_)(state_); }
 
@@ -475,10 +531,8 @@ static char* CopyString(const std::string& str) {
   return result;
 }
 
-rocksdb_t* rocksdb_open(
-    const rocksdb_options_t* options,
-    const char* name,
-    char** errptr) {
+rocksdb_t* rocksdb_open(const rocksdb_options_t* options, const char* name,
+                        char** errptr) {
   DB* db;
   if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) {
     return nullptr;
@@ -488,11 +542,8 @@ rocksdb_t* rocksdb_open(
   return result;
 }
 
-rocksdb_t* rocksdb_open_with_ttl(
-    const rocksdb_options_t* options,
-    const char* name,
-    int ttl,
-    char** errptr) {
+rocksdb_t* rocksdb_open_with_ttl(const rocksdb_options_t* options,
+                                 const char* name, int ttl, char** errptr) {
   ROCKSDB_NAMESPACE::DBWithTTL* db;
   if (SaveError(errptr, ROCKSDB_NAMESPACE::DBWithTTL::Open(
                             options->rep, std::string(name), &db, ttl))) {
@@ -535,12 +586,11 @@ rocksdb_t* rocksdb_open_as_secondary(const rocksdb_options_t* options,
 rocksdb_backup_engine_t* rocksdb_backup_engine_open(
     const rocksdb_options_t* options, const char* path, char** errptr) {
   BackupEngine* be;
-  if (SaveError(errptr, BackupEngine::Open(options->rep.env,
-                                           BackupableDBOptions(path,
-                                                               nullptr,
-                                                               true,
-                                                               options->rep.info_log.get()),
-                                           &be))) {
+  if (SaveError(errptr, BackupEngine::Open(
+                            options->rep.env,
+                            BackupEngineOptions(path, nullptr, true,
+                                                options->rep.info_log.get()),
+                            &be))) {
     return nullptr;
   }
   rocksdb_backup_engine_t* result = new rocksdb_backup_engine_t;
@@ -549,7 +599,7 @@ rocksdb_backup_engine_t* rocksdb_backup_engine_open(
 }
 
 rocksdb_backup_engine_t* rocksdb_backup_engine_open_opts(
-    const rocksdb_backupable_db_options_t* options, rocksdb_env_t* env,
+    const rocksdb_backup_engine_options_t* options, rocksdb_env_t* env,
     char** errptr) {
   BackupEngine* be;
   if (SaveError(errptr, BackupEngine::Open(options->rep, env->rep, &be))) {
@@ -561,15 +611,13 @@ rocksdb_backup_engine_t* rocksdb_backup_engine_open_opts(
 }
 
 void rocksdb_backup_engine_create_new_backup(rocksdb_backup_engine_t* be,
-                                             rocksdb_t* db,
-                                             char** errptr) {
+                                             rocksdb_t* db, char** errptr) {
   SaveError(errptr, be->rep->CreateNewBackup(db->rep));
 }
 
-void rocksdb_backup_engine_create_new_backup_flush(rocksdb_backup_engine_t* be,
-                                                   rocksdb_t* db,
-                                                   unsigned char flush_before_backup,
-                                                   char** errptr) {
+void rocksdb_backup_engine_create_new_backup_flush(
+    rocksdb_backup_engine_t* be, rocksdb_t* db,
+    unsigned char flush_before_backup, char** errptr) {
   SaveError(errptr, be->rep->CreateNewBackup(db->rep, flush_before_backup));
 }
 
@@ -592,9 +640,8 @@ void rocksdb_restore_options_set_keep_log_files(rocksdb_restore_options_t* opt,
   opt->rep.keep_log_files = v;
 }
 
-
 void rocksdb_backup_engine_verify_backup(rocksdb_backup_engine_t* be,
-    uint32_t backup_id, char** errptr) {
+                                         uint32_t backup_id, char** errptr) {
   SaveError(errptr, be->rep->VerifyBackup(static_cast<BackupID>(backup_id)));
 }
 
@@ -656,125 +703,125 @@ void rocksdb_backup_engine_close(rocksdb_backup_engine_t* be) {
   delete be;
 }
 
-rocksdb_backupable_db_options_t* rocksdb_backupable_db_options_create(
+rocksdb_backup_engine_options_t* rocksdb_backup_engine_options_create(
     const char* backup_dir) {
-  return new rocksdb_backupable_db_options_t{
-      BackupableDBOptions(std::string(backup_dir))};
+  return new rocksdb_backup_engine_options_t{
+      BackupEngineOptions(std::string(backup_dir))};
 }
 
-void rocksdb_backupable_db_options_set_backup_dir(
-    rocksdb_backupable_db_options_t* options, const char* backup_dir) {
+void rocksdb_backup_engine_options_set_backup_dir(
+    rocksdb_backup_engine_options_t* options, const char* backup_dir) {
   options->rep.backup_dir = std::string(backup_dir);
 }
 
-void rocksdb_backupable_db_options_set_env(
-    rocksdb_backupable_db_options_t* options, rocksdb_env_t* env) {
+void rocksdb_backup_engine_options_set_env(
+    rocksdb_backup_engine_options_t* options, rocksdb_env_t* env) {
   options->rep.backup_env = (env ? env->rep : nullptr);
 }
 
-void rocksdb_backupable_db_options_set_share_table_files(
-    rocksdb_backupable_db_options_t* options, unsigned char val) {
+void rocksdb_backup_engine_options_set_share_table_files(
+    rocksdb_backup_engine_options_t* options, unsigned char val) {
   options->rep.share_table_files = val;
 }
 
-unsigned char rocksdb_backupable_db_options_get_share_table_files(
-    rocksdb_backupable_db_options_t* options) {
+unsigned char rocksdb_backup_engine_options_get_share_table_files(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.share_table_files;
 }
 
-void rocksdb_backupable_db_options_set_sync(
-    rocksdb_backupable_db_options_t* options, unsigned char val) {
+void rocksdb_backup_engine_options_set_sync(
+    rocksdb_backup_engine_options_t* options, unsigned char val) {
   options->rep.sync = val;
 }
 
-unsigned char rocksdb_backupable_db_options_get_sync(
-    rocksdb_backupable_db_options_t* options) {
+unsigned char rocksdb_backup_engine_options_get_sync(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.sync;
 }
 
-void rocksdb_backupable_db_options_set_destroy_old_data(
-    rocksdb_backupable_db_options_t* options, unsigned char val) {
+void rocksdb_backup_engine_options_set_destroy_old_data(
+    rocksdb_backup_engine_options_t* options, unsigned char val) {
   options->rep.destroy_old_data = val;
 }
 
-unsigned char rocksdb_backupable_db_options_get_destroy_old_data(
-    rocksdb_backupable_db_options_t* options) {
+unsigned char rocksdb_backup_engine_options_get_destroy_old_data(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.destroy_old_data;
 }
 
-void rocksdb_backupable_db_options_set_backup_log_files(
-    rocksdb_backupable_db_options_t* options, unsigned char val) {
+void rocksdb_backup_engine_options_set_backup_log_files(
+    rocksdb_backup_engine_options_t* options, unsigned char val) {
   options->rep.backup_log_files = val;
 }
 
-unsigned char rocksdb_backupable_db_options_get_backup_log_files(
-    rocksdb_backupable_db_options_t* options) {
+unsigned char rocksdb_backup_engine_options_get_backup_log_files(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.backup_log_files;
 }
 
-void rocksdb_backupable_db_options_set_backup_rate_limit(
-    rocksdb_backupable_db_options_t* options, uint64_t limit) {
+void rocksdb_backup_engine_options_set_backup_rate_limit(
+    rocksdb_backup_engine_options_t* options, uint64_t limit) {
   options->rep.backup_rate_limit = limit;
 }
 
-uint64_t rocksdb_backupable_db_options_get_backup_rate_limit(
-    rocksdb_backupable_db_options_t* options) {
+uint64_t rocksdb_backup_engine_options_get_backup_rate_limit(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.backup_rate_limit;
 }
 
-void rocksdb_backupable_db_options_set_restore_rate_limit(
-    rocksdb_backupable_db_options_t* options, uint64_t limit) {
+void rocksdb_backup_engine_options_set_restore_rate_limit(
+    rocksdb_backup_engine_options_t* options, uint64_t limit) {
   options->rep.restore_rate_limit = limit;
 }
 
-uint64_t rocksdb_backupable_db_options_get_restore_rate_limit(
-    rocksdb_backupable_db_options_t* options) {
+uint64_t rocksdb_backup_engine_options_get_restore_rate_limit(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.restore_rate_limit;
 }
 
-void rocksdb_backupable_db_options_set_max_background_operations(
-    rocksdb_backupable_db_options_t* options, int val) {
+void rocksdb_backup_engine_options_set_max_background_operations(
+    rocksdb_backup_engine_options_t* options, int val) {
   options->rep.max_background_operations = val;
 }
 
-int rocksdb_backupable_db_options_get_max_background_operations(
-    rocksdb_backupable_db_options_t* options) {
+int rocksdb_backup_engine_options_get_max_background_operations(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.max_background_operations;
 }
 
-void rocksdb_backupable_db_options_set_callback_trigger_interval_size(
-    rocksdb_backupable_db_options_t* options, uint64_t size) {
+void rocksdb_backup_engine_options_set_callback_trigger_interval_size(
+    rocksdb_backup_engine_options_t* options, uint64_t size) {
   options->rep.callback_trigger_interval_size = size;
 }
 
-uint64_t rocksdb_backupable_db_options_get_callback_trigger_interval_size(
-    rocksdb_backupable_db_options_t* options) {
+uint64_t rocksdb_backup_engine_options_get_callback_trigger_interval_size(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.callback_trigger_interval_size;
 }
 
-void rocksdb_backupable_db_options_set_max_valid_backups_to_open(
-    rocksdb_backupable_db_options_t* options, int val) {
+void rocksdb_backup_engine_options_set_max_valid_backups_to_open(
+    rocksdb_backup_engine_options_t* options, int val) {
   options->rep.max_valid_backups_to_open = val;
 }
 
-int rocksdb_backupable_db_options_get_max_valid_backups_to_open(
-    rocksdb_backupable_db_options_t* options) {
+int rocksdb_backup_engine_options_get_max_valid_backups_to_open(
+    rocksdb_backup_engine_options_t* options) {
   return options->rep.max_valid_backups_to_open;
 }
 
-void rocksdb_backupable_db_options_set_share_files_with_checksum_naming(
-    rocksdb_backupable_db_options_t* options, int val) {
+void rocksdb_backup_engine_options_set_share_files_with_checksum_naming(
+    rocksdb_backup_engine_options_t* options, int val) {
   options->rep.share_files_with_checksum_naming =
-      static_cast<BackupableDBOptions::ShareFilesNaming>(val);
+      static_cast<BackupEngineOptions::ShareFilesNaming>(val);
 }
 
-int rocksdb_backupable_db_options_get_share_files_with_checksum_naming(
-    rocksdb_backupable_db_options_t* options) {
+int rocksdb_backup_engine_options_get_share_files_with_checksum_naming(
+    rocksdb_backup_engine_options_t* options) {
   return static_cast<int>(options->rep.share_files_with_checksum_naming);
 }
 
-void rocksdb_backupable_db_options_destroy(
-    rocksdb_backupable_db_options_t* options) {
+void rocksdb_backup_engine_options_destroy(
+    rocksdb_backup_engine_options_t* options) {
   delete options;
 }
 
@@ -811,6 +858,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<ColumnFamilyDescriptor> 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<ColumnFamilyHandle*> 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,
@@ -825,13 +906,14 @@ rocksdb_t* rocksdb_open_column_families(
 
   DB* db;
   std::vector<ColumnFamilyHandle*> handles;
-  if (SaveError(errptr, DB::Open(DBOptions(db_options->rep),
-          std::string(name), column_families, &handles, &db))) {
+  if (SaveError(errptr, DB::Open(DBOptions(db_options->rep), std::string(name),
+                                 column_families, &handles, &db))) {
     return nullptr;
   }
 
   for (size_t i = 0; i < handles.size(); i++) {
-    rocksdb_column_family_handle_t* c_handle = new rocksdb_column_family_handle_t;
+    rocksdb_column_family_handle_t* c_handle =
+        new rocksdb_column_family_handle_t;
     c_handle->rep = handles[i];
     column_family_handles[i] = c_handle;
   }
@@ -898,7 +980,8 @@ rocksdb_t* rocksdb_open_for_read_only_column_families(
   }
 
   for (size_t i = 0; i < handles.size(); i++) {
-    rocksdb_column_family_handle_t* c_handle = new rocksdb_column_family_handle_t;
+    rocksdb_column_family_handle_t* c_handle =
+        new rocksdb_column_family_handle_t;
     c_handle->rep = handles[i];
     column_family_handles[i] = c_handle;
   }
@@ -938,18 +1021,16 @@ rocksdb_t* rocksdb_open_as_secondary_column_families(
   return result;
 }
 
-char** rocksdb_list_column_families(
-    const rocksdb_options_t* options,
-    const char* name,
-    size_t* lencfs,
-    char** errptr) {
+char** rocksdb_list_column_families(const rocksdb_options_t* options,
+                                    const char* name, size_t* lencfs,
+                                    char** errptr) {
   std::vector<std::string> fams;
-  SaveError(errptr,
-      DB::ListColumnFamilies(DBOptions(options->rep),
-        std::string(name), &fams));
+  SaveError(errptr, DB::ListColumnFamilies(DBOptions(options->rep),
+                                           std::string(name), &fams));
 
   *lencfs = fams.size();
-  char** column_families = static_cast<char**>(malloc(sizeof(char*) * fams.size()));
+  char** column_families =
+      static_cast<char**>(malloc(sizeof(char*) * fams.size()));
   for (size_t i = 0; i < fams.size(); i++) {
     column_families[i] = strdup(fams[i].c_str());
   }
@@ -964,14 +1045,12 @@ void rocksdb_list_column_families_destroy(char** list, size_t len) {
 }
 
 rocksdb_column_family_handle_t* rocksdb_create_column_family(
-    rocksdb_t* db,
-    const rocksdb_options_t* column_family_options,
-    const char* column_family_name,
-    char** errptr) {
+    rocksdb_t* db, const rocksdb_options_t* column_family_options,
+    const char* column_family_name, char** errptr) {
   rocksdb_column_family_handle_t* handle = new rocksdb_column_family_handle_t;
-  SaveError(errptr,
-      db->rep->CreateColumnFamily(ColumnFamilyOptions(column_family_options->rep),
-        std::string(column_family_name), &(handle->rep)));
+  SaveError(errptr, db->rep->CreateColumnFamily(
+                        ColumnFamilyOptions(column_family_options->rep),
+                        std::string(column_family_name), &(handle->rep)));
   return handle;
 }
 
@@ -987,56 +1066,144 @@ rocksdb_column_family_handle_t* rocksdb_create_column_family_with_ttl(
   return handle;
 }
 
-void rocksdb_drop_column_family(
-    rocksdb_t* db,
-    rocksdb_column_family_handle_t* handle,
-    char** errptr) {
+void rocksdb_drop_column_family(rocksdb_t* db,
+                                rocksdb_column_family_handle_t* handle,
+                                char** errptr) {
   SaveError(errptr, db->rep->DropColumnFamily(handle->rep));
 }
 
-void rocksdb_column_family_handle_destroy(rocksdb_column_family_handle_t* handle) {
+uint32_t rocksdb_column_family_handle_get_id(
+    rocksdb_column_family_handle_t* handle) {
+  return handle->rep->GetID();
+}
+
+char* rocksdb_column_family_handle_get_name(
+    rocksdb_column_family_handle_t* handle, size_t* name_len) {
+  auto name = handle->rep->GetName();
+  *name_len = name.size();
+  return CopyString(name);
+}
+
+void rocksdb_column_family_handle_destroy(
+    rocksdb_column_family_handle_t* handle) {
   delete handle->rep;
   delete handle;
 }
 
-void rocksdb_put(
-    rocksdb_t* db,
-    const rocksdb_writeoptions_t* options,
-    const char* key, size_t keylen,
-    const char* val, size_t vallen,
-    char** errptr) {
+void rocksdb_put(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->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)));
 }
 
-void rocksdb_delete_cf(
-    rocksdb_t* db,
-    const rocksdb_writeoptions_t* options,
-    rocksdb_column_family_handle_t* column_family,
-    const char* key, size_t keylen,
-    char** errptr) {
+void rocksdb_delete_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->Delete(options->rep, column_family->rep,
+                                    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(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,
@@ -1050,42 +1217,29 @@ 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) {
-  SaveError(errptr,
-            db->rep->Merge(options->rep, column_family->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) {
+  SaveError(errptr, db->rep->Merge(options->rep, column_family->rep,
+                                   Slice(key, keylen), Slice(val, vallen)));
 }
 
-void rocksdb_write(
-    rocksdb_t* db,
-    const rocksdb_writeoptions_t* options,
-    rocksdb_writebatch_t* batch,
-    char** errptr) {
+void rocksdb_write(rocksdb_t* db, const rocksdb_writeoptions_t* options,
+                   rocksdb_writebatch_t* batch, char** errptr) {
   SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
 }
 
-char* rocksdb_get(
-    rocksdb_t* db,
-    const rocksdb_readoptions_t* options,
-    const char* key, size_t keylen,
-    size_t* vallen,
-    char** errptr) {
+char* rocksdb_get(rocksdb_t* db, const rocksdb_readoptions_t* options,
+                  const char* key, size_t keylen, size_t* vallen,
+                  char** errptr) {
   char* result = nullptr;
   std::string tmp;
   Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp);
@@ -1101,17 +1255,14 @@ char* rocksdb_get(
   return result;
 }
 
-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) {
+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) {
   char* result = nullptr;
   std::string tmp;
-  Status s = db->rep->Get(options->rep, column_family->rep,
-      Slice(key, keylen), &tmp);
+  Status s =
+      db->rep->Get(options->rep, column_family->rep, Slice(key, keylen), &tmp);
   if (s.ok()) {
     *vallen = tmp.size();
     result = CopyString(tmp);
@@ -1124,13 +1275,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<Slice> keys(num_keys);
   for (size_t i = 0; i < num_keys; i++) {
     keys[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1154,30 +1349,33 @@ void rocksdb_multi_get(
   }
 }
 
-void rocksdb_multi_get_cf(
-    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) {
+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<Slice> keys(num_keys);
-  std::vector<ColumnFamilyHandle*> 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<std::string> values(num_keys);
-  std::vector<Status> statuses = db->rep->MultiGet(options->rep, cfs, keys, &values);
+  std::vector<std::string> timestamps(num_keys);
+  std::vector<Status> statuses =
+      db->rep->MultiGet(options->rep, keys, &values, &timestamps);
   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 {
@@ -1187,46 +1385,153 @@ void rocksdb_multi_get_cf(
   }
 }
 
-unsigned char rocksdb_key_may_exist(rocksdb_t* db,
-                                    const rocksdb_readoptions_t* options,
-                                    const char* key, size_t key_len,
-                                    char** value, size_t* val_len,
-                                    const char* timestamp, size_t timestamp_len,
-                                    unsigned char* value_found) {
-  std::string tmp;
-  std::string time;
-  if (timestamp) {
-    time.assign(timestamp, timestamp_len);
+void rocksdb_multi_get_cf(
+    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) {
+  std::vector<Slice> keys(num_keys);
+  std::vector<ColumnFamilyHandle*> 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;
   }
-  bool found = false;
-  const bool result = db->rep->KeyMayExist(options->rep, Slice(key, key_len),
-                                           &tmp, timestamp ? &time : nullptr,
-                                           value_found ? &found : nullptr);
-  if (value_found) {
-    *value_found = found;
-    if (found) {
-      *val_len = tmp.size();
-      *value = CopyString(tmp);
+  std::vector<std::string> values(num_keys);
+  std::vector<Status> 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;
+      }
     }
   }
-  return result;
 }
 
-unsigned char rocksdb_key_may_exist_cf(
+void rocksdb_multi_get_cf_with_ts(
     rocksdb_t* db, const rocksdb_readoptions_t* options,
-    rocksdb_column_family_handle_t* column_family, const char* key,
-    size_t key_len, char** value, size_t* val_len, const char* timestamp,
-    size_t timestamp_len, unsigned char* value_found) {
-  std::string tmp;
-  std::string time;
-  if (timestamp) {
-    time.assign(timestamp, timestamp_len);
-  }
-  bool found = false;
-  const bool result = db->rep->KeyMayExist(
-      options->rep, column_family->rep, Slice(key, key_len), &tmp,
-      timestamp ? &time : nullptr, value_found ? &found : nullptr);
-  if (value_found) {
+    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<Slice> keys(num_keys);
+  std::vector<ColumnFamilyHandle*> 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<std::string> values(num_keys);
+  std::vector<std::string> timestamps(num_keys);
+  std::vector<Status> statuses =
+      db->rep->MultiGet(options->rep, cfs, keys, &values, &timestamps);
+  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 {
+        errs[i] = nullptr;
+      }
+    }
+  }
+}
+
+void rocksdb_batched_multi_get_cf(rocksdb_t* db,
+                                  const rocksdb_readoptions_t* options,
+                                  rocksdb_column_family_handle_t* column_family,
+                                  size_t num_keys, const char* const* keys_list,
+                                  const size_t* keys_list_sizes,
+                                  rocksdb_pinnableslice_t** values, char** errs,
+                                  const bool sorted_input) {
+  Slice* key_slices = new Slice[num_keys];
+  PinnableSlice* value_slices = new PinnableSlice[num_keys];
+  Status* statuses = new Status[num_keys];
+  for (size_t i = 0; i < num_keys; ++i) {
+    key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
+  }
+
+  db->rep->MultiGet(options->rep, column_family->rep, num_keys, key_slices,
+                    value_slices, statuses, sorted_input);
+
+  for (size_t i = 0; i < num_keys; ++i) {
+    if (statuses[i].ok()) {
+      values[i] = new (rocksdb_pinnableslice_t);
+      values[i]->rep = std::move(value_slices[i]);
+      errs[i] = nullptr;
+    } else {
+      values[i] = nullptr;
+      if (!statuses[i].IsNotFound()) {
+        errs[i] = strdup(statuses[i].ToString().c_str());
+      } else {
+        errs[i] = nullptr;
+      }
+    }
+  }
+
+  delete[] key_slices;
+  delete[] value_slices;
+  delete[] statuses;
+}
+
+unsigned char rocksdb_key_may_exist(rocksdb_t* db,
+                                    const rocksdb_readoptions_t* options,
+                                    const char* key, size_t key_len,
+                                    char** value, size_t* val_len,
+                                    const char* timestamp, size_t timestamp_len,
+                                    unsigned char* value_found) {
+  std::string tmp;
+  std::string time;
+  if (timestamp) {
+    time.assign(timestamp, timestamp_len);
+  }
+  bool found = false;
+  const bool result = db->rep->KeyMayExist(options->rep, Slice(key, key_len),
+                                           &tmp, timestamp ? &time : nullptr,
+                                           value_found ? &found : nullptr);
+  if (value_found) {
+    *value_found = found;
+    if (found) {
+      *val_len = tmp.size();
+      *value = CopyString(tmp);
+    }
+  }
+  return result;
+}
+
+unsigned char rocksdb_key_may_exist_cf(
+    rocksdb_t* db, const rocksdb_readoptions_t* options,
+    rocksdb_column_family_handle_t* column_family, const char* key,
+    size_t key_len, char** value, size_t* val_len, const char* timestamp,
+    size_t timestamp_len, unsigned char* value_found) {
+  std::string tmp;
+  std::string time;
+  if (timestamp) {
+    time.assign(timestamp, timestamp_len);
+  }
+  bool found = false;
+  const bool result = db->rep->KeyMayExist(
+      options->rep, column_family->rep, Slice(key, key_len), &tmp,
+      timestamp ? &time : nullptr, value_found ? &found : nullptr);
+  if (value_found) {
     *value_found = found;
     if (found) {
       *val_len = tmp.size();
@@ -1237,21 +1542,19 @@ unsigned char rocksdb_key_may_exist_cf(
 }
 
 rocksdb_iterator_t* rocksdb_create_iterator(
-    rocksdb_t* db,
-    const rocksdb_readoptions_t* options) {
+    rocksdb_t* db, const rocksdb_readoptions_t* options) {
   rocksdb_iterator_t* result = new rocksdb_iterator_t;
   result->rep = db->rep->NewIterator(options->rep);
   return result;
 }
 
 rocksdb_wal_iterator_t* rocksdb_get_updates_since(
-        rocksdb_t* db, uint64_t seq_number,
-        const rocksdb_wal_readoptions_t* options,
-        char** errptr) {
+    rocksdb_t* db, uint64_t seq_number,
+    const rocksdb_wal_readoptions_t* options, char** errptr) {
   std::unique_ptr<TransactionLogIterator> iter;
   TransactionLogIterator::ReadOptions ro;
-  if (options!=nullptr) {
-      ro = options->rep;
+  if (options != nullptr) {
+    ro = options->rep;
   }
   if (SaveError(errptr, db->rep->GetUpdatesSince(seq_number, &iter, ro))) {
     return nullptr;
@@ -1261,24 +1564,24 @@ rocksdb_wal_iterator_t* rocksdb_get_updates_since(
   return result;
 }
 
-void rocksdb_wal_iter_next(rocksdb_wal_iterator_t* iter) {
-    iter->rep->Next();
-}
+void rocksdb_wal_iter_next(rocksdb_wal_iterator_t* iter) { iter->rep->Next(); }
 
 unsigned char rocksdb_wal_iter_valid(const rocksdb_wal_iterator_t* iter) {
-    return iter->rep->Valid();
+  return iter->rep->Valid();
 }
 
-void rocksdb_wal_iter_status (const rocksdb_wal_iterator_t* iter, char** errptr) {
-    SaveError(errptr, iter->rep->status());
+void rocksdb_wal_iter_status(const rocksdb_wal_iterator_t* iter,
+                             char** errptr) {
+  SaveError(errptr, iter->rep->status());
 }
 
-void rocksdb_wal_iter_destroy (const rocksdb_wal_iterator_t* iter) {
+void rocksdb_wal_iter_destroy(const rocksdb_wal_iterator_t* iter) {
   delete iter->rep;
   delete iter;
 }
 
-rocksdb_writebatch_t* rocksdb_wal_iter_get_batch (const rocksdb_wal_iterator_t* iter, uint64_t* seq) {
+rocksdb_writebatch_t* rocksdb_wal_iter_get_batch(
+    const rocksdb_wal_iterator_t* iter, uint64_t* seq) {
   rocksdb_writebatch_t* result = rocksdb_writebatch_create();
   BatchResult wal_batch = iter->rep->GetBatch();
   result->rep = std::move(*wal_batch.writeBatchPtr);
@@ -1288,26 +1591,22 @@ rocksdb_writebatch_t* rocksdb_wal_iter_get_batch (const rocksdb_wal_iterator_t*
   return result;
 }
 
-uint64_t rocksdb_get_latest_sequence_number (rocksdb_t *db) {
-    return db->rep->GetLatestSequenceNumber();
+uint64_t rocksdb_get_latest_sequence_number(rocksdb_t* db) {
+  return db->rep->GetLatestSequenceNumber();
 }
 
 rocksdb_iterator_t* rocksdb_create_iterator_cf(
-    rocksdb_t* db,
-    const rocksdb_readoptions_t* options,
+    rocksdb_t* db, const rocksdb_readoptions_t* options,
     rocksdb_column_family_handle_t* column_family) {
   rocksdb_iterator_t* result = new rocksdb_iterator_t;
   result->rep = db->rep->NewIterator(options->rep, column_family->rep);
   return result;
 }
 
-void rocksdb_create_iterators(
-    rocksdb_t *db,
-    rocksdb_readoptions_t* opts,
-    rocksdb_column_family_handle_t** column_families,
-    rocksdb_iterator_t** iterators,
-    size_t size,
-    char** errptr) {
+void rocksdb_create_iterators(rocksdb_t* db, rocksdb_readoptions_t* opts,
+                              rocksdb_column_family_handle_t** column_families,
+                              rocksdb_iterator_t** iterators, size_t size,
+                              char** errptr) {
   std::vector<ColumnFamilyHandle*> column_families_vec;
   for (size_t i = 0; i < size; i++) {
     column_families_vec.push_back(column_families[i]->rep);
@@ -1326,23 +1625,19 @@ void rocksdb_create_iterators(
   }
 }
 
-const rocksdb_snapshot_t* rocksdb_create_snapshot(
-    rocksdb_t* db) {
+const rocksdb_snapshot_t* rocksdb_create_snapshot(rocksdb_t* db) {
   rocksdb_snapshot_t* result = new rocksdb_snapshot_t;
   result->rep = db->rep->GetSnapshot();
   return result;
 }
 
-void rocksdb_release_snapshot(
-    rocksdb_t* db,
-    const rocksdb_snapshot_t* snapshot) {
+void rocksdb_release_snapshot(rocksdb_t* db,
+                              const rocksdb_snapshot_t* snapshot) {
   db->rep->ReleaseSnapshot(snapshot->rep);
   delete snapshot;
 }
 
-char* rocksdb_property_value(
-    rocksdb_t* db,
-    const char* propname) {
+char* rocksdb_property_value(rocksdb_t* db, const char* propname) {
   std::string tmp;
   if (db->rep->GetProperty(Slice(propname), &tmp)) {
     // We use strdup() since we expect human readable output.
@@ -1352,10 +1647,8 @@ char* rocksdb_property_value(
   }
 }
 
-int rocksdb_property_int(
-    rocksdb_t* db,
-    const char* propname,
-    uint64_t *out_val) {
+int rocksdb_property_int(rocksdb_t* db, const char* propname,
+                         uint64_t* out_val) {
   if (db->rep->GetIntProperty(Slice(propname), out_val)) {
     return 0;
   } else {
@@ -1363,11 +1656,9 @@ int rocksdb_property_int(
   }
 }
 
-int rocksdb_property_int_cf(
-    rocksdb_t* db,
-    rocksdb_column_family_handle_t* column_family,
-    const char* propname,
-    uint64_t *out_val) {
+int rocksdb_property_int_cf(rocksdb_t* db,
+                            rocksdb_column_family_handle_t* column_family,
+                            const char* propname, uint64_t* out_val) {
   if (db->rep->GetIntProperty(column_family->rep, Slice(propname), out_val)) {
     return 0;
   } else {
@@ -1375,10 +1666,9 @@ int rocksdb_property_int_cf(
   }
 }
 
-char* rocksdb_property_value_cf(
-    rocksdb_t* db,
-    rocksdb_column_family_handle_t* column_family,
-    const char* propname) {
+char* rocksdb_property_value_cf(rocksdb_t* db,
+                                rocksdb_column_family_handle_t* column_family,
+                                const char* propname) {
   std::string tmp;
   if (db->rep->GetProperty(column_family->rep, Slice(propname), &tmp)) {
     // We use strdup() since we expect human readable output.
@@ -1388,54 +1678,55 @@ char* rocksdb_property_value_cf(
   }
 }
 
-void rocksdb_approximate_sizes(
-    rocksdb_t* db,
-    int num_ranges,
-    const char* const* range_start_key, const size_t* range_start_key_len,
-    const char* const* range_limit_key, const size_t* range_limit_key_len,
-    uint64_t* sizes) {
+void rocksdb_approximate_sizes(rocksdb_t* db, int num_ranges,
+                               const char* const* range_start_key,
+                               const size_t* range_start_key_len,
+                               const char* const* range_limit_key,
+                               const size_t* range_limit_key_len,
+                               uint64_t* sizes, char** errptr) {
   Range* ranges = new Range[num_ranges];
   for (int i = 0; i < num_ranges; i++) {
     ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]);
     ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]);
   }
-  db->rep->GetApproximateSizes(ranges, num_ranges, sizes);
+  Status s = db->rep->GetApproximateSizes(ranges, num_ranges, sizes);
+  if (!s.ok()) {
+    SaveError(errptr, s);
+  }
   delete[] ranges;
 }
 
 void rocksdb_approximate_sizes_cf(
-    rocksdb_t* db,
-    rocksdb_column_family_handle_t* column_family,
-    int num_ranges,
-    const char* const* range_start_key, const size_t* range_start_key_len,
-    const char* const* range_limit_key, const size_t* range_limit_key_len,
-    uint64_t* sizes) {
+    rocksdb_t* db, rocksdb_column_family_handle_t* column_family,
+    int num_ranges, const char* const* range_start_key,
+    const size_t* range_start_key_len, const char* const* range_limit_key,
+    const size_t* range_limit_key_len, uint64_t* sizes, char** errptr) {
   Range* ranges = new Range[num_ranges];
   for (int i = 0; i < num_ranges; i++) {
     ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]);
     ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]);
   }
-  db->rep->GetApproximateSizes(column_family->rep, ranges, num_ranges, sizes);
+  Status s = db->rep->GetApproximateSizes(column_family->rep, ranges,
+                                          num_ranges, sizes);
+  if (!s.ok()) {
+    SaveError(errptr, s);
+  }
   delete[] ranges;
 }
 
-void rocksdb_delete_file(
-    rocksdb_t* db,
-    const char* name) {
+void rocksdb_delete_file(rocksdb_t* db, const char* name) {
   db->rep->DeleteFile(name);
 }
 
-const rocksdb_livefiles_t* rocksdb_livefiles(
-    rocksdb_t* db) {
+const rocksdb_livefiles_t* rocksdb_livefiles(rocksdb_t* db) {
   rocksdb_livefiles_t* result = new rocksdb_livefiles_t;
   db->rep->GetLiveFilesMetaData(&result->rep);
   return result;
 }
 
-void rocksdb_compact_range(
-    rocksdb_t* db,
-    const char* start_key, size_t start_key_len,
-    const char* limit_key, size_t limit_key_len) {
+void rocksdb_compact_range(rocksdb_t* db, const char* start_key,
+                           size_t start_key_len, const char* limit_key,
+                           size_t limit_key_len) {
   Slice a, b;
   db->rep->CompactRange(
       CompactRangeOptions(),
@@ -1444,11 +1735,10 @@ void rocksdb_compact_range(
       (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr));
 }
 
-void rocksdb_compact_range_cf(
-    rocksdb_t* db,
-    rocksdb_column_family_handle_t* column_family,
-    const char* start_key, size_t start_key_len,
-    const char* limit_key, size_t limit_key_len) {
+void rocksdb_compact_range_cf(rocksdb_t* db,
+                              rocksdb_column_family_handle_t* column_family,
+                              const char* start_key, size_t start_key_len,
+                              const char* limit_key, size_t limit_key_len) {
   Slice a, b;
   db->rep->CompactRange(
       CompactRangeOptions(), column_family->rep,
@@ -1457,6 +1747,29 @@ void rocksdb_compact_range_cf(
       (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr));
 }
 
+void rocksdb_suggest_compact_range(rocksdb_t* db, const char* start_key,
+                                   size_t start_key_len, const char* limit_key,
+                                   size_t limit_key_len, char** errptr) {
+  Slice a, b;
+  Status s = ROCKSDB_NAMESPACE::experimental::SuggestCompactRange(
+      db->rep,
+      (start_key ? (a = Slice(start_key, start_key_len), &a) : nullptr),
+      (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr));
+  SaveError(errptr, s);
+}
+
+void rocksdb_suggest_compact_range_cf(
+    rocksdb_t* db, rocksdb_column_family_handle_t* column_family,
+    const char* start_key, size_t start_key_len, const char* limit_key,
+    size_t limit_key_len, char** errptr) {
+  Slice a, b;
+  Status s = db->rep->SuggestCompactRange(
+      column_family->rep,
+      (start_key ? (a = Slice(start_key, start_key_len), &a) : nullptr),
+      (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr));
+  SaveError(errptr, s);
+}
+
 void rocksdb_compact_range_opt(rocksdb_t* db, rocksdb_compactoptions_t* opt,
                                const char* start_key, size_t start_key_len,
                                const char* limit_key, size_t limit_key_len) {
@@ -1481,45 +1794,37 @@ void rocksdb_compact_range_cf_opt(rocksdb_t* db,
       (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr));
 }
 
-void rocksdb_flush(
-    rocksdb_t* db,
-    const rocksdb_flushoptions_t* options,
-    char** errptr) {
+void rocksdb_flush(rocksdb_t* db, const rocksdb_flushoptions_t* options,
+                   char** errptr) {
   SaveError(errptr, db->rep->Flush(options->rep));
 }
 
-void rocksdb_flush_cf(
-    rocksdb_t* db,
-    const rocksdb_flushoptions_t* options,
-    rocksdb_column_family_handle_t* column_family,
-    char** errptr) {
+void rocksdb_flush_cf(rocksdb_t* db, const rocksdb_flushoptions_t* options,
+                      rocksdb_column_family_handle_t* column_family,
+                      char** errptr) {
   SaveError(errptr, db->rep->Flush(options->rep, column_family->rep));
 }
 
-void rocksdb_disable_file_deletions(
-    rocksdb_t* db,
-    char** errptr) {
+void rocksdb_flush_wal(rocksdb_t* db, unsigned char sync, char** errptr) {
+  SaveError(errptr, db->rep->FlushWAL(sync));
+}
+
+void rocksdb_disable_file_deletions(rocksdb_t* db, char** errptr) {
   SaveError(errptr, db->rep->DisableFileDeletions());
 }
 
-void rocksdb_enable_file_deletions(
-    rocksdb_t* db,
-    unsigned char force,
-    char** errptr) {
+void rocksdb_enable_file_deletions(rocksdb_t* db, unsigned char force,
+                                   char** errptr) {
   SaveError(errptr, db->rep->EnableFileDeletions(force));
 }
 
-void rocksdb_destroy_db(
-    const rocksdb_options_t* options,
-    const char* name,
-    char** errptr) {
+void rocksdb_destroy_db(const rocksdb_options_t* options, const char* name,
+                        char** errptr) {
   SaveError(errptr, DestroyDB(name, options->rep));
 }
 
-void rocksdb_repair_db(
-    const rocksdb_options_t* options,
-    const char* name,
-    char** errptr) {
+void rocksdb_repair_db(const rocksdb_options_t* options, const char* name,
+                       char** errptr) {
   SaveError(errptr, RepairDB(name, options->rep));
 }
 
@@ -1549,13 +1854,9 @@ void rocksdb_iter_seek_for_prev(rocksdb_iterator_t* iter, const char* k,
   iter->rep->SeekForPrev(Slice(k, klen));
 }
 
-void rocksdb_iter_next(rocksdb_iterator_t* iter) {
-  iter->rep->Next();
-}
+void rocksdb_iter_next(rocksdb_iterator_t* iter) { iter->rep->Next(); }
 
-void rocksdb_iter_prev(rocksdb_iterator_t* iter) {
-  iter->rep->Prev();
-}
+void rocksdb_iter_prev(rocksdb_iterator_t* iter) { iter->rep->Prev(); }
 
 const char* rocksdb_iter_key(const rocksdb_iterator_t* iter, size_t* klen) {
   Slice s = iter->rep->key();
@@ -1569,6 +1870,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());
 }
@@ -1584,39 +1892,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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1629,13 +1935,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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1648,27 +1953,23 @@ 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));
 }
 
-void rocksdb_writebatch_merge_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_merge_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.Merge(column_family->rep, Slice(key, klen), Slice(val, vlen));
 }
 
-void rocksdb_writebatch_mergev(
-    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_mergev(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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1681,13 +1982,12 @@ void rocksdb_writebatch_mergev(
                SliceParts(value_slices.data(), num_values));
 }
 
-void rocksdb_writebatch_mergev_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_mergev_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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1700,9 +2000,8 @@ void rocksdb_writebatch_mergev_cf(
                SliceParts(value_slices.data(), num_values));
 }
 
-void rocksdb_writebatch_delete(
-    rocksdb_writebatch_t* b,
-    const char* key, size_t klen) {
+void rocksdb_writebatch_delete(rocksdb_writebatch_t* b, const char* key,
+                               size_t klen) {
   b->rep.Delete(Slice(key, klen));
 }
 
@@ -1711,23 +2010,33 @@ void rocksdb_writebatch_singledelete(rocksdb_writebatch_t* b, const char* key,
   b->rep.SingleDelete(Slice(key, klen));
 }
 
-void rocksdb_writebatch_delete_cf(
-    rocksdb_writebatch_t* b,
-    rocksdb_column_family_handle_t* column_family,
-    const char* key, size_t klen) {
+void rocksdb_writebatch_delete_cf(rocksdb_writebatch_t* b,
+                                  rocksdb_column_family_handle_t* column_family,
+                                  const char* key, size_t klen) {
   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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1736,10 +2045,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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1794,9 +2101,8 @@ void rocksdb_writebatch_delete_rangev_cf(
                      SliceParts(end_key_slices.data(), num_keys));
 }
 
-void rocksdb_writebatch_put_log_data(
-    rocksdb_writebatch_t* b,
-    const char* blob, size_t len) {
+void rocksdb_writebatch_put_log_data(rocksdb_writebatch_t* b, const char* blob,
+                                     size_t len) {
   b->rep.PutLogData(Slice(blob, len));
 }
 
@@ -1813,11 +2119,11 @@ class H : public WriteBatch::Handler {
   }
 };
 
-void rocksdb_writebatch_iterate(
-    rocksdb_writebatch_t* b,
-    void* state,
-    void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
-    void (*deleted)(void*, const char* k, size_t klen)) {
+void rocksdb_writebatch_iterate(rocksdb_writebatch_t* b, void* state,
+                                void (*put)(void*, const char* k, size_t klen,
+                                            const char* v, size_t vlen),
+                                void (*deleted)(void*, const char* k,
+                                                size_t klen)) {
   H handler;
   handler.state_ = state;
   handler.put_ = put;
@@ -1843,9 +2149,11 @@ void rocksdb_writebatch_pop_save_point(rocksdb_writebatch_t* b, char** errptr) {
   SaveError(errptr, b->rep.PopSavePoint());
 }
 
-rocksdb_writebatch_wi_t* rocksdb_writebatch_wi_create(size_t reserved_bytes, unsigned char overwrite_key) {
+rocksdb_writebatch_wi_t* rocksdb_writebatch_wi_create(
+    size_t reserved_bytes, unsigned char overwrite_key) {
   rocksdb_writebatch_wi_t* b = new rocksdb_writebatch_wi_t;
-  b->rep = new WriteBatchWithIndex(BytewiseComparator(), reserved_bytes, overwrite_key);
+  b->rep = new WriteBatchWithIndex(BytewiseComparator(), reserved_bytes,
+                                   overwrite_key);
   return b;
 }
 
@@ -1864,27 +2172,23 @@ int rocksdb_writebatch_wi_count(rocksdb_writebatch_wi_t* b) {
   return b->rep->GetWriteBatch()->Count();
 }
 
-void rocksdb_writebatch_wi_put(
-    rocksdb_writebatch_wi_t* b,
-    const char* key, size_t klen,
-    const char* val, size_t vlen) {
+void rocksdb_writebatch_wi_put(rocksdb_writebatch_wi_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_wi_put_cf(
-    rocksdb_writebatch_wi_t* b,
-    rocksdb_column_family_handle_t* column_family,
-    const char* key, size_t klen,
-    const char* val, size_t vlen) {
+void rocksdb_writebatch_wi_put_cf(rocksdb_writebatch_wi_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_wi_putv(
-    rocksdb_writebatch_wi_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_wi_putv(rocksdb_writebatch_wi_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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1894,14 +2198,12 @@ void rocksdb_writebatch_wi_putv(
     value_slices[i] = Slice(values_list[i], values_list_sizes[i]);
   }
   b->rep->Put(SliceParts(key_slices.data(), num_keys),
-             SliceParts(value_slices.data(), num_values));
+              SliceParts(value_slices.data(), num_values));
 }
 
 void rocksdb_writebatch_wi_putv_cf(
-    rocksdb_writebatch_wi_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_wi_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<Slice> key_slices(num_keys);
@@ -1913,30 +2215,25 @@ void rocksdb_writebatch_wi_putv_cf(
     value_slices[i] = Slice(values_list[i], values_list_sizes[i]);
   }
   b->rep->Put(column_family->rep, SliceParts(key_slices.data(), num_keys),
-             SliceParts(value_slices.data(), num_values));
+              SliceParts(value_slices.data(), num_values));
 }
 
-void rocksdb_writebatch_wi_merge(
-    rocksdb_writebatch_wi_t* b,
-    const char* key, size_t klen,
-    const char* val, size_t vlen) {
+void rocksdb_writebatch_wi_merge(rocksdb_writebatch_wi_t* b, const char* key,
+                                 size_t klen, const char* val, size_t vlen) {
   b->rep->Merge(Slice(key, klen), Slice(val, vlen));
 }
 
 void rocksdb_writebatch_wi_merge_cf(
-    rocksdb_writebatch_wi_t* b,
-    rocksdb_column_family_handle_t* column_family,
-    const char* key, size_t klen,
-    const char* val, size_t vlen) {
+    rocksdb_writebatch_wi_t* b, rocksdb_column_family_handle_t* column_family,
+    const char* key, size_t klen, const char* val, size_t vlen) {
   b->rep->Merge(column_family->rep, Slice(key, klen), Slice(val, vlen));
 }
 
-void rocksdb_writebatch_wi_mergev(
-    rocksdb_writebatch_wi_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_wi_mergev(rocksdb_writebatch_wi_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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -1946,14 +2243,12 @@ void rocksdb_writebatch_wi_mergev(
     value_slices[i] = Slice(values_list[i], values_list_sizes[i]);
   }
   b->rep->Merge(SliceParts(key_slices.data(), num_keys),
-               SliceParts(value_slices.data(), num_values));
+                SliceParts(value_slices.data(), num_values));
 }
 
 void rocksdb_writebatch_wi_mergev_cf(
-    rocksdb_writebatch_wi_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_wi_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<Slice> key_slices(num_keys);
@@ -1965,12 +2260,11 @@ void rocksdb_writebatch_wi_mergev_cf(
     value_slices[i] = Slice(values_list[i], values_list_sizes[i]);
   }
   b->rep->Merge(column_family->rep, SliceParts(key_slices.data(), num_keys),
-               SliceParts(value_slices.data(), num_values));
+                SliceParts(value_slices.data(), num_values));
 }
 
-void rocksdb_writebatch_wi_delete(
-    rocksdb_writebatch_wi_t* b,
-    const char* key, size_t klen) {
+void rocksdb_writebatch_wi_delete(rocksdb_writebatch_wi_t* b, const char* key,
+                                  size_t klen) {
   b->rep->Delete(Slice(key, klen));
 }
 
@@ -1980,8 +2274,7 @@ void rocksdb_writebatch_wi_singledelete(rocksdb_writebatch_wi_t* b,
 }
 
 void rocksdb_writebatch_wi_delete_cf(
-    rocksdb_writebatch_wi_t* b,
-    rocksdb_column_family_handle_t* column_family,
+    rocksdb_writebatch_wi_t* b, rocksdb_column_family_handle_t* column_family,
     const char* key, size_t klen) {
   b->rep->Delete(column_family->rep, Slice(key, klen));
 }
@@ -1992,10 +2285,9 @@ void rocksdb_writebatch_wi_singledelete_cf(
   b->rep->SingleDelete(column_family->rep, Slice(key, klen));
 }
 
-void rocksdb_writebatch_wi_deletev(
-    rocksdb_writebatch_wi_t* b,
-    int num_keys, const char* const* keys_list,
-    const size_t* keys_list_sizes) {
+void rocksdb_writebatch_wi_deletev(rocksdb_writebatch_wi_t* b, int num_keys,
+                                   const char* const* keys_list,
+                                   const size_t* keys_list_sizes) {
   std::vector<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -2004,10 +2296,8 @@ void rocksdb_writebatch_wi_deletev(
 }
 
 void rocksdb_writebatch_wi_deletev_cf(
-    rocksdb_writebatch_wi_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_wi_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<Slice> key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
     key_slices[i] = Slice(keys_list[i], keys_list_sizes[i]);
@@ -2016,11 +2306,12 @@ void rocksdb_writebatch_wi_deletev_cf(
 }
 
 void rocksdb_writebatch_wi_delete_range(rocksdb_writebatch_wi_t* b,
-                                     const char* start_key,
-                                     size_t start_key_len, const char* end_key,
-                                     size_t end_key_len) {
+                                        const char* start_key,
+                                        size_t start_key_len,
+                                        const char* end_key,
+                                        size_t end_key_len) {
   b->rep->DeleteRange(Slice(start_key, start_key_len),
-                     Slice(end_key, end_key_len));
+                      Slice(end_key, end_key_len));
 }
 
 void rocksdb_writebatch_wi_delete_range_cf(
@@ -2028,14 +2319,15 @@ void rocksdb_writebatch_wi_delete_range_cf(
     const char* start_key, size_t start_key_len, const char* end_key,
     size_t end_key_len) {
   b->rep->DeleteRange(column_family->rep, Slice(start_key, start_key_len),
-                     Slice(end_key, end_key_len));
+                      Slice(end_key, end_key_len));
 }
 
-void rocksdb_writebatch_wi_delete_rangev(rocksdb_writebatch_wi_t* b, int num_keys,
-                                      const char* const* start_keys_list,
-                                      const size_t* start_keys_list_sizes,
-                                      const char* const* end_keys_list,
-                                      const size_t* end_keys_list_sizes) {
+void rocksdb_writebatch_wi_delete_rangev(rocksdb_writebatch_wi_t* b,
+                                         int num_keys,
+                                         const char* const* start_keys_list,
+                                         const size_t* start_keys_list_sizes,
+                                         const char* const* end_keys_list,
+                                         const size_t* end_keys_list_sizes) {
   std::vector<Slice> start_key_slices(num_keys);
   std::vector<Slice> end_key_slices(num_keys);
   for (int i = 0; i < num_keys; i++) {
@@ -2043,7 +2335,7 @@ void rocksdb_writebatch_wi_delete_rangev(rocksdb_writebatch_wi_t* b, int num_key
     end_key_slices[i] = Slice(end_keys_list[i], end_keys_list_sizes[i]);
   }
   b->rep->DeleteRange(SliceParts(start_key_slices.data(), num_keys),
-                     SliceParts(end_key_slices.data(), num_keys));
+                      SliceParts(end_key_slices.data(), num_keys));
 }
 
 void rocksdb_writebatch_wi_delete_rangev_cf(
@@ -2058,19 +2350,17 @@ void rocksdb_writebatch_wi_delete_rangev_cf(
     end_key_slices[i] = Slice(end_keys_list[i], end_keys_list_sizes[i]);
   }
   b->rep->DeleteRange(column_family->rep,
-                     SliceParts(start_key_slices.data(), num_keys),
-                     SliceParts(end_key_slices.data(), num_keys));
+                      SliceParts(start_key_slices.data(), num_keys),
+                      SliceParts(end_key_slices.data(), num_keys));
 }
 
-void rocksdb_writebatch_wi_put_log_data(
-    rocksdb_writebatch_wi_t* b,
-    const char* blob, size_t len) {
+void rocksdb_writebatch_wi_put_log_data(rocksdb_writebatch_wi_t* b,
+                                        const char* blob, size_t len) {
   b->rep->PutLogData(Slice(blob, len));
 }
 
 void rocksdb_writebatch_wi_iterate(
-    rocksdb_writebatch_wi_t* b,
-    void* state,
+    rocksdb_writebatch_wi_t* b, void* state,
     void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
     void (*deleted)(void*, const char* k, size_t klen)) {
   H handler;
@@ -2080,7 +2370,8 @@ void rocksdb_writebatch_wi_iterate(
   b->rep->GetWriteBatch()->Iterate(&handler);
 }
 
-const char* rocksdb_writebatch_wi_data(rocksdb_writebatch_wi_t* b, size_t* size) {
+const char* rocksdb_writebatch_wi_data(rocksdb_writebatch_wi_t* b,
+                                       size_t* size) {
   WriteBatch* wb = b->rep->GetWriteBatch();
   *size = wb->GetDataSize();
   return wb->Data().c_str();
@@ -2091,13 +2382,12 @@ void rocksdb_writebatch_wi_set_save_point(rocksdb_writebatch_wi_t* b) {
 }
 
 void rocksdb_writebatch_wi_rollback_to_save_point(rocksdb_writebatch_wi_t* b,
-                                               char** errptr) {
+                                                  char** errptr) {
   SaveError(errptr, b->rep->RollbackToSavePoint());
 }
 
 rocksdb_iterator_t* rocksdb_writebatch_wi_create_iterator_with_base(
-    rocksdb_writebatch_wi_t* wbwi,
-    rocksdb_iterator_t* base_iterator) {
+    rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator) {
   rocksdb_iterator_t* result = new rocksdb_iterator_t;
   result->rep = wbwi->rep->NewIteratorWithBase(base_iterator->rep);
   delete base_iterator;
@@ -2114,12 +2404,10 @@ rocksdb_iterator_t* rocksdb_writebatch_wi_create_iterator_with_base_cf(
   return result;
 }
 
-char* rocksdb_writebatch_wi_get_from_batch(
-    rocksdb_writebatch_wi_t* wbwi,
-    const rocksdb_options_t* options,
-    const char* key, size_t keylen,
-    size_t* vallen,
-    char** errptr) {
+char* rocksdb_writebatch_wi_get_from_batch(rocksdb_writebatch_wi_t* wbwi,
+                                           const rocksdb_options_t* options,
+                                           const char* key, size_t keylen,
+                                           size_t* vallen, char** errptr) {
   char* result = nullptr;
   std::string tmp;
   Status s = wbwi->rep->GetFromBatch(options->rep, Slice(key, keylen), &tmp);
@@ -2136,16 +2424,13 @@ char* rocksdb_writebatch_wi_get_from_batch(
 }
 
 char* rocksdb_writebatch_wi_get_from_batch_cf(
-    rocksdb_writebatch_wi_t* wbwi,
-    const rocksdb_options_t* options,
-    rocksdb_column_family_handle_t* column_family,
-    const char* key, size_t keylen,
-    size_t* vallen,
-    char** errptr) {
+    rocksdb_writebatch_wi_t* wbwi, const rocksdb_options_t* options,
+    rocksdb_column_family_handle_t* column_family, const char* key,
+    size_t keylen, size_t* vallen, char** errptr) {
   char* result = nullptr;
   std::string tmp;
   Status s = wbwi->rep->GetFromBatch(column_family->rep, options->rep,
-      Slice(key, keylen), &tmp);
+                                     Slice(key, keylen), &tmp);
   if (s.ok()) {
     *vallen = tmp.size();
     result = CopyString(tmp);
@@ -2159,15 +2444,13 @@ char* rocksdb_writebatch_wi_get_from_batch_cf(
 }
 
 char* rocksdb_writebatch_wi_get_from_batch_and_db(
-    rocksdb_writebatch_wi_t* wbwi,
-    rocksdb_t* db,
-    const rocksdb_readoptions_t* options,
-    const char* key, size_t keylen,
-    size_t* vallen,
-    char** errptr) {
+    rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
+    const rocksdb_readoptions_t* options, const char* key, size_t keylen,
+    size_t* vallen, char** errptr) {
   char* result = nullptr;
   std::string tmp;
-  Status s = wbwi->rep->GetFromBatchAndDB(db->rep, options->rep, Slice(key, keylen), &tmp);
+  Status s = wbwi->rep->GetFromBatchAndDB(db->rep, options->rep,
+                                          Slice(key, keylen), &tmp);
   if (s.ok()) {
     *vallen = tmp.size();
     result = CopyString(tmp);
@@ -2181,17 +2464,14 @@ char* rocksdb_writebatch_wi_get_from_batch_and_db(
 }
 
 char* rocksdb_writebatch_wi_get_from_batch_and_db_cf(
-    rocksdb_writebatch_wi_t* wbwi,
-    rocksdb_t* db,
+    rocksdb_writebatch_wi_t* wbwi, 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) {
+    rocksdb_column_family_handle_t* column_family, const char* key,
+    size_t keylen, size_t* vallen, char** errptr) {
   char* result = nullptr;
   std::string tmp;
-  Status s = wbwi->rep->GetFromBatchAndDB(db->rep, options->rep, column_family->rep,
-      Slice(key, keylen), &tmp);
+  Status s = wbwi->rep->GetFromBatchAndDB(
+      db->rep, options->rep, column_family->rep, Slice(key, keylen), &tmp);
   if (s.ok()) {
     *vallen = tmp.size();
     result = CopyString(tmp);
@@ -2204,17 +2484,64 @@ char* rocksdb_writebatch_wi_get_from_batch_and_db_cf(
   return result;
 }
 
-void rocksdb_write_writebatch_wi(
-    rocksdb_t* db,
-    const rocksdb_writeoptions_t* options,
-    rocksdb_writebatch_wi_t* wbwi,
-    char** errptr) {
+void rocksdb_write_writebatch_wi(rocksdb_t* db,
+                                 const rocksdb_writeoptions_t* options,
+                                 rocksdb_writebatch_wi_t* wbwi, char** errptr) {
   WriteBatch* wb = wbwi->rep->GetWriteBatch();
   SaveError(errptr, db->rep->Write(options->rep, wb));
 }
 
-rocksdb_block_based_table_options_t*
-rocksdb_block_based_options_create() {
+void rocksdb_load_latest_options(
+    const char* db_path, rocksdb_env_t* env, bool ignore_unknown_options,
+    rocksdb_cache_t* cache, rocksdb_options_t** db_options,
+    size_t* num_column_families, char*** list_column_family_names,
+    rocksdb_options_t*** list_column_family_options, char** errptr) {
+  DBOptions db_opt;
+  std::vector<ColumnFamilyDescriptor> cf_descs;
+  Status s = LoadLatestOptions(std::string(db_path), env->rep, &db_opt,
+                               &cf_descs, ignore_unknown_options, &cache->rep);
+  if (s.ok()) {
+    char** cf_names = (char**)malloc(cf_descs.size() * sizeof(char*));
+    rocksdb_options_t** cf_options = (rocksdb_options_t**)malloc(
+        cf_descs.size() * sizeof(rocksdb_options_t*));
+    for (size_t i = 0; i < cf_descs.size(); ++i) {
+      cf_names[i] = strdup(cf_descs[i].name.c_str());
+      cf_options[i] = new rocksdb_options_t{
+          Options(DBOptions(), std::move(cf_descs[i].options))};
+    }
+    *num_column_families = cf_descs.size();
+    *db_options = new rocksdb_options_t{
+        Options(std::move(db_opt), ColumnFamilyOptions())};
+    *list_column_family_names = cf_names;
+    *list_column_family_options = cf_options;
+  } else {
+    *num_column_families = 0;
+    *db_options = nullptr;
+    *list_column_family_names = nullptr;
+    *list_column_family_options = nullptr;
+    SaveError(errptr, s);
+  }
+}
+
+void rocksdb_load_latest_options_destroy(
+    rocksdb_options_t* db_options, char** list_column_family_names,
+    rocksdb_options_t** list_column_family_options, size_t len) {
+  rocksdb_options_destroy(db_options);
+  if (list_column_family_names) {
+    for (size_t i = 0; i < len; ++i) {
+      free(list_column_family_names[i]);
+    }
+    free(list_column_family_names);
+  }
+  if (list_column_family_options) {
+    for (size_t i = 0; i < len; ++i) {
+      rocksdb_options_destroy(list_column_family_options[i]);
+    }
+    free(list_column_family_options);
+  }
+}
+
+rocksdb_block_based_table_options_t* rocksdb_block_based_options_create() {
   return new rocksdb_block_based_table_options_t;
 }
 
@@ -2223,6 +2550,11 @@ void rocksdb_block_based_options_destroy(
   delete options;
 }
 
+void rocksdb_block_based_options_set_checksum(
+    rocksdb_block_based_table_options_t* opt, char v) {
+  opt->rep.checksum = static_cast<ROCKSDB_NAMESPACE::ChecksumType>(v);
+}
+
 void rocksdb_block_based_options_set_block_size(
     rocksdb_block_based_table_options_t* options, size_t block_size) {
   options->rep.block_size = block_size;
@@ -2239,22 +2571,26 @@ void rocksdb_block_based_options_set_block_restart_interval(
 }
 
 void rocksdb_block_based_options_set_index_block_restart_interval(
-    rocksdb_block_based_table_options_t* options, int index_block_restart_interval) {
+    rocksdb_block_based_table_options_t* options,
+    int index_block_restart_interval) {
   options->rep.index_block_restart_interval = index_block_restart_interval;
 }
 
 void rocksdb_block_based_options_set_metadata_block_size(
-    rocksdb_block_based_table_options_t* options, uint64_t metadata_block_size) {
+    rocksdb_block_based_table_options_t* options,
+    uint64_t metadata_block_size) {
   options->rep.metadata_block_size = metadata_block_size;
 }
 
 void rocksdb_block_based_options_set_partition_filters(
-    rocksdb_block_based_table_options_t* options, unsigned char partition_filters) {
+    rocksdb_block_based_table_options_t* options,
+    unsigned char partition_filters) {
   options->rep.partition_filters = partition_filters;
 }
 
 void rocksdb_block_based_options_set_use_delta_encoding(
-    rocksdb_block_based_table_options_t* options, unsigned char use_delta_encoding) {
+    rocksdb_block_based_table_options_t* options,
+    unsigned char use_delta_encoding) {
   options->rep.use_delta_encoding = use_delta_encoding;
 }
 
@@ -2304,7 +2640,7 @@ void rocksdb_block_based_options_set_index_type(
 void rocksdb_block_based_options_set_data_block_index_type(
     rocksdb_block_based_table_options_t* options, int v) {
   options->rep.data_block_index_type =
-          static_cast<BlockBasedTableOptions::DataBlockIndexType>(v);
+      static_cast<BlockBasedTableOptions::DataBlockIndexType>(v);
 }
 
 void rocksdb_block_based_options_set_data_block_hash_ratio(
@@ -2312,11 +2648,6 @@ void rocksdb_block_based_options_set_data_block_hash_ratio(
   options->rep.data_block_hash_table_util_ratio = v;
 }
 
-void rocksdb_block_based_options_set_hash_index_allow_collision(
-    rocksdb_block_based_table_options_t* options, unsigned char v) {
-  options->rep.hash_index_allow_collision = v;
-}
-
 void rocksdb_block_based_options_set_cache_index_and_filter_blocks(
     rocksdb_block_based_table_options_t* options, unsigned char v) {
   options->rep.cache_index_and_filter_blocks = v;
@@ -2338,7 +2669,7 @@ void rocksdb_block_based_options_set_pin_top_level_index_and_filter(
 }
 
 void rocksdb_options_set_block_based_table_factory(
-    rocksdb_options_t *opt,
+    rocksdb_options_topt,
     rocksdb_block_based_table_options_t* table_options) {
   if (table_options) {
     opt->rep.table_factory.reset(
@@ -2346,13 +2677,11 @@ void rocksdb_options_set_block_based_table_factory(
   }
 }
 
-rocksdb_cuckoo_table_options_t*
-rocksdb_cuckoo_options_create() {
+rocksdb_cuckoo_table_options_t* rocksdb_cuckoo_options_create() {
   return new rocksdb_cuckoo_table_options_t;
 }
 
-void rocksdb_cuckoo_options_destroy(
-    rocksdb_cuckoo_table_options_t* options) {
+void rocksdb_cuckoo_options_destroy(rocksdb_cuckoo_table_options_t* options) {
   delete options;
 }
 
@@ -2382,51 +2711,44 @@ void rocksdb_cuckoo_options_set_use_module_hash(
 }
 
 void rocksdb_options_set_cuckoo_table_factory(
-    rocksdb_options_t *opt,
-    rocksdb_cuckoo_table_options_t* table_options) {
+    rocksdb_options_t* opt, rocksdb_cuckoo_table_options_t* table_options) {
   if (table_options) {
     opt->rep.table_factory.reset(
         ROCKSDB_NAMESPACE::NewCuckooTableFactory(table_options->rep));
   }
 }
 
-void rocksdb_set_options(
-    rocksdb_t* db, int count, const char* const keys[], const char* const values[], char** errptr) {
-        std::unordered_map<std::string, std::string> options_map;
-        for (int i=0; i<count; i++)
-            options_map[keys[i]] = values[i];
-        SaveError(errptr,
-            db->rep->SetOptions(options_map));
-    }
-
-void rocksdb_set_options_cf(
-    rocksdb_t* db, rocksdb_column_family_handle_t* handle, int count, const char* const keys[], const char* const values[], char** errptr) {
-        std::unordered_map<std::string, std::string> options_map;
-        for (int i=0; i<count; i++)
-            options_map[keys[i]] = values[i];
-        SaveError(errptr,
-            db->rep->SetOptions(handle->rep, options_map));
-    }
-
-rocksdb_options_t* rocksdb_options_create() {
-  return new rocksdb_options_t;
+void rocksdb_set_options(rocksdb_t* db, int count, const char* const keys[],
+                         const char* const values[], char** errptr) {
+  std::unordered_map<std::string, std::string> options_map;
+  for (int i = 0; i < count; i++) options_map[keys[i]] = values[i];
+  SaveError(errptr, db->rep->SetOptions(options_map));
 }
 
-void rocksdb_options_destroy(rocksdb_options_t* options) {
-  delete options;
+void rocksdb_set_options_cf(rocksdb_t* db,
+                            rocksdb_column_family_handle_t* handle, int count,
+                            const char* const keys[],
+                            const char* const values[], char** errptr) {
+  std::unordered_map<std::string, std::string> options_map;
+  for (int i = 0; i < count; i++) options_map[keys[i]] = values[i];
+  SaveError(errptr, db->rep->SetOptions(handle->rep, options_map));
 }
 
+rocksdb_options_t* rocksdb_options_create() { return new rocksdb_options_t; }
+
+void rocksdb_options_destroy(rocksdb_options_t* options) { delete options; }
+
 rocksdb_options_t* rocksdb_options_create_copy(rocksdb_options_t* options) {
   return new rocksdb_options_t(*options);
 }
 
-void rocksdb_options_increase_parallelism(
-    rocksdb_options_t* opt, int total_threads) {
+void rocksdb_options_increase_parallelism(rocksdb_options_t* opt,
+                                          int total_threads) {
   opt->rep.IncreaseParallelism(total_threads);
 }
 
-void rocksdb_options_optimize_for_point_lookup(
-    rocksdb_options_t* opt, uint64_t block_cache_size_mb) {
+void rocksdb_options_optimize_for_point_lookup(rocksdb_options_t* opt,
+                                               uint64_t block_cache_size_mb) {
   opt->rep.OptimizeForPointLookup(block_cache_size_mb);
 }
 
@@ -2440,8 +2762,8 @@ void rocksdb_options_optimize_universal_style_compaction(
   opt->rep.OptimizeUniversalStyleCompaction(memtable_memory_budget);
 }
 
-void rocksdb_options_set_allow_ingest_behind(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_allow_ingest_behind(rocksdb_options_t* opt,
+                                             unsigned char v) {
   opt->rep.allow_ingest_behind = v;
 }
 
@@ -2449,9 +2771,8 @@ unsigned char rocksdb_options_get_allow_ingest_behind(rocksdb_options_t* opt) {
   return opt->rep.allow_ingest_behind;
 }
 
-void rocksdb_options_set_compaction_filter(
-    rocksdb_options_t* opt,
-    rocksdb_compactionfilter_t* filter) {
+void rocksdb_options_set_compaction_filter(rocksdb_options_t* opt,
+                                           rocksdb_compactionfilter_t* filter) {
   opt->rep.compaction_filter = filter;
 }
 
@@ -2461,8 +2782,8 @@ void rocksdb_options_set_compaction_filter_factory(
       std::shared_ptr<CompactionFilterFactory>(factory);
 }
 
-void rocksdb_options_compaction_readahead_size(
-    rocksdb_options_t* opt, size_t s) {
+void rocksdb_options_compaction_readahead_size(rocksdb_options_t* opt,
+                                               size_t s) {
   opt->rep.compaction_readahead_size = s;
 }
 
@@ -2470,20 +2791,18 @@ size_t rocksdb_options_get_compaction_readahead_size(rocksdb_options_t* opt) {
   return opt->rep.compaction_readahead_size;
 }
 
-void rocksdb_options_set_comparator(
-    rocksdb_options_t* opt,
-    rocksdb_comparator_t* cmp) {
+void rocksdb_options_set_comparator(rocksdb_options_t* opt,
+                                    rocksdb_comparator_t* cmp) {
   opt->rep.comparator = cmp;
 }
 
 void rocksdb_options_set_merge_operator(
-    rocksdb_options_t* opt,
-    rocksdb_mergeoperator_t* merge_operator) {
+    rocksdb_options_t* opt, rocksdb_mergeoperator_t* merge_operator) {
   opt->rep.merge_operator = std::shared_ptr<MergeOperator>(merge_operator);
 }
 
-void rocksdb_options_set_create_if_missing(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_create_if_missing(rocksdb_options_t* opt,
+                                           unsigned char v) {
   opt->rep.create_if_missing = v;
 }
 
@@ -2491,8 +2810,8 @@ unsigned char rocksdb_options_get_create_if_missing(rocksdb_options_t* opt) {
   return opt->rep.create_if_missing;
 }
 
-void rocksdb_options_set_create_missing_column_families(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_create_missing_column_families(rocksdb_options_t* opt,
+                                                        unsigned char v) {
   opt->rep.create_missing_column_families = v;
 }
 
@@ -2501,8 +2820,8 @@ unsigned char rocksdb_options_get_create_missing_column_families(
   return opt->rep.create_missing_column_families;
 }
 
-void rocksdb_options_set_error_if_exists(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_error_if_exists(rocksdb_options_t* opt,
+                                         unsigned char v) {
   opt->rep.error_if_exists = v;
 }
 
@@ -2510,8 +2829,8 @@ unsigned char rocksdb_options_get_error_if_exists(rocksdb_options_t* opt) {
   return opt->rep.error_if_exists;
 }
 
-void rocksdb_options_set_paranoid_checks(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_paranoid_checks(rocksdb_options_t* opt,
+                                         unsigned char v) {
   opt->rep.paranoid_checks = v;
 }
 
@@ -2539,8 +2858,7 @@ void rocksdb_options_set_info_log(rocksdb_options_t* opt, rocksdb_logger_t* l) {
   }
 }
 
-void rocksdb_options_set_info_log_level(
-    rocksdb_options_t* opt, int v) {
+void rocksdb_options_set_info_log_level(rocksdb_options_t* opt, int v) {
   opt->rep.info_log_level = static_cast<InfoLogLevel>(v);
 }
 
@@ -2573,7 +2891,8 @@ int rocksdb_options_get_max_open_files(rocksdb_options_t* opt) {
   return opt->rep.max_open_files;
 }
 
-void rocksdb_options_set_max_file_opening_threads(rocksdb_options_t* opt, int n) {
+void rocksdb_options_set_max_file_opening_threads(rocksdb_options_t* opt,
+                                                  int n) {
   opt->rep.max_file_opening_threads = n;
 }
 
@@ -2581,7 +2900,8 @@ int rocksdb_options_get_max_file_opening_threads(rocksdb_options_t* opt) {
   return opt->rep.max_file_opening_threads;
 }
 
-void rocksdb_options_set_max_total_wal_size(rocksdb_options_t* opt, uint64_t n) {
+void rocksdb_options_set_max_total_wal_size(rocksdb_options_t* opt,
+                                            uint64_t n) {
   opt->rep.max_total_wal_size = n;
 }
 
@@ -2589,8 +2909,8 @@ uint64_t rocksdb_options_get_max_total_wal_size(rocksdb_options_t* opt) {
   return opt->rep.max_total_wal_size;
 }
 
-void rocksdb_options_set_target_file_size_base(
-    rocksdb_options_t* opt, uint64_t n) {
+void rocksdb_options_set_target_file_size_base(rocksdb_options_t* opt,
+                                               uint64_t n) {
   opt->rep.target_file_size_base = n;
 }
 
@@ -2598,8 +2918,8 @@ uint64_t rocksdb_options_get_target_file_size_base(rocksdb_options_t* opt) {
   return opt->rep.target_file_size_base;
 }
 
-void rocksdb_options_set_target_file_size_multiplier(
-    rocksdb_options_t* opt, int n) {
+void rocksdb_options_set_target_file_size_multiplier(rocksdb_options_t* opt,
+                                                     int n) {
   opt->rep.target_file_size_multiplier = n;
 }
 
@@ -2607,8 +2927,8 @@ int rocksdb_options_get_target_file_size_multiplier(rocksdb_options_t* opt) {
   return opt->rep.target_file_size_multiplier;
 }
 
-void rocksdb_options_set_max_bytes_for_level_base(
-    rocksdb_options_t* opt, uint64_t n) {
+void rocksdb_options_set_max_bytes_for_level_base(rocksdb_options_t* opt,
+                                                  uint64_t n) {
   opt->rep.max_bytes_for_level_base = n;
 }
 
@@ -2677,26 +2997,120 @@ unsigned char rocksdb_options_get_skip_checking_sst_file_sizes_on_db_open(
   return opt->rep.skip_checking_sst_file_sizes_on_db_open;
 }
 
-void rocksdb_options_set_num_levels(rocksdb_options_t* opt, int n) {
-  opt->rep.num_levels = n;
+/* Blob Options Settings */
+void rocksdb_options_set_enable_blob_files(rocksdb_options_t* opt,
+                                           unsigned char val) {
+  opt->rep.enable_blob_files = val;
+}
+extern ROCKSDB_LIBRARY_API unsigned char rocksdb_options_get_enable_blob_files(
+    rocksdb_options_t* opt) {
+  return opt->rep.enable_blob_files;
 }
 
-int rocksdb_options_get_num_levels(rocksdb_options_t* opt) {
-  return opt->rep.num_levels;
+void rocksdb_options_set_min_blob_size(rocksdb_options_t* opt, uint64_t val) {
+  opt->rep.min_blob_size = val;
 }
 
-void rocksdb_options_set_level0_file_num_compaction_trigger(
-    rocksdb_options_t* opt, int n) {
-  opt->rep.level0_file_num_compaction_trigger = n;
+uint64_t rocksdb_options_get_min_blob_size(rocksdb_options_t* opt) {
+  return opt->rep.min_blob_size;
 }
 
-int rocksdb_options_get_level0_file_num_compaction_trigger(
-    rocksdb_options_t* opt) {
-  return opt->rep.level0_file_num_compaction_trigger;
+void rocksdb_options_set_blob_file_size(rocksdb_options_t* opt, uint64_t val) {
+  opt->rep.blob_file_size = val;
+}
+
+uint64_t rocksdb_options_get_blob_file_size(rocksdb_options_t* opt) {
+  return opt->rep.blob_file_size;
+}
+
+void rocksdb_options_set_blob_compression_type(rocksdb_options_t* opt,
+                                               int val) {
+  opt->rep.blob_compression_type = static_cast<CompressionType>(val);
+}
+
+int rocksdb_options_get_blob_compression_type(rocksdb_options_t* opt) {
+  return opt->rep.blob_compression_type;
+}
+
+void rocksdb_options_set_enable_blob_gc(rocksdb_options_t* opt,
+                                        unsigned char val) {
+  opt->rep.enable_blob_garbage_collection = val;
+}
+
+unsigned char rocksdb_options_get_enable_blob_gc(rocksdb_options_t* opt) {
+  return opt->rep.enable_blob_garbage_collection;
+}
+
+void rocksdb_options_set_blob_gc_age_cutoff(rocksdb_options_t* opt,
+                                            double val) {
+  opt->rep.blob_garbage_collection_age_cutoff = val;
+}
+
+double rocksdb_options_get_blob_gc_age_cutoff(rocksdb_options_t* opt) {
+  return opt->rep.blob_garbage_collection_age_cutoff;
+}
+
+void rocksdb_options_set_blob_gc_force_threshold(rocksdb_options_t* opt,
+                                                 double val) {
+  opt->rep.blob_garbage_collection_force_threshold = val;
+}
+
+double rocksdb_options_get_blob_gc_force_threshold(rocksdb_options_t* opt) {
+  return opt->rep.blob_garbage_collection_force_threshold;
+}
+
+void rocksdb_options_set_blob_compaction_readahead_size(rocksdb_options_t* opt,
+                                                        uint64_t val) {
+  opt->rep.blob_compaction_readahead_size = val;
+}
+
+uint64_t rocksdb_options_get_blob_compaction_readahead_size(
+    rocksdb_options_t* opt) {
+  return opt->rep.blob_compaction_readahead_size;
+}
+
+void rocksdb_options_set_blob_file_starting_level(rocksdb_options_t* opt,
+                                                  int val) {
+  opt->rep.blob_file_starting_level = val;
+}
+
+int rocksdb_options_get_blob_file_starting_level(rocksdb_options_t* opt) {
+  return opt->rep.blob_file_starting_level;
+}
+
+void rocksdb_options_set_blob_cache(rocksdb_options_t* opt,
+                                    rocksdb_cache_t* blob_cache) {
+  opt->rep.blob_cache = blob_cache->rep;
+}
+
+void rocksdb_options_set_prepopulate_blob_cache(rocksdb_options_t* opt, int t) {
+  opt->rep.prepopulate_blob_cache = static_cast<PrepopulateBlobCache>(t);
 }
 
-void rocksdb_options_set_level0_slowdown_writes_trigger(
+int rocksdb_options_get_prepopulate_blob_cache(rocksdb_options_t* opt) {
+  return static_cast<int>(opt->rep.prepopulate_blob_cache);
+}
+
+void rocksdb_options_set_num_levels(rocksdb_options_t* opt, int n) {
+  opt->rep.num_levels = n;
+}
+
+int rocksdb_options_get_num_levels(rocksdb_options_t* opt) {
+  return opt->rep.num_levels;
+}
+
+void rocksdb_options_set_level0_file_num_compaction_trigger(
     rocksdb_options_t* opt, int n) {
+  opt->rep.level0_file_num_compaction_trigger = n;
+}
+
+int rocksdb_options_get_level0_file_num_compaction_trigger(
+    rocksdb_options_t* opt) {
+  return opt->rep.level0_file_num_compaction_trigger;
+}
+
+void rocksdb_options_set_level0_slowdown_writes_trigger(rocksdb_options_t* opt,
+                                                        int n) {
   opt->rep.level0_slowdown_writes_trigger = n;
 }
 
@@ -2704,8 +3118,8 @@ int rocksdb_options_get_level0_slowdown_writes_trigger(rocksdb_options_t* opt) {
   return opt->rep.level0_slowdown_writes_trigger;
 }
 
-void rocksdb_options_set_level0_stop_writes_trigger(
-    rocksdb_options_t* opt, int n) {
+void rocksdb_options_set_level0_stop_writes_trigger(rocksdb_options_t* opt,
+                                                    int n) {
   opt->rep.level0_stop_writes_trigger = n;
 }
 
@@ -2713,10 +3127,7 @@ int rocksdb_options_get_level0_stop_writes_trigger(rocksdb_options_t* opt) {
   return opt->rep.level0_stop_writes_trigger;
 }
 
-void rocksdb_options_set_max_mem_compaction_level(rocksdb_options_t* /*opt*/,
-                                                  int /*n*/) {}
-
-void rocksdb_options_set_wal_recovery_mode(rocksdb_options_t* opt,int mode) {
+void rocksdb_options_set_wal_recovery_mode(rocksdb_options_t* opt, int mode) {
   opt->rep.wal_recovery_mode = static_cast<WALRecoveryMode>(mode);
 }
 
@@ -2741,12 +3152,12 @@ int rocksdb_options_get_bottommost_compression(rocksdb_options_t* opt) {
 }
 
 void rocksdb_options_set_compression_per_level(rocksdb_options_t* opt,
-                                               int* level_values,
+                                               const int* level_values,
                                                size_t num_levels) {
   opt->rep.compression_per_level.resize(num_levels);
   for (size_t i = 0; i < num_levels; ++i) {
     opt->rep.compression_per_level[i] =
-      static_cast<CompressionType>(level_values[i]);
+        static_cast<CompressionType>(level_values[i]);
   }
 }
 
@@ -2769,6 +3180,28 @@ void rocksdb_options_set_bottommost_compression_options_zstd_max_train_bytes(
   opt->rep.bottommost_compression_opts.enabled = enabled;
 }
 
+void rocksdb_options_set_bottommost_compression_options_use_zstd_dict_trainer(
+    rocksdb_options_t* opt, unsigned char use_zstd_dict_trainer,
+    unsigned char enabled) {
+  opt->rep.bottommost_compression_opts.use_zstd_dict_trainer =
+      use_zstd_dict_trainer;
+  opt->rep.bottommost_compression_opts.enabled = enabled;
+}
+
+unsigned char
+rocksdb_options_get_bottommost_compression_options_use_zstd_dict_trainer(
+    rocksdb_options_t* opt) {
+  return opt->rep.bottommost_compression_opts.use_zstd_dict_trainer;
+}
+
+void rocksdb_options_set_bottommost_compression_options_max_dict_buffer_bytes(
+    rocksdb_options_t* opt, uint64_t max_dict_buffer_bytes,
+    unsigned char enabled) {
+  opt->rep.bottommost_compression_opts.max_dict_buffer_bytes =
+      max_dict_buffer_bytes;
+  opt->rep.bottommost_compression_opts.enabled = enabled;
+}
+
 void rocksdb_options_set_compression_options(rocksdb_options_t* opt, int w_bits,
                                              int level, int strategy,
                                              int max_dict_bytes) {
@@ -2783,13 +3216,47 @@ void rocksdb_options_set_compression_options_zstd_max_train_bytes(
   opt->rep.compression_opts.zstd_max_train_bytes = zstd_max_train_bytes;
 }
 
+int rocksdb_options_get_compression_options_zstd_max_train_bytes(
+    rocksdb_options_t* opt) {
+  return opt->rep.compression_opts.zstd_max_train_bytes;
+}
+
+void rocksdb_options_set_compression_options_use_zstd_dict_trainer(
+    rocksdb_options_t* opt, unsigned char use_zstd_dict_trainer) {
+  opt->rep.compression_opts.use_zstd_dict_trainer = use_zstd_dict_trainer;
+}
+
+unsigned char rocksdb_options_get_compression_options_use_zstd_dict_trainer(
+    rocksdb_options_t* opt) {
+  return opt->rep.compression_opts.use_zstd_dict_trainer;
+}
+
+void rocksdb_options_set_compression_options_parallel_threads(
+    rocksdb_options_t* opt, int value) {
+  opt->rep.compression_opts.parallel_threads = value;
+}
+
+int rocksdb_options_get_compression_options_parallel_threads(
+    rocksdb_options_t* opt) {
+  return opt->rep.compression_opts.parallel_threads;
+}
+
+void rocksdb_options_set_compression_options_max_dict_buffer_bytes(
+    rocksdb_options_t* opt, uint64_t max_dict_buffer_bytes) {
+  opt->rep.compression_opts.max_dict_buffer_bytes = max_dict_buffer_bytes;
+}
+
+uint64_t rocksdb_options_get_compression_options_max_dict_buffer_bytes(
+    rocksdb_options_t* opt) {
+  return opt->rep.compression_opts.max_dict_buffer_bytes;
+}
+
 void rocksdb_options_set_prefix_extractor(
     rocksdb_options_t* opt, rocksdb_slicetransform_t* prefix_extractor) {
   opt->rep.prefix_extractor.reset(prefix_extractor);
 }
 
-void rocksdb_options_set_use_fsync(
-    rocksdb_options_t* opt, int use_fsync) {
+void rocksdb_options_set_use_fsync(rocksdb_options_t* opt, int use_fsync) {
   opt->rep.use_fsync = use_fsync;
 }
 
@@ -2797,13 +3264,12 @@ int rocksdb_options_get_use_fsync(rocksdb_options_t* opt) {
   return opt->rep.use_fsync;
 }
 
-void rocksdb_options_set_db_log_dir(
-    rocksdb_options_t* opt, const char* db_log_dir) {
+void rocksdb_options_set_db_log_dir(rocksdb_options_t* opt,
+                                    const char* db_log_dir) {
   opt->rep.db_log_dir = db_log_dir;
 }
 
-void rocksdb_options_set_wal_dir(
-    rocksdb_options_t* opt, const char* v) {
+void rocksdb_options_set_wal_dir(rocksdb_options_t* opt, const char* v) {
   opt->rep.wal_dir = v;
 }
 
@@ -2815,8 +3281,8 @@ uint64_t rocksdb_options_get_WAL_ttl_seconds(rocksdb_options_t* opt) {
   return opt->rep.WAL_ttl_seconds;
 }
 
-void rocksdb_options_set_WAL_size_limit_MB(
-    rocksdb_options_t* opt, uint64_t limit) {
+void rocksdb_options_set_WAL_size_limit_MB(rocksdb_options_t* opt,
+                                           uint64_t limit) {
   opt->rep.WAL_size_limit_MB = limit;
 }
 
@@ -2824,8 +3290,8 @@ uint64_t rocksdb_options_get_WAL_size_limit_MB(rocksdb_options_t* opt) {
   return opt->rep.WAL_size_limit_MB;
 }
 
-void rocksdb_options_set_manifest_preallocation_size(
-    rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_manifest_preallocation_size(rocksdb_options_t* opt,
+                                                     size_t v) {
   opt->rep.manifest_preallocation_size = v;
 }
 
@@ -2833,10 +3299,6 @@ size_t rocksdb_options_get_manifest_preallocation_size(rocksdb_options_t* opt) {
   return opt->rep.manifest_preallocation_size;
 }
 
-// noop
-void rocksdb_options_set_purge_redundant_kvs_while_flush(
-    rocksdb_options_t* /*opt*/, unsigned char /*v*/) {}
-
 void rocksdb_options_set_use_direct_reads(rocksdb_options_t* opt,
                                           unsigned char v) {
   opt->rep.use_direct_reads = v;
@@ -2856,8 +3318,8 @@ unsigned char rocksdb_options_get_use_direct_io_for_flush_and_compaction(
   return opt->rep.use_direct_io_for_flush_and_compaction;
 }
 
-void rocksdb_options_set_allow_mmap_reads(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_allow_mmap_reads(rocksdb_options_t* opt,
+                                          unsigned char v) {
   opt->rep.allow_mmap_reads = v;
 }
 
@@ -2865,8 +3327,8 @@ unsigned char rocksdb_options_get_allow_mmap_reads(rocksdb_options_t* opt) {
   return opt->rep.allow_mmap_reads;
 }
 
-void rocksdb_options_set_allow_mmap_writes(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_allow_mmap_writes(rocksdb_options_t* opt,
+                                           unsigned char v) {
   opt->rep.allow_mmap_writes = v;
 }
 
@@ -2874,8 +3336,8 @@ unsigned char rocksdb_options_get_allow_mmap_writes(rocksdb_options_t* opt) {
   return opt->rep.allow_mmap_writes;
 }
 
-void rocksdb_options_set_is_fd_close_on_exec(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_is_fd_close_on_exec(rocksdb_options_t* opt,
+                                             unsigned char v) {
   opt->rep.is_fd_close_on_exec = v;
 }
 
@@ -2883,18 +3345,8 @@ unsigned char rocksdb_options_get_is_fd_close_on_exec(rocksdb_options_t* opt) {
   return opt->rep.is_fd_close_on_exec;
 }
 
-void rocksdb_options_set_skip_log_error_on_recovery(
-    rocksdb_options_t* opt, unsigned char v) {
-  opt->rep.skip_log_error_on_recovery = v;
-}
-
-unsigned char rocksdb_options_get_skip_log_error_on_recovery(
-    rocksdb_options_t* opt) {
-  return opt->rep.skip_log_error_on_recovery;
-}
-
-void rocksdb_options_set_stats_dump_period_sec(
-    rocksdb_options_t* opt, unsigned int v) {
+void rocksdb_options_set_stats_dump_period_sec(rocksdb_options_t* opt,
+                                               unsigned int v) {
   opt->rep.stats_dump_period_sec = v;
 }
 
@@ -2912,8 +3364,8 @@ unsigned int rocksdb_options_get_stats_persist_period_sec(
   return opt->rep.stats_persist_period_sec;
 }
 
-void rocksdb_options_set_advise_random_on_open(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_advise_random_on_open(rocksdb_options_t* opt,
+                                               unsigned char v) {
   opt->rep.advise_random_on_open = v;
 }
 
@@ -2922,9 +3374,9 @@ unsigned char rocksdb_options_get_advise_random_on_open(
   return opt->rep.advise_random_on_open;
 }
 
-void rocksdb_options_set_access_hint_on_compaction_start(
-    rocksdb_options_t* opt, int v) {
-  switch(v) {
+void rocksdb_options_set_access_hint_on_compaction_start(rocksdb_options_t* opt,
+                                                         int v) {
+  switch (v) {
     case 0:
       opt->rep.access_hint_on_compaction_start =
           ROCKSDB_NAMESPACE::Options::NONE;
@@ -2941,6 +3393,8 @@ void rocksdb_options_set_access_hint_on_compaction_start(
       opt->rep.access_hint_on_compaction_start =
           ROCKSDB_NAMESPACE::Options::WILLNEED;
       break;
+    default:
+      assert(0);
   }
 }
 
@@ -2949,8 +3403,8 @@ int rocksdb_options_get_access_hint_on_compaction_start(
   return opt->rep.access_hint_on_compaction_start;
 }
 
-void rocksdb_options_set_use_adaptive_mutex(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_use_adaptive_mutex(rocksdb_options_t* opt,
+                                            unsigned char v) {
   opt->rep.use_adaptive_mutex = v;
 }
 
@@ -2958,8 +3412,8 @@ unsigned char rocksdb_options_get_use_adaptive_mutex(rocksdb_options_t* opt) {
   return opt->rep.use_adaptive_mutex;
 }
 
-void rocksdb_options_set_wal_bytes_per_sync(
-    rocksdb_options_t* opt, uint64_t v) {
+void rocksdb_options_set_wal_bytes_per_sync(rocksdb_options_t* opt,
+                                            uint64_t v) {
   opt->rep.wal_bytes_per_sync = v;
 }
 
@@ -2967,8 +3421,7 @@ uint64_t rocksdb_options_get_wal_bytes_per_sync(rocksdb_options_t* opt) {
   return opt->rep.wal_bytes_per_sync;
 }
 
-void rocksdb_options_set_bytes_per_sync(
-    rocksdb_options_t* opt, uint64_t v) {
+void rocksdb_options_set_bytes_per_sync(rocksdb_options_t* opt, uint64_t v) {
   opt->rep.bytes_per_sync = v;
 }
 
@@ -3016,7 +3469,8 @@ uint64_t rocksdb_options_get_max_sequential_skip_in_iterations(
   return opt->rep.max_sequential_skip_in_iterations;
 }
 
-void rocksdb_options_set_max_write_buffer_number(rocksdb_options_t* opt, int n) {
+void rocksdb_options_set_max_write_buffer_number(rocksdb_options_t* opt,
+                                                 int n) {
   opt->rep.max_write_buffer_number = n;
 }
 
@@ -3024,7 +3478,8 @@ int rocksdb_options_get_max_write_buffer_number(rocksdb_options_t* opt) {
   return opt->rep.max_write_buffer_number;
 }
 
-void rocksdb_options_set_min_write_buffer_number_to_merge(rocksdb_options_t* opt, int n) {
+void rocksdb_options_set_min_write_buffer_number_to_merge(
+    rocksdb_options_t* opt, int n) {
   opt->rep.min_write_buffer_number_to_merge = n;
 }
 
@@ -3089,7 +3544,8 @@ int rocksdb_options_get_max_background_jobs(rocksdb_options_t* opt) {
   return opt->rep.max_background_jobs;
 }
 
-void rocksdb_options_set_max_background_compactions(rocksdb_options_t* opt, int n) {
+void rocksdb_options_set_max_background_compactions(rocksdb_options_t* opt,
+                                                    int n) {
   opt->rep.max_background_compactions = n;
 }
 
@@ -3097,15 +3553,6 @@ int rocksdb_options_get_max_background_compactions(rocksdb_options_t* opt) {
   return opt->rep.max_background_compactions;
 }
 
-void rocksdb_options_set_base_background_compactions(rocksdb_options_t* opt,
-                                                     int n) {
-  opt->rep.base_background_compactions = n;
-}
-
-int rocksdb_options_get_base_background_compactions(rocksdb_options_t* opt) {
-  return opt->rep.base_background_compactions;
-}
-
 void rocksdb_options_set_max_background_flushes(rocksdb_options_t* opt, int n) {
   opt->rep.max_background_flushes = n;
 }
@@ -3114,6 +3561,16 @@ int rocksdb_options_get_max_background_flushes(rocksdb_options_t* opt) {
   return opt->rep.max_background_flushes;
 }
 
+void rocksdb_options_set_experimental_mempurge_threshold(rocksdb_options_t* opt,
+                                                         double v) {
+  opt->rep.experimental_mempurge_threshold = v;
+}
+
+double rocksdb_options_get_experimental_mempurge_threshold(
+    rocksdb_options_t* opt) {
+  return opt->rep.experimental_mempurge_threshold;
+}
+
 void rocksdb_options_set_max_log_file_size(rocksdb_options_t* opt, size_t v) {
   opt->rep.max_log_file_size = v;
 }
@@ -3122,7 +3579,8 @@ size_t rocksdb_options_get_max_log_file_size(rocksdb_options_t* opt) {
   return opt->rep.max_log_file_size;
 }
 
-void rocksdb_options_set_log_file_time_to_roll(rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_log_file_time_to_roll(rocksdb_options_t* opt,
+                                               size_t v) {
   opt->rep.log_file_time_to_roll = v;
 }
 
@@ -3147,23 +3605,8 @@ size_t rocksdb_options_get_recycle_log_file_num(rocksdb_options_t* opt) {
   return opt->rep.recycle_log_file_num;
 }
 
-void rocksdb_options_set_soft_rate_limit(rocksdb_options_t* opt, double v) {
-  opt->rep.soft_rate_limit = v;
-}
-
-double rocksdb_options_get_soft_rate_limit(rocksdb_options_t* opt) {
-  return opt->rep.soft_rate_limit;
-}
-
-void rocksdb_options_set_hard_rate_limit(rocksdb_options_t* opt, double v) {
-  opt->rep.hard_rate_limit = v;
-}
-
-double rocksdb_options_get_hard_rate_limit(rocksdb_options_t* opt) {
-  return opt->rep.hard_rate_limit;
-}
-
-void rocksdb_options_set_soft_pending_compaction_bytes_limit(rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_soft_pending_compaction_bytes_limit(
+    rocksdb_options_t* opt, size_t v) {
   opt->rep.soft_pending_compaction_bytes_limit = v;
 }
 
@@ -3172,7 +3615,8 @@ size_t rocksdb_options_get_soft_pending_compaction_bytes_limit(
   return opt->rep.soft_pending_compaction_bytes_limit;
 }
 
-void rocksdb_options_set_hard_pending_compaction_bytes_limit(rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_hard_pending_compaction_bytes_limit(
+    rocksdb_options_t* opt, size_t v) {
   opt->rep.hard_pending_compaction_bytes_limit = v;
 }
 
@@ -3181,18 +3625,8 @@ size_t rocksdb_options_get_hard_pending_compaction_bytes_limit(
   return opt->rep.hard_pending_compaction_bytes_limit;
 }
 
-void rocksdb_options_set_rate_limit_delay_max_milliseconds(
-    rocksdb_options_t* opt, unsigned int v) {
-  opt->rep.rate_limit_delay_max_milliseconds = v;
-}
-
-unsigned int rocksdb_options_get_rate_limit_delay_max_milliseconds(
-    rocksdb_options_t* opt) {
-  return opt->rep.rate_limit_delay_max_milliseconds;
-}
-
-void rocksdb_options_set_max_manifest_file_size(
-    rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_max_manifest_file_size(rocksdb_options_t* opt,
+                                                size_t v) {
   opt->rep.max_manifest_file_size = v;
 }
 
@@ -3200,8 +3634,8 @@ size_t rocksdb_options_get_max_manifest_file_size(rocksdb_options_t* opt) {
   return opt->rep.max_manifest_file_size;
 }
 
-void rocksdb_options_set_table_cache_numshardbits(
-    rocksdb_options_t* opt, int v) {
+void rocksdb_options_set_table_cache_numshardbits(rocksdb_options_t* opt,
+                                                  int v) {
   opt->rep.table_cache_numshardbits = v;
 }
 
@@ -3209,13 +3643,7 @@ int rocksdb_options_get_table_cache_numshardbits(rocksdb_options_t* opt) {
   return opt->rep.table_cache_numshardbits;
 }
 
-void rocksdb_options_set_table_cache_remove_scan_count_limit(
-    rocksdb_options_t* /*opt*/, int /*v*/) {
-  // this option is deprecated
-}
-
-void rocksdb_options_set_arena_block_size(
-    rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_arena_block_size(rocksdb_options_t* opt, size_t v) {
   opt->rep.arena_block_size = v;
 }
 
@@ -3223,7 +3651,8 @@ size_t rocksdb_options_get_arena_block_size(rocksdb_options_t* opt) {
   return opt->rep.arena_block_size;
 }
 
-void rocksdb_options_set_disable_auto_compactions(rocksdb_options_t* opt, int disable) {
+void rocksdb_options_set_disable_auto_compactions(rocksdb_options_t* opt,
+                                                  int disable) {
   opt->rep.disable_auto_compactions = disable;
 }
 
@@ -3232,7 +3661,8 @@ unsigned char rocksdb_options_get_disable_auto_compactions(
   return opt->rep.disable_auto_compactions;
 }
 
-void rocksdb_options_set_optimize_filters_for_hits(rocksdb_options_t* opt, int v) {
+void rocksdb_options_set_optimize_filters_for_hits(rocksdb_options_t* opt,
+                                                   int v) {
   opt->rep.optimize_filters_for_hits = v;
 }
 
@@ -3255,7 +3685,7 @@ void rocksdb_options_prepare_for_bulk_load(rocksdb_options_t* opt) {
   opt->rep.PrepareForBulkLoad();
 }
 
-void rocksdb_options_set_memtable_vector_rep(rocksdb_options_t *opt) {
+void rocksdb_options_set_memtable_vector_rep(rocksdb_options_topt) {
   opt->rep.memtable_factory.reset(new ROCKSDB_NAMESPACE::VectorRepFactory);
 }
 
@@ -3278,24 +3708,27 @@ size_t rocksdb_options_get_memtable_huge_page_size(rocksdb_options_t* opt) {
   return opt->rep.memtable_huge_page_size;
 }
 
-void rocksdb_options_set_hash_skip_list_rep(
-    rocksdb_options_t *opt, size_t bucket_count,
-    int32_t skiplist_height, int32_t skiplist_branching_factor) {
+void rocksdb_options_set_hash_skip_list_rep(rocksdb_options_t* opt,
+                                            size_t bucket_count,
+                                            int32_t skiplist_height,
+                                            int32_t skiplist_branching_factor) {
   ROCKSDB_NAMESPACE::MemTableRepFactory* factory =
       ROCKSDB_NAMESPACE::NewHashSkipListRepFactory(
           bucket_count, skiplist_height, skiplist_branching_factor);
   opt->rep.memtable_factory.reset(factory);
 }
 
-void rocksdb_options_set_hash_link_list_rep(
-    rocksdb_options_t *opt, size_t bucket_count) {
+void rocksdb_options_set_hash_link_list_rep(rocksdb_options_t* opt,
+                                            size_t bucket_count) {
   opt->rep.memtable_factory.reset(
       ROCKSDB_NAMESPACE::NewHashLinkListRepFactory(bucket_count));
 }
 
-void rocksdb_options_set_plain_table_factory(
-    rocksdb_options_t *opt, uint32_t user_key_len, int bloom_bits_per_key,
-    double hash_table_ratio, size_t index_sparseness) {
+void rocksdb_options_set_plain_table_factory(rocksdb_options_t* opt,
+                                             uint32_t user_key_len,
+                                             int bloom_bits_per_key,
+                                             double hash_table_ratio,
+                                             size_t index_sparseness) {
   ROCKSDB_NAMESPACE::PlainTableOptions options;
   options.user_key_len = user_key_len;
   options.bloom_bits_per_key = bloom_bits_per_key;
@@ -3307,8 +3740,8 @@ void rocksdb_options_set_plain_table_factory(
   opt->rep.table_factory.reset(factory);
 }
 
-void rocksdb_options_set_max_successive_merges(
-    rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_max_successive_merges(rocksdb_options_t* opt,
+                                               size_t v) {
   opt->rep.max_successive_merges = v;
 }
 
@@ -3316,8 +3749,7 @@ size_t rocksdb_options_get_max_successive_merges(rocksdb_options_t* opt) {
   return opt->rep.max_successive_merges;
 }
 
-void rocksdb_options_set_bloom_locality(
-    rocksdb_options_t* opt, uint32_t v) {
+void rocksdb_options_set_bloom_locality(rocksdb_options_t* opt, uint32_t v) {
   opt->rep.bloom_locality = v;
 }
 
@@ -3325,8 +3757,8 @@ uint32_t rocksdb_options_get_bloom_locality(rocksdb_options_t* opt) {
   return opt->rep.bloom_locality;
 }
 
-void rocksdb_options_set_inplace_update_support(
-    rocksdb_options_t* opt, unsigned char v) {
+void rocksdb_options_set_inplace_update_support(rocksdb_options_t* opt,
+                                                unsigned char v) {
   opt->rep.inplace_update_support = v;
 }
 
@@ -3335,8 +3767,8 @@ unsigned char rocksdb_options_get_inplace_update_support(
   return opt->rep.inplace_update_support;
 }
 
-void rocksdb_options_set_inplace_update_num_locks(
-    rocksdb_options_t* opt, size_t v) {
+void rocksdb_options_set_inplace_update_num_locks(rocksdb_options_t* opt,
+                                                  size_t v) {
   opt->rep.inplace_update_num_locks = v;
 }
 
@@ -3344,8 +3776,7 @@ size_t rocksdb_options_get_inplace_update_num_locks(rocksdb_options_t* opt) {
   return opt->rep.inplace_update_num_locks;
 }
 
-void rocksdb_options_set_report_bg_io_stats(
-    rocksdb_options_t* opt, int v) {
+void rocksdb_options_set_report_bg_io_stats(rocksdb_options_t* opt, int v) {
   opt->rep.report_bg_io_stats = v;
 }
 
@@ -3353,7 +3784,7 @@ unsigned char rocksdb_options_get_report_bg_io_stats(rocksdb_options_t* opt) {
   return opt->rep.report_bg_io_stats;
 }
 
-void rocksdb_options_set_compaction_style(rocksdb_options_t *opt, int style) {
+void rocksdb_options_set_compaction_style(rocksdb_options_topt, int style) {
   opt->rep.compaction_style =
       static_cast<ROCKSDB_NAMESPACE::CompactionStyle>(style);
 }
@@ -3362,17 +3793,17 @@ int rocksdb_options_get_compaction_style(rocksdb_options_t* opt) {
   return opt->rep.compaction_style;
 }
 
-void rocksdb_options_set_universal_compaction_options(rocksdb_options_t *opt, rocksdb_universal_compaction_options_t *uco) {
+void rocksdb_options_set_universal_compaction_options(
+    rocksdb_options_t* opt, rocksdb_universal_compaction_options_t* uco) {
   opt->rep.compaction_options_universal = *(uco->rep);
 }
 
 void rocksdb_options_set_fifo_compaction_options(
-    rocksdb_options_t* opt,
-    rocksdb_fifo_compaction_options_t* fifo) {
+    rocksdb_options_t* opt, rocksdb_fifo_compaction_options_t* fifo) {
   opt->rep.compaction_options_fifo = fifo->rep;
 }
 
-char *rocksdb_options_statistics_get_string(rocksdb_options_t *opt) {
+char* rocksdb_options_statistics_get_string(rocksdb_options_t* opt) {
   ROCKSDB_NAMESPACE::Statistics* statistics = opt->rep.statistics.get();
   if (statistics) {
     return strdup(statistics->ToString().c_str());
@@ -3380,7 +3811,8 @@ char *rocksdb_options_statistics_get_string(rocksdb_options_t *opt) {
   return nullptr;
 }
 
-void rocksdb_options_set_ratelimiter(rocksdb_options_t *opt, rocksdb_ratelimiter_t *limiter) {
+void rocksdb_options_set_ratelimiter(rocksdb_options_t* opt,
+                                     rocksdb_ratelimiter_t* limiter) {
   if (limiter) {
     opt->rep.rate_limiter = limiter->rep;
   }
@@ -3395,27 +3827,51 @@ unsigned char rocksdb_options_get_atomic_flush(rocksdb_options_t* opt) {
   return opt->rep.atomic_flush;
 }
 
-rocksdb_ratelimiter_t* rocksdb_ratelimiter_create(
-    int64_t rate_bytes_per_sec,
-    int64_t refill_period_us,
-    int32_t fairness) {
+void rocksdb_options_set_manual_wal_flush(rocksdb_options_t* opt,
+                                          unsigned char manual_wal_flush) {
+  opt->rep.manual_wal_flush = manual_wal_flush;
+}
+
+unsigned char rocksdb_options_get_manual_wal_flush(rocksdb_options_t* opt) {
+  return opt->rep.manual_wal_flush;
+}
+
+void rocksdb_options_set_wal_compression(rocksdb_options_t* opt, int val) {
+  opt->rep.wal_compression = static_cast<CompressionType>(val);
+}
+
+int rocksdb_options_get_wal_compression(rocksdb_options_t* opt) {
+  return opt->rep.wal_compression;
+}
+
+rocksdb_ratelimiter_t* rocksdb_ratelimiter_create(int64_t rate_bytes_per_sec,
+                                                  int64_t refill_period_us,
+                                                  int32_t fairness) {
   rocksdb_ratelimiter_t* rate_limiter = new rocksdb_ratelimiter_t;
   rate_limiter->rep.reset(
-               NewGenericRateLimiter(rate_bytes_per_sec,
-                                     refill_period_us, fairness));
+      NewGenericRateLimiter(rate_bytes_per_sec, refill_period_us, fairness));
   return rate_limiter;
 }
 
-void rocksdb_ratelimiter_destroy(rocksdb_ratelimiter_t *limiter) {
+void rocksdb_ratelimiter_destroy(rocksdb_ratelimiter_tlimiter) {
   delete limiter;
 }
 
-void rocksdb_options_set_row_cache(rocksdb_options_t* opt, rocksdb_cache_t* cache) {
-  if(cache) {
+void rocksdb_options_set_row_cache(rocksdb_options_t* opt,
+                                   rocksdb_cache_t* cache) {
+  if (cache) {
     opt->rep.row_cache = cache->rep;
   }
 }
 
+void rocksdb_options_add_compact_on_deletion_collector_factory(
+    rocksdb_options_t* opt, size_t window_size, size_t num_dels_trigger) {
+  std::shared_ptr<ROCKSDB_NAMESPACE::TablePropertiesCollectorFactory>
+      compact_on_del =
+          NewCompactOnDeletionCollectorFactory(window_size, num_dels_trigger);
+  opt->rep.table_properties_collector_factories.emplace_back(compact_on_del);
+}
+
 void rocksdb_set_perf_level(int v) {
   PerfLevel level = static_cast<PerfLevel>(v);
   SetPerfLevel(level);
@@ -3432,12 +3888,12 @@ void rocksdb_perfcontext_reset(rocksdb_perfcontext_t* context) {
 }
 
 char* rocksdb_perfcontext_report(rocksdb_perfcontext_t* context,
-    unsigned char exclude_zero_counters) {
+                                 unsigned char exclude_zero_counters) {
   return strdup(context->rep->ToString(exclude_zero_counters).c_str());
 }
 
 uint64_t rocksdb_perfcontext_metric(rocksdb_perfcontext_t* context,
-    int metric) {
+                                    int metric) {
   PerfContext* rep = context->rep;
   switch (metric) {
     case rocksdb_user_key_comparison_count:
@@ -3576,6 +4032,22 @@ uint64_t rocksdb_perfcontext_metric(rocksdb_perfcontext_t* context,
       return rep->env_unlock_file_nanos;
     case rocksdb_env_new_logger_nanos:
       return rep->env_new_logger_nanos;
+    case rocksdb_number_async_seek:
+      return rep->number_async_seek;
+    case rocksdb_blob_cache_hit_count:
+      return rep->blob_cache_hit_count;
+    case rocksdb_blob_read_count:
+      return rep->blob_read_count;
+    case rocksdb_blob_read_byte:
+      return rep->blob_read_byte;
+    case rocksdb_blob_read_time:
+      return rep->blob_read_time;
+    case rocksdb_blob_checksum_time:
+      return rep->blob_checksum_time;
+    case rocksdb_blob_decompress_time:
+      return rep->blob_decompress_time;
+    case rocksdb_internal_range_del_reseek_count:
+      return rep->internal_range_del_reseek_count;
     default:
       break;
   }
@@ -3601,15 +4073,12 @@ table_properties_collectors
 */
 
 rocksdb_compactionfilter_t* rocksdb_compactionfilter_create(
-    void* state,
-    void (*destructor)(void*),
-    unsigned char (*filter)(
-        void*,
-        int level,
-        const char* key, size_t key_length,
-        const char* existing_value, size_t value_length,
-        char** new_value, size_t *new_value_length,
-        unsigned char* value_changed),
+    void* state, void (*destructor)(void*),
+    unsigned char (*filter)(void*, int level, const char* key,
+                            size_t key_length, const char* existing_value,
+                            size_t value_length, char** new_value,
+                            size_t* new_value_length,
+                            unsigned char* value_changed),
     const char* (*name)(void*)) {
   rocksdb_compactionfilter_t* result = new rocksdb_compactionfilter_t;
   result->state_ = state;
@@ -3621,8 +4090,7 @@ rocksdb_compactionfilter_t* rocksdb_compactionfilter_create(
 }
 
 void rocksdb_compactionfilter_set_ignore_snapshots(
-  rocksdb_compactionfilter_t* filter,
-  unsigned char whether_ignore) {
+    rocksdb_compactionfilter_t* filter, unsigned char whether_ignore) {
   filter->ignore_snapshots_ = whether_ignore;
 }
 
@@ -3660,47 +4128,38 @@ void rocksdb_compactionfilterfactory_destroy(
 }
 
 rocksdb_comparator_t* rocksdb_comparator_create(
-    void* state,
-    void (*destructor)(void*),
-    int (*compare)(
-        void*,
-        const char* a, size_t alen,
-        const char* b, size_t blen),
+    void* state, void (*destructor)(void*),
+    int (*compare)(void*, const char* a, size_t alen, const char* b,
+                   size_t blen),
     const char* (*name)(void*)) {
   rocksdb_comparator_t* result = new rocksdb_comparator_t;
   result->state_ = state;
   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;
-}
-
-rocksdb_filterpolicy_t* rocksdb_filterpolicy_create(
-    void* state,
-    void (*destructor)(void*),
-    char* (*create_filter)(
-        void*,
-        const char* const* key_array, const size_t* key_length_array,
-        int num_keys,
-        size_t* filter_length),
-    unsigned char (*key_may_match)(
-        void*,
-        const char* key, size_t length,
-        const char* filter, size_t filter_length),
-    void (*delete_filter)(
-        void*,
-        const char* filter, size_t filter_length),
-    const char* (*name)(void*)) {
-  rocksdb_filterpolicy_t* result = new rocksdb_filterpolicy_t;
+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->create_ = create_filter;
-  result->key_match_ = key_may_match;
-  result->delete_filter_ = delete_filter;
+  result->compare_ = compare;
+  result->compare_ts_ = compare_ts;
+  result->compare_without_ts_ = compare_without_ts;
   result->name_ = name;
   return result;
 }
@@ -3709,7 +4168,8 @@ void rocksdb_filterpolicy_destroy(rocksdb_filterpolicy_t* filter) {
   delete filter;
 }
 
-rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom_format(int bits_per_key, bool original_format) {
+rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom_format(
+    double bits_per_key, bool original_format) {
   // Make a rocksdb_filterpolicy_t, but override all of its methods so
   // they delegate to a NewBloomFilterPolicy() instead of user
   // supplied C functions.
@@ -3717,12 +4177,8 @@ rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom_format(int bits_per_ke
     const FilterPolicy* rep_;
     ~Wrapper() override { delete rep_; }
     const char* Name() const override { return rep_->Name(); }
-    void CreateFilter(const Slice* keys, int n,
-                      std::string* dst) const override {
-      return rep_->CreateFilter(keys, n, dst);
-    }
-    bool KeyMayMatch(const Slice& key, const Slice& filter) const override {
-      return rep_->KeyMayMatch(key, filter);
+    const char* CompatibilityName() const override {
+      return rep_->CompatibilityName();
     }
     // No need to override GetFilterBitsBuilder if this one is overridden
     ROCKSDB_NAMESPACE::FilterBitsBuilder* GetBuilderWithContext(
@@ -3739,19 +4195,62 @@ rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom_format(int bits_per_ke
   Wrapper* wrapper = new Wrapper;
   wrapper->rep_ = NewBloomFilterPolicy(bits_per_key, original_format);
   wrapper->state_ = nullptr;
-  wrapper->delete_filter_ = nullptr;
   wrapper->destructor_ = &Wrapper::DoNothing;
   return wrapper;
 }
 
-rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom_full(int bits_per_key) {
+rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom_full(
+    double bits_per_key) {
   return rocksdb_filterpolicy_create_bloom_format(bits_per_key, false);
 }
 
-rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom(int bits_per_key) {
+rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_bloom(double bits_per_key) {
   return rocksdb_filterpolicy_create_bloom_format(bits_per_key, true);
 }
 
+rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_ribbon_format(
+    double bloom_equivalent_bits_per_key, int bloom_before_level) {
+  // Make a rocksdb_filterpolicy_t, but override all of its methods so
+  // they delegate to a NewRibbonFilterPolicy() instead of user
+  // supplied C functions.
+  struct Wrapper : public rocksdb_filterpolicy_t {
+    const FilterPolicy* rep_;
+    ~Wrapper() override { delete rep_; }
+    const char* Name() const override { return rep_->Name(); }
+    const char* CompatibilityName() const override {
+      return rep_->CompatibilityName();
+    }
+    ROCKSDB_NAMESPACE::FilterBitsBuilder* GetBuilderWithContext(
+        const ROCKSDB_NAMESPACE::FilterBuildingContext& context)
+        const override {
+      return rep_->GetBuilderWithContext(context);
+    }
+    ROCKSDB_NAMESPACE::FilterBitsReader* GetFilterBitsReader(
+        const Slice& contents) const override {
+      return rep_->GetFilterBitsReader(contents);
+    }
+    static void DoNothing(void*) {}
+  };
+  Wrapper* wrapper = new Wrapper;
+  wrapper->rep_ =
+      NewRibbonFilterPolicy(bloom_equivalent_bits_per_key, bloom_before_level);
+  wrapper->state_ = nullptr;
+  wrapper->destructor_ = &Wrapper::DoNothing;
+  return wrapper;
+}
+
+rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_ribbon(
+    double bloom_equivalent_bits_per_key) {
+  return rocksdb_filterpolicy_create_ribbon_format(
+      bloom_equivalent_bits_per_key, /*bloom_before_level = disabled*/ -1);
+}
+
+rocksdb_filterpolicy_t* rocksdb_filterpolicy_create_ribbon_hybrid(
+    double bloom_equivalent_bits_per_key, int bloom_before_level) {
+  return rocksdb_filterpolicy_create_ribbon_format(
+      bloom_equivalent_bits_per_key, bloom_before_level);
+}
+
 rocksdb_mergeoperator_t* rocksdb_mergeoperator_create(
     void* state, void (*destructor)(void*),
     char* (*full_merge)(void*, const char* key, size_t key_length,
@@ -3784,13 +4283,10 @@ rocksdb_readoptions_t* rocksdb_readoptions_create() {
   return new rocksdb_readoptions_t;
 }
 
-void rocksdb_readoptions_destroy(rocksdb_readoptions_t* opt) {
-  delete opt;
-}
+void rocksdb_readoptions_destroy(rocksdb_readoptions_t* opt) { delete opt; }
 
-void rocksdb_readoptions_set_verify_checksums(
-    rocksdb_readoptions_t* opt,
-    unsigned char v) {
+void rocksdb_readoptions_set_verify_checksums(rocksdb_readoptions_t* opt,
+                                              unsigned char v) {
   opt->rep.verify_checksums = v;
 }
 
@@ -3799,8 +4295,8 @@ unsigned char rocksdb_readoptions_get_verify_checksums(
   return opt->rep.verify_checksums;
 }
 
-void rocksdb_readoptions_set_fill_cache(
-    rocksdb_readoptions_t* opt, unsigned char v) {
+void rocksdb_readoptions_set_fill_cache(rocksdb_readoptions_t* opt,
+                                        unsigned char v) {
   opt->rep.fill_cache = v;
 }
 
@@ -3808,15 +4304,14 @@ unsigned char rocksdb_readoptions_get_fill_cache(rocksdb_readoptions_t* opt) {
   return opt->rep.fill_cache;
 }
 
-void rocksdb_readoptions_set_snapshot(
-    rocksdb_readoptions_t* opt,
-    const rocksdb_snapshot_t* snap) {
+void rocksdb_readoptions_set_snapshot(rocksdb_readoptions_t* opt,
+                                      const rocksdb_snapshot_t* snap) {
   opt->rep.snapshot = (snap ? snap->rep : nullptr);
 }
 
-void rocksdb_readoptions_set_iterate_upper_bound(
-    rocksdb_readoptions_t* opt,
-    const char* key, size_t keylen) {
+void rocksdb_readoptions_set_iterate_upper_bound(rocksdb_readoptions_t* opt,
+                                                 const char* key,
+                                                 size_t keylen) {
   if (key == nullptr) {
     opt->upper_bound = Slice();
     opt->rep.iterate_upper_bound = nullptr;
@@ -3827,9 +4322,9 @@ void rocksdb_readoptions_set_iterate_upper_bound(
   }
 }
 
-void rocksdb_readoptions_set_iterate_lower_bound(
-    rocksdb_readoptions_t *opt,
-    const char* key, size_t keylen) {
+void rocksdb_readoptions_set_iterate_lower_bound(rocksdb_readoptions_t* opt,
+                                                 const char* key,
+                                                 size_t keylen) {
   if (key == nullptr) {
     opt->lower_bound = Slice();
     opt->rep.iterate_lower_bound = nullptr;
@@ -3839,8 +4334,7 @@ void rocksdb_readoptions_set_iterate_lower_bound(
   }
 }
 
-void rocksdb_readoptions_set_read_tier(
-    rocksdb_readoptions_t* opt, int v) {
+void rocksdb_readoptions_set_read_tier(rocksdb_readoptions_t* opt, int v) {
   opt->rep.read_tier = static_cast<ROCKSDB_NAMESPACE::ReadTier>(v);
 }
 
@@ -3848,8 +4342,8 @@ int rocksdb_readoptions_get_read_tier(rocksdb_readoptions_t* opt) {
   return static_cast<int>(opt->rep.read_tier);
 }
 
-void rocksdb_readoptions_set_tailing(
-    rocksdb_readoptions_t* opt, unsigned char v) {
+void rocksdb_readoptions_set_tailing(rocksdb_readoptions_t* opt,
+                                     unsigned char v) {
   opt->rep.tailing = v;
 }
 
@@ -3857,13 +4351,13 @@ unsigned char rocksdb_readoptions_get_tailing(rocksdb_readoptions_t* opt) {
   return opt->rep.tailing;
 }
 
-void rocksdb_readoptions_set_managed(
-    rocksdb_readoptions_t* opt, unsigned char v) {
+void rocksdb_readoptions_set_managed(rocksdb_readoptions_t* opt,
+                                     unsigned char v) {
   opt->rep.managed = v;
 }
 
-void rocksdb_readoptions_set_readahead_size(
-    rocksdb_readoptions_t* opt, size_t v) {
+void rocksdb_readoptions_set_readahead_size(rocksdb_readoptions_t* opt,
+                                            size_t v) {
   opt->rep.readahead_size = v;
 }
 
@@ -3871,8 +4365,8 @@ size_t rocksdb_readoptions_get_readahead_size(rocksdb_readoptions_t* opt) {
   return opt->rep.readahead_size;
 }
 
-void rocksdb_readoptions_set_prefix_same_as_start(
-    rocksdb_readoptions_t* opt, unsigned char v) {
+void rocksdb_readoptions_set_prefix_same_as_start(rocksdb_readoptions_t* opt,
+                                                  unsigned char v) {
   opt->rep.prefix_same_as_start = v;
 }
 
@@ -3901,8 +4395,7 @@ unsigned char rocksdb_readoptions_get_total_order_seek(
 }
 
 void rocksdb_readoptions_set_max_skippable_internal_keys(
-    rocksdb_readoptions_t* opt,
-    uint64_t v) {
+    rocksdb_readoptions_t* opt, uint64_t v) {
   opt->rep.max_skippable_internal_keys = v;
 }
 
@@ -3921,8 +4414,8 @@ unsigned char rocksdb_readoptions_get_background_purge_on_iterator_cleanup(
   return opt->rep.background_purge_on_iterator_cleanup;
 }
 
-void rocksdb_readoptions_set_ignore_range_deletions(
-    rocksdb_readoptions_t* opt, unsigned char v) {
+void rocksdb_readoptions_set_ignore_range_deletions(rocksdb_readoptions_t* opt,
+                                                    unsigned char v) {
   opt->rep.ignore_range_deletions = v;
 }
 
@@ -3931,16 +4424,55 @@ unsigned char rocksdb_readoptions_get_ignore_range_deletions(
   return opt->rep.ignore_range_deletions;
 }
 
+void rocksdb_readoptions_set_deadline(rocksdb_readoptions_t* opt,
+                                      uint64_t microseconds) {
+  opt->rep.deadline = std::chrono::microseconds(microseconds);
+}
+
+uint64_t rocksdb_readoptions_get_deadline(rocksdb_readoptions_t* opt) {
+  return opt->rep.deadline.count();
+}
+
+void rocksdb_readoptions_set_io_timeout(rocksdb_readoptions_t* opt,
+                                        uint64_t microseconds) {
+  opt->rep.io_timeout = std::chrono::microseconds(microseconds);
+}
+
+extern ROCKSDB_LIBRARY_API uint64_t
+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;
 }
 
-void rocksdb_writeoptions_destroy(rocksdb_writeoptions_t* opt) {
-  delete opt;
-}
+void rocksdb_writeoptions_destroy(rocksdb_writeoptions_t* opt) { delete opt; }
 
-void rocksdb_writeoptions_set_sync(
-    rocksdb_writeoptions_t* opt, unsigned char v) {
+void rocksdb_writeoptions_set_sync(rocksdb_writeoptions_t* opt,
+                                   unsigned char v) {
   opt->rep.sync = v;
 }
 
@@ -3948,7 +4480,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;
 }
 
@@ -3958,8 +4491,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;
 }
 
@@ -3968,9 +4500,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;
 }
 
@@ -3979,9 +4510,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;
 }
 
@@ -4009,7 +4539,8 @@ void rocksdb_compactoptions_destroy(rocksdb_compactoptions_t* opt) {
 
 void rocksdb_compactoptions_set_bottommost_level_compaction(
     rocksdb_compactoptions_t* opt, unsigned char v) {
-  opt->rep.bottommost_level_compaction = static_cast<BottommostLevelCompaction>(v);
+  opt->rep.bottommost_level_compaction =
+      static_cast<BottommostLevelCompaction>(v);
 }
 
 unsigned char rocksdb_compactoptions_get_bottommost_level_compaction(
@@ -4046,16 +4577,25 @@ 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;
 }
 
-void rocksdb_flushoptions_destroy(rocksdb_flushoptions_t* opt) {
-  delete opt;
-}
+void rocksdb_flushoptions_destroy(rocksdb_flushoptions_t* opt) { delete opt; }
 
-void rocksdb_flushoptions_set_wait(
-    rocksdb_flushoptions_t* opt, unsigned char v) {
+void rocksdb_flushoptions_set_wait(rocksdb_flushoptions_t* opt,
+                                   unsigned char v) {
   opt->rep.wait = v;
 }
 
@@ -4063,14 +4603,67 @@ unsigned char rocksdb_flushoptions_get_wait(rocksdb_flushoptions_t* opt) {
   return opt->rep.wait;
 }
 
+rocksdb_memory_allocator_t* rocksdb_jemalloc_nodump_allocator_create(
+    char** errptr) {
+  rocksdb_memory_allocator_t* allocator = new rocksdb_memory_allocator_t;
+  ROCKSDB_NAMESPACE::JemallocAllocatorOptions options;
+  SaveError(errptr, ROCKSDB_NAMESPACE::NewJemallocNodumpAllocator(
+                        options, &allocator->rep));
+  return allocator;
+}
+
+void rocksdb_memory_allocator_destroy(rocksdb_memory_allocator_t* allocator) {
+  delete allocator;
+}
+
+rocksdb_lru_cache_options_t* rocksdb_lru_cache_options_create() {
+  return new rocksdb_lru_cache_options_t;
+}
+
+void rocksdb_lru_cache_options_destroy(rocksdb_lru_cache_options_t* opt) {
+  delete opt;
+}
+
+void rocksdb_lru_cache_options_set_capacity(rocksdb_lru_cache_options_t* opt,
+                                            size_t capacity) {
+  opt->rep.capacity = capacity;
+}
+
+void rocksdb_lru_cache_options_set_num_shard_bits(
+    rocksdb_lru_cache_options_t* opt, int num_shard_bits) {
+  opt->rep.num_shard_bits = num_shard_bits;
+}
+
+void rocksdb_lru_cache_options_set_memory_allocator(
+    rocksdb_lru_cache_options_t* opt, rocksdb_memory_allocator_t* allocator) {
+  opt->rep.memory_allocator = allocator->rep;
+}
+
 rocksdb_cache_t* rocksdb_cache_create_lru(size_t capacity) {
   rocksdb_cache_t* c = new rocksdb_cache_t;
   c->rep = NewLRUCache(capacity);
   return c;
 }
 
-void rocksdb_cache_destroy(rocksdb_cache_t* cache) {
-  delete cache;
+rocksdb_cache_t* rocksdb_cache_create_lru_with_strict_capacity_limit(
+    size_t capacity) {
+  rocksdb_cache_t* c = new rocksdb_cache_t;
+  c->rep = NewLRUCache(capacity);
+  c->rep->SetStrictCapacityLimit(true);
+  return c;
+}
+
+rocksdb_cache_t* rocksdb_cache_create_lru_opts(
+    rocksdb_lru_cache_options_t* opt) {
+  rocksdb_cache_t* c = new rocksdb_cache_t;
+  c->rep = NewLRUCache(opt->rep);
+  return c;
+}
+
+void rocksdb_cache_destroy(rocksdb_cache_t* cache) { delete cache; }
+
+void rocksdb_cache_disown_data(rocksdb_cache_t* cache) {
+  cache->rep->DisownData();
 }
 
 void rocksdb_cache_set_capacity(rocksdb_cache_t* cache, size_t capacity) {
@@ -4089,16 +4682,15 @@ size_t rocksdb_cache_get_pinned_usage(rocksdb_cache_t* cache) {
   return cache->rep->GetPinnedUsage();
 }
 
-rocksdb_dbpath_t* rocksdb_dbpath_create(const char* path, uint64_t target_size) {
+rocksdb_dbpath_t* rocksdb_dbpath_create(const char* path,
+                                        uint64_t target_size) {
   rocksdb_dbpath_t* result = new rocksdb_dbpath_t;
   result->rep.path = std::string(path);
   result->rep.target_size = target_size;
   return result;
 }
 
-void rocksdb_dbpath_destroy(rocksdb_dbpath_t* dbpath) {
-  delete dbpath;
-}
+void rocksdb_dbpath_destroy(rocksdb_dbpath_t* dbpath) { delete dbpath; }
 
 rocksdb_env_t* rocksdb_create_default_env() {
   rocksdb_env_t* result = new rocksdb_env_t;
@@ -4131,7 +4723,8 @@ int rocksdb_env_get_bottom_priority_background_threads(rocksdb_env_t* env) {
   return env->rep->GetBackgroundThreads(Env::BOTTOM);
 }
 
-void rocksdb_env_set_high_priority_background_threads(rocksdb_env_t* env, int n) {
+void rocksdb_env_set_high_priority_background_threads(rocksdb_env_t* env,
+                                                      int n) {
   env->rep->SetBackgroundThreads(n, Env::HIGH);
 }
 
@@ -4156,7 +4749,8 @@ void rocksdb_env_lower_thread_pool_io_priority(rocksdb_env_t* env) {
   env->rep->LowerThreadPoolIOPriority();
 }
 
-void rocksdb_env_lower_high_priority_thread_pool_io_priority(rocksdb_env_t* env) {
+void rocksdb_env_lower_high_priority_thread_pool_io_priority(
+    rocksdb_env_t* env) {
   env->rep->LowerThreadPoolIOPriority(Env::HIGH);
 }
 
@@ -4164,7 +4758,8 @@ void rocksdb_env_lower_thread_pool_cpu_priority(rocksdb_env_t* env) {
   env->rep->LowerThreadPoolCPUPriority();
 }
 
-void rocksdb_env_lower_high_priority_thread_pool_cpu_priority(rocksdb_env_t* env) {
+void rocksdb_env_lower_high_priority_thread_pool_cpu_priority(
+    rocksdb_env_t* env) {
   env->rep->LowerThreadPoolCPUPriority(Env::HIGH);
 }
 
@@ -4187,6 +4782,11 @@ rocksdb_sstfilewriter_t* rocksdb_sstfilewriter_create(
   return writer;
 }
 
+void rocksdb_create_dir_if_missing(rocksdb_env_t* env, const char* path,
+                                   char** errptr) {
+  SaveError(errptr, env->rep->CreateDirIfMissing(std::string(path)));
+}
+
 rocksdb_sstfilewriter_t* rocksdb_sstfilewriter_create_with_comparator(
     const rocksdb_envoptions_t* env, const rocksdb_options_t* io_options,
     const rocksdb_comparator_t* /*comparator*/) {
@@ -4212,6 +4812,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,
@@ -4225,13 +4834,29 @@ 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_delete_range(rocksdb_sstfilewriter_t* writer,
+                                        const char* begin_key,
+                                        size_t begin_keylen,
+                                        const char* end_key, size_t end_keylen,
+                                        char** errptr) {
+  SaveError(errptr, writer->rep->DeleteRange(Slice(begin_key, begin_keylen),
+                                             Slice(end_key, end_keylen)));
+}
+
 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();
 }
 
@@ -4271,8 +4896,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;
 }
 
@@ -4307,18 +4931,11 @@ void rocksdb_try_catch_up_with_primary(rocksdb_t* db, char** errptr) {
 }
 
 rocksdb_slicetransform_t* rocksdb_slicetransform_create(
-    void* state,
-    void (*destructor)(void*),
-    char* (*transform)(
-        void*,
-        const char* key, size_t length,
-        size_t* dst_length),
-    unsigned char (*in_domain)(
-        void*,
-        const char* key, size_t length),
-    unsigned char (*in_range)(
-        void*,
-        const char* key, size_t length),
+    void* state, void (*destructor)(void*),
+    char* (*transform)(void*, const char* key, size_t length,
+                       size_t* dst_length),
+    unsigned char (*in_domain)(void*, const char* key, size_t length),
+    unsigned char (*in_range)(void*, const char* key, size_t length),
     const char* (*name)(void*)) {
   rocksdb_slicetransform_t* result = new rocksdb_slicetransform_t;
   result->state_ = state;
@@ -4330,48 +4947,48 @@ rocksdb_slicetransform_t* rocksdb_slicetransform_create(
   return result;
 }
 
-void rocksdb_slicetransform_destroy(rocksdb_slicetransform_t* st) {
-  delete st;
-}
+void rocksdb_slicetransform_destroy(rocksdb_slicetransform_t* st) { delete st; }
 
-struct Wrapper : public rocksdb_slicetransform_t {
+struct SliceTransformWrapper : public rocksdb_slicetransform_t {
   const SliceTransform* rep_;
-  ~Wrapper() override { delete rep_; }
+  ~SliceTransformWrapper() override { delete rep_; }
   const char* Name() const override { return rep_->Name(); }
+  std::string GetId() const override { return rep_->GetId(); }
   Slice Transform(const Slice& src) const override {
     return rep_->Transform(src);
   }
-  bool InDomain(const Slice& src) const override {
-    return rep_->InDomain(src);
-  }
+  bool InDomain(const Slice& src) const override { return rep_->InDomain(src); }
   bool InRange(const Slice& src) const override { return rep_->InRange(src); }
-  static void DoNothing(void*) { }
+  static void DoNothing(void*) {}
 };
 
-rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(size_t prefixLen) {
-  Wrapper* wrapper = new Wrapper;
+rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(
+    size_t prefixLen) {
+  SliceTransformWrapper* wrapper = new SliceTransformWrapper;
   wrapper->rep_ = ROCKSDB_NAMESPACE::NewFixedPrefixTransform(prefixLen);
   wrapper->state_ = nullptr;
-  wrapper->destructor_ = &Wrapper::DoNothing;
+  wrapper->destructor_ = &SliceTransformWrapper::DoNothing;
   return wrapper;
 }
 
 rocksdb_slicetransform_t* rocksdb_slicetransform_create_noop() {
-  Wrapper* wrapper = new Wrapper;
+  SliceTransformWrapper* wrapper = new SliceTransformWrapper;
   wrapper->rep_ = ROCKSDB_NAMESPACE::NewNoopTransform();
   wrapper->state_ = nullptr;
-  wrapper->destructor_ = &Wrapper::DoNothing;
+  wrapper->destructor_ = &SliceTransformWrapper::DoNothing;
   return wrapper;
 }
 
-rocksdb_universal_compaction_options_t* rocksdb_universal_compaction_options_create() {
-  rocksdb_universal_compaction_options_t* result = new rocksdb_universal_compaction_options_t;
+rocksdb_universal_compaction_options_t*
+rocksdb_universal_compaction_options_create() {
+  rocksdb_universal_compaction_options_t* result =
+      new rocksdb_universal_compaction_options_t;
   result->rep = new ROCKSDB_NAMESPACE::CompactionOptionsUniversal;
   return result;
 }
 
 void rocksdb_universal_compaction_options_set_size_ratio(
-  rocksdb_universal_compaction_options_t* uco, int ratio) {
+    rocksdb_universal_compaction_options_t* uco, int ratio) {
   uco->rep->size_ratio = ratio;
 }
 
@@ -4381,7 +4998,7 @@ int rocksdb_universal_compaction_options_get_size_ratio(
 }
 
 void rocksdb_universal_compaction_options_set_min_merge_width(
-  rocksdb_universal_compaction_options_t* uco, int w) {
+    rocksdb_universal_compaction_options_t* uco, int w) {
   uco->rep->min_merge_width = w;
 }
 
@@ -4391,7 +5008,7 @@ int rocksdb_universal_compaction_options_get_min_merge_width(
 }
 
 void rocksdb_universal_compaction_options_set_max_merge_width(
-  rocksdb_universal_compaction_options_t* uco, int w) {
+    rocksdb_universal_compaction_options_t* uco, int w) {
   uco->rep->max_merge_width = w;
 }
 
@@ -4401,7 +5018,7 @@ int rocksdb_universal_compaction_options_get_max_merge_width(
 }
 
 void rocksdb_universal_compaction_options_set_max_size_amplification_percent(
-  rocksdb_universal_compaction_options_t* uco, int p) {
+    rocksdb_universal_compaction_options_t* uco, int p) {
   uco->rep->max_size_amplification_percent = p;
 }
 
@@ -4411,7 +5028,7 @@ int rocksdb_universal_compaction_options_get_max_size_amplification_percent(
 }
 
 void rocksdb_universal_compaction_options_set_compression_size_percent(
-  rocksdb_universal_compaction_options_t* uco, int p) {
+    rocksdb_universal_compaction_options_t* uco, int p) {
   uco->rep->compression_size_percent = p;
 }
 
@@ -4421,7 +5038,7 @@ int rocksdb_universal_compaction_options_get_compression_size_percent(
 }
 
 void rocksdb_universal_compaction_options_set_stop_style(
-  rocksdb_universal_compaction_options_t* uco, int style) {
+    rocksdb_universal_compaction_options_t* uco, int style) {
   uco->rep->stop_style =
       static_cast<ROCKSDB_NAMESPACE::CompactionStopStyle>(style);
 }
@@ -4432,14 +5049,15 @@ int rocksdb_universal_compaction_options_get_stop_style(
 }
 
 void rocksdb_universal_compaction_options_destroy(
-  rocksdb_universal_compaction_options_t* uco) {
+    rocksdb_universal_compaction_options_t* uco) {
   delete uco->rep;
   delete uco;
 }
 
 rocksdb_fifo_compaction_options_t* rocksdb_fifo_compaction_options_create() {
-  rocksdb_fifo_compaction_options_t* result = new rocksdb_fifo_compaction_options_t;
-  result->rep =  CompactionOptionsFIFO();
+  rocksdb_fifo_compaction_options_t* result =
+      new rocksdb_fifo_compaction_options_t;
+  result->rep = CompactionOptionsFIFO();
   return result;
 }
 
@@ -4458,7 +5076,8 @@ void rocksdb_fifo_compaction_options_destroy(
   delete fifo_opts;
 }
 
-void rocksdb_options_set_min_level_to_compress(rocksdb_options_t* opt, int level) {
+void rocksdb_options_set_min_level_to_compress(rocksdb_options_t* opt,
+                                               int level) {
   if (level >= 0) {
     assert(level <= opt->rep.num_levels);
     opt->rep.compression_per_level.resize(opt->rep.num_levels);
@@ -4471,59 +5090,48 @@ void rocksdb_options_set_min_level_to_compress(rocksdb_options_t* opt, int level
   }
 }
 
-int rocksdb_livefiles_count(
-  const rocksdb_livefiles_t* lf) {
+int rocksdb_livefiles_count(const rocksdb_livefiles_t* lf) {
   return static_cast<int>(lf->rep.size());
 }
 
-const char* rocksdb_livefiles_name(
-  const rocksdb_livefiles_t* lf,
-  int index) {
+const char* rocksdb_livefiles_column_family_name(const rocksdb_livefiles_t* lf,
+                                                 int index) {
+  return lf->rep[index].column_family_name.c_str();
+}
+
+const char* rocksdb_livefiles_name(const rocksdb_livefiles_t* lf, int index) {
   return lf->rep[index].name.c_str();
 }
 
-int rocksdb_livefiles_level(
-  const rocksdb_livefiles_t* lf,
-  int index) {
+int rocksdb_livefiles_level(const rocksdb_livefiles_t* lf, int index) {
   return lf->rep[index].level;
 }
 
-size_t rocksdb_livefiles_size(
-  const rocksdb_livefiles_t* lf,
-  int index) {
+size_t rocksdb_livefiles_size(const rocksdb_livefiles_t* lf, int index) {
   return lf->rep[index].size;
 }
 
-const char* rocksdb_livefiles_smallestkey(
-  const rocksdb_livefiles_t* lf,
-  int index,
-  size_t* size) {
+const char* rocksdb_livefiles_smallestkey(const rocksdb_livefiles_t* lf,
+                                          int index, size_t* size) {
   *size = lf->rep[index].smallestkey.size();
   return lf->rep[index].smallestkey.data();
 }
 
-const char* rocksdb_livefiles_largestkey(
-  const rocksdb_livefiles_t* lf,
-  int index,
-  size_t* size) {
+const char* rocksdb_livefiles_largestkey(const rocksdb_livefiles_t* lf,
+                                         int index, size_t* size) {
   *size = lf->rep[index].largestkey.size();
   return lf->rep[index].largestkey.data();
 }
 
-uint64_t rocksdb_livefiles_entries(
-    const rocksdb_livefiles_t* lf,
-    int index) {
+uint64_t rocksdb_livefiles_entries(const rocksdb_livefiles_t* lf, int index) {
   return lf->rep[index].num_entries;
 }
 
-uint64_t rocksdb_livefiles_deletions(
-    const rocksdb_livefiles_t* lf,
-    int index) {
+uint64_t rocksdb_livefiles_deletions(const rocksdb_livefiles_t* lf, int index) {
   return lf->rep[index].num_deletions;
 }
 
-extern void rocksdb_livefiles_destroy(
-  const rocksdb_livefiles_t* lf) {
+extern void rocksdb_livefiles_destroy(const rocksdb_livefiles_t* lf) {
   delete lf;
 }
 
@@ -4561,11 +5169,125 @@ void rocksdb_delete_file_in_range_cf(
           (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr)));
 }
 
+/* MetaData */
+
+rocksdb_column_family_metadata_t* rocksdb_get_column_family_metadata(
+    rocksdb_t* db) {
+  rocksdb_column_family_metadata_t* meta = new rocksdb_column_family_metadata_t;
+  db->rep->GetColumnFamilyMetaData(&meta->rep);
+  return meta;
+}
+
+rocksdb_column_family_metadata_t* rocksdb_get_column_family_metadata_cf(
+    rocksdb_t* db, rocksdb_column_family_handle_t* column_family) {
+  rocksdb_column_family_metadata_t* meta = new rocksdb_column_family_metadata_t;
+  db->rep->GetColumnFamilyMetaData(column_family->rep, &meta->rep);
+  return meta;
+}
+
+void rocksdb_column_family_metadata_destroy(
+    rocksdb_column_family_metadata_t* cf_meta) {
+  delete cf_meta;
+}
+
+uint64_t rocksdb_column_family_metadata_get_size(
+    rocksdb_column_family_metadata_t* cf_meta) {
+  return cf_meta->rep.size;
+}
+
+size_t rocksdb_column_family_metadata_get_file_count(
+    rocksdb_column_family_metadata_t* cf_meta) {
+  return cf_meta->rep.file_count;
+}
+
+char* rocksdb_column_family_metadata_get_name(
+    rocksdb_column_family_metadata_t* cf_meta) {
+  return strdup(cf_meta->rep.name.c_str());
+}
+
+size_t rocksdb_column_family_metadata_get_level_count(
+    rocksdb_column_family_metadata_t* cf_meta) {
+  return cf_meta->rep.levels.size();
+}
+
+rocksdb_level_metadata_t* rocksdb_column_family_metadata_get_level_metadata(
+    rocksdb_column_family_metadata_t* cf_meta, size_t i) {
+  if (i >= cf_meta->rep.levels.size()) {
+    return NULL;
+  }
+  rocksdb_level_metadata_t* level_meta =
+      (rocksdb_level_metadata_t*)malloc(sizeof(rocksdb_level_metadata_t));
+  level_meta->rep = &cf_meta->rep.levels[i];
+
+  return level_meta;
+}
+
+void rocksdb_level_metadata_destroy(rocksdb_level_metadata_t* level_meta) {
+  // Only free the base pointer as its parent rocksdb_column_family_metadata_t
+  // has the ownership of its rep.
+  free(level_meta);
+}
+
+int rocksdb_level_metadata_get_level(rocksdb_level_metadata_t* level_meta) {
+  return level_meta->rep->level;
+}
+
+uint64_t rocksdb_level_metadata_get_size(rocksdb_level_metadata_t* level_meta) {
+  return level_meta->rep->size;
+}
+
+size_t rocksdb_level_metadata_get_file_count(
+    rocksdb_level_metadata_t* level_meta) {
+  return level_meta->rep->files.size();
+}
+
+rocksdb_sst_file_metadata_t* rocksdb_level_metadata_get_sst_file_metadata(
+    rocksdb_level_metadata_t* level_meta, size_t i) {
+  if (i >= level_meta->rep->files.size()) {
+    return nullptr;
+  }
+  rocksdb_sst_file_metadata_t* file_meta =
+      (rocksdb_sst_file_metadata_t*)malloc(sizeof(rocksdb_sst_file_metadata_t));
+  file_meta->rep = &level_meta->rep->files[i];
+  return file_meta;
+}
+
+void rocksdb_sst_file_metadata_destroy(rocksdb_sst_file_metadata_t* file_meta) {
+  // Only free the base pointer as its parent rocksdb_level_metadata_t
+  // has the ownership of its rep.
+  free(file_meta);
+}
+
+char* rocksdb_sst_file_metadata_get_relative_filename(
+    rocksdb_sst_file_metadata_t* file_meta) {
+  return strdup(file_meta->rep->relative_filename.c_str());
+}
+
+uint64_t rocksdb_sst_file_metadata_get_size(
+    rocksdb_sst_file_metadata_t* file_meta) {
+  return file_meta->rep->size;
+}
+
+char* rocksdb_sst_file_metadata_get_smallestkey(
+    rocksdb_sst_file_metadata_t* file_meta, size_t* key_len) {
+  *key_len = file_meta->rep->smallestkey.size();
+  return CopyString(file_meta->rep->smallestkey);
+}
+
+char* rocksdb_sst_file_metadata_get_largestkey(
+    rocksdb_sst_file_metadata_t* file_meta, size_t* key_len) {
+  *key_len = file_meta->rep->largestkey.size();
+  return CopyString(file_meta->rep->largestkey);
+}
+
+/* Transactions */
+
 rocksdb_transactiondb_options_t* rocksdb_transactiondb_options_create() {
   return new rocksdb_transactiondb_options_t;
 }
 
-void rocksdb_transactiondb_options_destroy(rocksdb_transactiondb_options_t* opt){
+void rocksdb_transactiondb_options_destroy(
+    rocksdb_transactiondb_options_t* opt) {
   delete opt;
 }
 
@@ -4627,6 +5349,11 @@ void rocksdb_transaction_options_set_max_write_batch_size(
   opt->rep.max_write_batch_size = size;
 }
 
+void rocksdb_transaction_options_set_skip_prepare(
+    rocksdb_transaction_options_t* opt, unsigned char v) {
+  opt->rep.skip_prepare = v;
+}
+
 rocksdb_optimistictransaction_options_t*
 rocksdb_optimistictransaction_options_create() {
   return new rocksdb_optimistictransaction_options_t;
@@ -4642,6 +5369,27 @@ void rocksdb_optimistictransaction_options_set_set_snapshot(
   opt->rep.set_snapshot = v;
 }
 
+char* rocksdb_optimistictransactiondb_property_value(
+    rocksdb_optimistictransactiondb_t* db, const char* propname) {
+  std::string tmp;
+  if (db->rep->GetProperty(Slice(propname), &tmp)) {
+    // We use strdup() since we expect human readable output.
+    return strdup(tmp.c_str());
+  } else {
+    return nullptr;
+  }
+}
+
+int rocksdb_optimistictransactiondb_property_int(
+    rocksdb_optimistictransactiondb_t* db, const char* propname,
+    uint64_t* out_val) {
+  if (db->rep->GetIntProperty(Slice(propname), out_val)) {
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
 rocksdb_column_family_handle_t* rocksdb_transactiondb_create_column_family(
     rocksdb_transactiondb_t* txn_db,
     const rocksdb_options_t* column_family_options,
@@ -4712,6 +5460,27 @@ void rocksdb_transactiondb_release_snapshot(
   delete snapshot;
 }
 
+char* rocksdb_transactiondb_property_value(rocksdb_transactiondb_t* db,
+                                           const char* propname) {
+  std::string tmp;
+  if (db->rep->GetProperty(Slice(propname), &tmp)) {
+    // We use strdup() since we expect human readable output.
+    return strdup(tmp.c_str());
+  } else {
+    return nullptr;
+  }
+}
+
+int rocksdb_transactiondb_property_int(rocksdb_transactiondb_t* db,
+                                       const char* propname,
+                                       uint64_t* out_val) {
+  if (db->rep->GetIntProperty(Slice(propname), out_val)) {
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
 rocksdb_transaction_t* rocksdb_transaction_begin(
     rocksdb_transactiondb_t* txn_db,
     const rocksdb_writeoptions_t* write_options,
@@ -4724,10 +5493,66 @@ rocksdb_transaction_t* rocksdb_transaction_begin(
     return result;
   }
   old_txn->rep = txn_db->rep->BeginTransaction(write_options->rep,
-                                                txn_options->rep, old_txn->rep);
+                                               txn_options->rep, old_txn->rep);
   return old_txn;
 }
 
+rocksdb_transaction_t** rocksdb_transactiondb_get_prepared_transactions(
+    rocksdb_transactiondb_t* txn_db, size_t* cnt) {
+  std::vector<Transaction*> txns;
+  txn_db->rep->GetAllPreparedTransactions(&txns);
+  *cnt = txns.size();
+  if (txns.empty()) {
+    return nullptr;
+  } else {
+    rocksdb_transaction_t** buf = (rocksdb_transaction_t**)malloc(
+        txns.size() * sizeof(rocksdb_transaction_t*));
+    for (size_t i = 0; i < txns.size(); i++) {
+      buf[i] = new rocksdb_transaction_t;
+      buf[i]->rep = txns[i];
+    }
+    return buf;
+  }
+}
+
+void rocksdb_transaction_set_name(rocksdb_transaction_t* txn, const char* name,
+                                  size_t name_len, char** errptr) {
+  std::string str = std::string(name, name_len);
+  SaveError(errptr, txn->rep->SetName(str));
+}
+
+char* rocksdb_transaction_get_name(rocksdb_transaction_t* txn,
+                                   size_t* name_len) {
+  auto name = txn->rep->GetName();
+  *name_len = name.size();
+  return CopyString(name);
+}
+
+void rocksdb_transaction_prepare(rocksdb_transaction_t* txn, char** errptr) {
+  SaveError(errptr, txn->rep->Prepare());
+}
+
+rocksdb_writebatch_wi_t* rocksdb_transaction_get_writebatch_wi(
+    rocksdb_transaction_t* txn) {
+  rocksdb_writebatch_wi_t* wi =
+      (rocksdb_writebatch_wi_t*)malloc(sizeof(rocksdb_writebatch_wi_t));
+  wi->rep = txn->rep->GetWriteBatch();
+
+  return wi;
+}
+
+void rocksdb_transaction_rebuild_from_writebatch(
+    rocksdb_transaction_t* txn, rocksdb_writebatch_t* writebatch,
+    char** errptr) {
+  SaveError(errptr, txn->rep->RebuildFromWriteBatch(&writebatch->rep));
+}
+
+void rocksdb_transaction_rebuild_from_writebatch_wi(rocksdb_transaction_t* txn,
+                                                    rocksdb_writebatch_wi_t* wi,
+                                                    char** errptr) {
+  SaveError(errptr, txn->rep->RebuildFromWriteBatch(wi->rep->GetWriteBatch()));
+}
+
 void rocksdb_transaction_commit(rocksdb_transaction_t* txn, char** errptr) {
   SaveError(errptr, txn->rep->Commit());
 }
@@ -4740,7 +5565,8 @@ void rocksdb_transaction_set_savepoint(rocksdb_transaction_t* txn) {
   txn->rep->SetSavePoint();
 }
 
-void rocksdb_transaction_rollback_to_savepoint(rocksdb_transaction_t* txn, char** errptr) {
+void rocksdb_transaction_rollback_to_savepoint(rocksdb_transaction_t* txn,
+                                               char** errptr) {
   SaveError(errptr, txn->rep->RollbackToSavePoint());
 }
 
@@ -4751,7 +5577,10 @@ void rocksdb_transaction_destroy(rocksdb_transaction_t* txn) {
 
 const rocksdb_snapshot_t* rocksdb_transaction_get_snapshot(
     rocksdb_transaction_t* txn) {
-  rocksdb_snapshot_t* result = new rocksdb_snapshot_t;
+  // This will be freed later on using free, so use malloc here to avoid a
+  // mismatch
+  rocksdb_snapshot_t* result =
+      (rocksdb_snapshot_t*)malloc(sizeof(rocksdb_snapshot_t));
   result->rep = txn->rep->GetSnapshot();
   return result;
 }
@@ -4776,6 +5605,21 @@ char* rocksdb_transaction_get(rocksdb_transaction_t* txn,
   return result;
 }
 
+rocksdb_pinnableslice_t* rocksdb_transaction_get_pinned(
+    rocksdb_transaction_t* txn, const rocksdb_readoptions_t* options,
+    const char* key, size_t klen, char** errptr) {
+  rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
+  Status s = txn->rep->Get(options->rep, Slice(key, klen), &v->rep);
+  if (!s.ok()) {
+    delete (v);
+    if (!s.IsNotFound()) {
+      SaveError(errptr, s);
+    }
+    return nullptr;
+  }
+  return v;
+}
+
 char* rocksdb_transaction_get_cf(rocksdb_transaction_t* txn,
                                  const rocksdb_readoptions_t* options,
                                  rocksdb_column_family_handle_t* column_family,
@@ -4797,6 +5641,23 @@ char* rocksdb_transaction_get_cf(rocksdb_transaction_t* txn,
   return result;
 }
 
+rocksdb_pinnableslice_t* rocksdb_transaction_get_pinned_cf(
+    rocksdb_transaction_t* txn, const rocksdb_readoptions_t* options,
+    rocksdb_column_family_handle_t* column_family, const char* key, size_t klen,
+    char** errptr) {
+  rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
+  Status s = txn->rep->Get(options->rep, column_family->rep, Slice(key, klen),
+                           &v->rep);
+  if (!s.ok()) {
+    delete (v);
+    if (!s.IsNotFound()) {
+      SaveError(errptr, s);
+    }
+    return nullptr;
+  }
+  return v;
+}
+
 // Read a key inside a transaction
 char* rocksdb_transaction_get_for_update(rocksdb_transaction_t* txn,
                                          const rocksdb_readoptions_t* options,
@@ -4819,6 +5680,23 @@ char* rocksdb_transaction_get_for_update(rocksdb_transaction_t* txn,
   return result;
 }
 
+rocksdb_pinnableslice_t* rocksdb_transaction_get_pinned_for_update(
+    rocksdb_transaction_t* txn, const rocksdb_readoptions_t* options,
+    const char* key, size_t klen, unsigned char exclusive, char** errptr) {
+  rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
+  Status s = txn->rep->GetForUpdate(options->rep, Slice(key, klen),
+                                    v->rep.GetSelf(), exclusive);
+  v->rep.PinSelf();
+  if (!s.ok()) {
+    delete (v);
+    if (!s.IsNotFound()) {
+      SaveError(errptr, s);
+    }
+    return nullptr;
+  }
+  return v;
+}
+
 char* rocksdb_transaction_get_for_update_cf(
     rocksdb_transaction_t* txn, const rocksdb_readoptions_t* options,
     rocksdb_column_family_handle_t* column_family, const char* key, size_t klen,
@@ -4839,13 +5717,91 @@ char* rocksdb_transaction_get_for_update_cf(
   return result;
 }
 
+rocksdb_pinnableslice_t* rocksdb_transaction_get_pinned_for_update_cf(
+    rocksdb_transaction_t* txn, const rocksdb_readoptions_t* options,
+    rocksdb_column_family_handle_t* column_family, const char* key, size_t klen,
+    unsigned char exclusive, char** errptr) {
+  rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
+  Status s = txn->rep->GetForUpdate(options->rep, column_family->rep,
+                                    Slice(key, klen), &v->rep, exclusive);
+  if (!s.ok()) {
+    delete (v);
+    if (!s.IsNotFound()) {
+      SaveError(errptr, s);
+    }
+    return nullptr;
+  }
+  return v;
+}
+
+void rocksdb_transaction_multi_get(rocksdb_transaction_t* txn,
+                                   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<Slice> keys(num_keys);
+  for (size_t i = 0; i < num_keys; i++) {
+    keys[i] = Slice(keys_list[i], keys_list_sizes[i]);
+  }
+  std::vector<std::string> values(num_keys);
+  std::vector<Status> statuses =
+      txn->rep->MultiGet(options->rep, 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_transaction_multi_get_cf(
+    rocksdb_transaction_t* txn, 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) {
+  std::vector<Slice> keys(num_keys);
+  std::vector<ColumnFamilyHandle*> 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<std::string> values(num_keys);
+  std::vector<Status> statuses =
+      txn->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;
+      }
+    }
+  }
+}
+
 // Read a key outside a transaction
-char* rocksdb_transactiondb_get(
-    rocksdb_transactiondb_t* txn_db,
-    const rocksdb_readoptions_t* options,
-    const char* key, size_t klen,
-    size_t* vlen,
-    char** errptr){
+char* rocksdb_transactiondb_get(rocksdb_transactiondb_t* txn_db,
+                                const rocksdb_readoptions_t* options,
+                                const char* key, size_t klen, size_t* vlen,
+                                char** errptr) {
   char* result = nullptr;
   std::string tmp;
   Status s = txn_db->rep->Get(options->rep, Slice(key, klen), &tmp);
@@ -4861,6 +5817,22 @@ char* rocksdb_transactiondb_get(
   return result;
 }
 
+rocksdb_pinnableslice_t* rocksdb_transactiondb_get_pinned(
+    rocksdb_transactiondb_t* txn_db, const rocksdb_readoptions_t* options,
+    const char* key, size_t klen, char** errptr) {
+  rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
+  Status s = txn_db->rep->Get(options->rep, txn_db->rep->DefaultColumnFamily(),
+                              Slice(key, klen), &v->rep);
+  if (!s.ok()) {
+    delete (v);
+    if (!s.IsNotFound()) {
+      SaveError(errptr, s);
+    }
+    return nullptr;
+  }
+  return v;
+}
+
 char* rocksdb_transactiondb_get_cf(
     rocksdb_transactiondb_t* txn_db, const rocksdb_readoptions_t* options,
     rocksdb_column_family_handle_t* column_family, const char* key,
@@ -4881,6 +5853,86 @@ char* rocksdb_transactiondb_get_cf(
   return result;
 }
 
+rocksdb_pinnableslice_t* rocksdb_transactiondb_get_pinned_cf(
+    rocksdb_transactiondb_t* txn_db, const rocksdb_readoptions_t* options,
+    rocksdb_column_family_handle_t* column_family, const char* key,
+    size_t keylen, char** errptr) {
+  rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
+  Status s = txn_db->rep->Get(options->rep, column_family->rep,
+                              Slice(key, keylen), &v->rep);
+  if (!s.ok()) {
+    delete (v);
+    if (!s.IsNotFound()) {
+      SaveError(errptr, s);
+    }
+    return nullptr;
+  }
+  return v;
+}
+
+void rocksdb_transactiondb_multi_get(rocksdb_transactiondb_t* txn_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<Slice> keys(num_keys);
+  for (size_t i = 0; i < num_keys; i++) {
+    keys[i] = Slice(keys_list[i], keys_list_sizes[i]);
+  }
+  std::vector<std::string> values(num_keys);
+  std::vector<Status> statuses =
+      txn_db->rep->MultiGet(options->rep, 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_transactiondb_multi_get_cf(
+    rocksdb_transactiondb_t* txn_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) {
+  std::vector<Slice> keys(num_keys);
+  std::vector<ColumnFamilyHandle*> 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<std::string> values(num_keys);
+  std::vector<Status> statuses =
+      txn_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;
+      }
+    }
+  }
+}
+
 // Put a key inside a transaction
 void rocksdb_transaction_put(rocksdb_transaction_t* txn, const char* key,
                              size_t klen, const char* val, size_t vlen,
@@ -4896,6 +5948,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,
@@ -4916,11 +5978,9 @@ void rocksdb_transactiondb_put_cf(rocksdb_transactiondb_t* txn_db,
 }
 
 // Write batch into transaction db
-void rocksdb_transactiondb_write(
-        rocksdb_transactiondb_t* db,
-        const rocksdb_writeoptions_t* options,
-        rocksdb_writebatch_t* batch,
-        char** errptr) {
+void rocksdb_transactiondb_write(rocksdb_transactiondb_t* db,
+                                 const rocksdb_writeoptions_t* options,
+                                 rocksdb_writebatch_t* batch, char** errptr) {
   SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
 }
 
@@ -5021,6 +6081,23 @@ void rocksdb_transactiondb_close(rocksdb_transactiondb_t* txn_db) {
   delete txn_db;
 }
 
+void rocksdb_transactiondb_flush_wal(rocksdb_transactiondb_t* txn_db,
+                                     unsigned char sync, char** errptr) {
+  SaveError(errptr, txn_db->rep->FlushWAL(sync));
+}
+
+void rocksdb_transactiondb_flush(rocksdb_transactiondb_t* txn_db,
+                                 const rocksdb_flushoptions_t* options,
+                                 char** errptr) {
+  SaveError(errptr, txn_db->rep->Flush(options->rep));
+}
+
+void rocksdb_transactiondb_flush_cf(
+    rocksdb_transactiondb_t* txn_db, const rocksdb_flushoptions_t* options,
+    rocksdb_column_family_handle_t* column_family, char** errptr) {
+  SaveError(errptr, txn_db->rep->Flush(options->rep, column_family->rep));
+}
+
 rocksdb_checkpoint_t* rocksdb_transactiondb_checkpoint_object_create(
     rocksdb_transactiondb_t* txn_db, char** errptr) {
   Checkpoint* checkpoint;
@@ -5111,12 +6188,31 @@ rocksdb_transaction_t* rocksdb_optimistictransaction_begin(
   return old_txn;
 }
 
+// Write batch into OptimisticTransactionDB
+void rocksdb_optimistictransactiondb_write(
+    rocksdb_optimistictransactiondb_t* otxn_db,
+    const rocksdb_writeoptions_t* options, rocksdb_writebatch_t* batch,
+    char** errptr) {
+  SaveError(errptr, otxn_db->rep->Write(options->rep, &batch->rep));
+}
+
 void rocksdb_optimistictransactiondb_close(
     rocksdb_optimistictransactiondb_t* otxn_db) {
   delete otxn_db->rep;
   delete otxn_db;
 }
 
+rocksdb_checkpoint_t* rocksdb_optimistictransactiondb_checkpoint_object_create(
+    rocksdb_optimistictransactiondb_t* otxn_db, char** errptr) {
+  Checkpoint* checkpoint;
+  if (SaveError(errptr, Checkpoint::Create(otxn_db->rep, &checkpoint))) {
+    return nullptr;
+  }
+  rocksdb_checkpoint_t* result = new rocksdb_checkpoint_t;
+  result->rep = checkpoint;
+  return result;
+}
+
 void rocksdb_free(void* ptr) { free(ptr); }
 
 rocksdb_pinnableslice_t* rocksdb_get_pinned(
@@ -5205,7 +6301,6 @@ struct rocksdb_memory_usage_t {
 // estimates amount of memory occupied by consumers (dbs and caches)
 rocksdb_memory_usage_t* rocksdb_approximate_memory_usage_create(
     rocksdb_memory_consumers_t* consumers, char** errptr) {
-
   vector<DB*> dbs;
   for (auto db : consumers->dbs) {
     dbs.push_back(db->rep);
@@ -5227,7 +6322,8 @@ rocksdb_memory_usage_t* rocksdb_approximate_memory_usage_create(
   auto result = new rocksdb_memory_usage_t;
   result->mem_table_total = usage_by_type[MemoryUtil::kMemTableTotal];
   result->mem_table_unflushed = usage_by_type[MemoryUtil::kMemTableUnFlushed];
-  result->mem_table_readers_total = usage_by_type[MemoryUtil::kTableReadersTotal];
+  result->mem_table_readers_total =
+      usage_by_type[MemoryUtil::kTableReadersTotal];
   result->cache_total = usage_by_type[MemoryUtil::kCacheTotal];
   return result;
 }
@@ -5262,6 +6358,16 @@ void rocksdb_options_set_memtable_whole_key_filtering(rocksdb_options_t* opt,
   opt->rep.memtable_whole_key_filtering = val;
 }
 
+void rocksdb_options_set_avoid_unnecessary_blocking_io(rocksdb_options_t* opt,
+                                                       unsigned char val) {
+  opt->rep.avoid_unnecessary_blocking_io = val;
+}
+
+unsigned char rocksdb_options_get_avoid_unnecessary_blocking_io(
+    rocksdb_options_t* opt) {
+  return opt->rep.avoid_unnecessary_blocking_io;
+}
+
 // deletes container with memory usage estimates
 void rocksdb_approximate_memory_usage_destroy(rocksdb_memory_usage_t* usage) {
   delete usage;
@@ -5271,6 +6377,14 @@ void rocksdb_cancel_all_background_work(rocksdb_t* db, unsigned char wait) {
   CancelAllBackgroundWork(db->rep, wait);
 }
 
+void rocksdb_disable_manual_compaction(rocksdb_t* db) {
+  db->rep->DisableManualCompaction();
+}
+
+void rocksdb_enable_manual_compaction(rocksdb_t* db) {
+  db->rep->EnableManualCompaction();
+}
+
 }  // end extern "C"
 
 #endif  // !ROCKSDB_LITE