1717#include " rocksdb/listener.h"
1818#include " rocksdb/options.h"
1919#include " rocksdb/table.h"
20+ #include " rocksdb/write_batch.h"
2021
2122using ROCKSDB_NAMESPACE ::BackgroundErrorRecoveryInfo;
2223using ROCKSDB_NAMESPACE ::BlockBasedTableOptions;
@@ -28,8 +29,10 @@ using ROCKSDB_NAMESPACE::ExternalFileIngestionInfo;
2829using ROCKSDB_NAMESPACE ::FlushJobInfo;
2930using ROCKSDB_NAMESPACE ::Options;
3031using ROCKSDB_NAMESPACE ::ReadOptions;
32+ using ROCKSDB_NAMESPACE ::Slice;
3133using ROCKSDB_NAMESPACE ::Status;
3234using ROCKSDB_NAMESPACE ::SubcompactionJobInfo;
35+ using ROCKSDB_NAMESPACE ::WriteBatch;
3336using ROCKSDB_NAMESPACE ::WriteStallInfo;
3437using ROCKSDB_NAMESPACE ::MemTableInfo;
3538
@@ -350,3 +353,109 @@ extern "C" double rocksdb_compactoptions_get_blob_garbage_collection_age_cutoff(
350353 rocksdb_compactoptions_t * opt) {
351354 return reinterpret_cast <CompactRangeOptions*>(opt)->blob_garbage_collection_age_cutoff ;
352355}
356+
357+ // -----------------------------------------------------------------------------
358+ // WriteBatch iteration with log_data support
359+ //
360+ // rocksdb_writebatch_t is defined in rocksdb/db/c.cc as:
361+ // struct rocksdb_writebatch_t { WriteBatch rep; };
362+ // The `rep` field is the first (and only) member, so a pointer to the opaque
363+ // C type is also a valid pointer to its embedded WriteBatch — same layout
364+ // trick used for ReadOptions, Options, and BlockBasedTableOptions above.
365+ // -----------------------------------------------------------------------------
366+
367+ namespace {
368+
369+ class RustWriteBatchHandler : public WriteBatch ::Handler {
370+ public:
371+ void * state;
372+ void (*put_fn)(void *, const char *, size_t , const char *, size_t );
373+ void (*delete_fn)(void *, const char *, size_t );
374+ void (*log_data_fn)(void *, const char *, size_t );
375+
376+ Status PutCF (uint32_t cf, const Slice& key, const Slice& value) override {
377+ if (cf == 0 && put_fn != nullptr ) {
378+ put_fn (state, key.data (), key.size (), value.data (), value.size ());
379+ }
380+ return Status::OK ();
381+ }
382+
383+ Status DeleteCF (uint32_t cf, const Slice& key) override {
384+ if (cf == 0 && delete_fn != nullptr ) {
385+ delete_fn (state, key.data (), key.size ());
386+ }
387+ return Status::OK ();
388+ }
389+
390+ void LogData (const Slice& blob) override {
391+ if (log_data_fn != nullptr ) {
392+ log_data_fn (state, blob.data (), blob.size ());
393+ }
394+ }
395+ };
396+
397+ class RustWriteBatchCfHandler : public WriteBatch ::Handler {
398+ public:
399+ void * state;
400+ void (*put_cf_fn)(void *, uint32_t , const char *, size_t , const char *, size_t );
401+ void (*delete_cf_fn)(void *, uint32_t , const char *, size_t );
402+ void (*merge_cf_fn)(void *, uint32_t , const char *, size_t , const char *, size_t );
403+ void (*log_data_fn)(void *, const char *, size_t );
404+
405+ Status PutCF (uint32_t cf, const Slice& key, const Slice& value) override {
406+ if (put_cf_fn != nullptr ) {
407+ put_cf_fn (state, cf, key.data (), key.size (), value.data (), value.size ());
408+ }
409+ return Status::OK ();
410+ }
411+
412+ Status DeleteCF (uint32_t cf, const Slice& key) override {
413+ if (delete_cf_fn != nullptr ) {
414+ delete_cf_fn (state, cf, key.data (), key.size ());
415+ }
416+ return Status::OK ();
417+ }
418+
419+ Status MergeCF (uint32_t cf, const Slice& key, const Slice& value) override {
420+ if (merge_cf_fn != nullptr ) {
421+ merge_cf_fn (state, cf, key.data (), key.size (), value.data (), value.size ());
422+ }
423+ return Status::OK ();
424+ }
425+
426+ void LogData (const Slice& blob) override {
427+ if (log_data_fn != nullptr ) {
428+ log_data_fn (state, blob.data (), blob.size ());
429+ }
430+ }
431+ };
432+
433+ } // namespace
434+
435+ extern " C" void rust_rocksdb_writebatch_iterate (
436+ rocksdb_writebatch_t * b, void * state,
437+ void (*put)(void *, const char *, size_t , const char *, size_t ),
438+ void (*deleted)(void *, const char *, size_t ),
439+ void (*log_data)(void *, const char *, size_t )) {
440+ RustWriteBatchHandler handler;
441+ handler.state = state;
442+ handler.put_fn = put;
443+ handler.delete_fn = deleted;
444+ handler.log_data_fn = log_data;
445+ reinterpret_cast <WriteBatch*>(b)->Iterate (&handler);
446+ }
447+
448+ extern " C" void rust_rocksdb_writebatch_iterate_cf (
449+ rocksdb_writebatch_t * b, void * state,
450+ void (*put_cf)(void *, uint32_t , const char *, size_t , const char *, size_t ),
451+ void (*deleted_cf)(void *, uint32_t , const char *, size_t ),
452+ void (*merge_cf)(void *, uint32_t , const char *, size_t , const char *, size_t ),
453+ void (*log_data)(void *, const char *, size_t )) {
454+ RustWriteBatchCfHandler handler;
455+ handler.state = state;
456+ handler.put_cf_fn = put_cf;
457+ handler.delete_cf_fn = deleted_cf;
458+ handler.merge_cf_fn = merge_cf;
459+ handler.log_data_fn = log_data;
460+ reinterpret_cast <WriteBatch*>(b)->Iterate (&handler);
461+ }
0 commit comments