diff --git a/db/c.cc b/db/c.cc index 924b8e0ab..d9e75e04f 100644 --- a/db/c.cc +++ b/db/c.cc @@ -89,6 +89,7 @@ using rocksdb::RestoreOptions; using rocksdb::CompactRangeOptions; using rocksdb::RateLimiter; using rocksdb::NewGenericRateLimiter; +using rocksdb::PinnableSlice; using std::shared_ptr; @@ -127,6 +128,9 @@ struct rocksdb_envoptions_t { EnvOptions rep; }; struct rocksdb_ingestexternalfileoptions_t { IngestExternalFileOptions rep; }; struct rocksdb_sstfilewriter_t { SstFileWriter* rep; }; struct rocksdb_ratelimiter_t { RateLimiter* rep; }; +struct rocksdb_pinnableslice_t { + PinnableSlice rep; +}; struct rocksdb_compactionfiltercontext_t { CompactionFilter::Context rep; @@ -3092,6 +3096,51 @@ void rocksdb_delete_file_in_range_cf( void rocksdb_free(void* ptr) { free(ptr); } +rocksdb_pinnableslice_t* rocksdb_get_pinned( + rocksdb_t* db, const rocksdb_readoptions_t* options, const char* key, + size_t keylen, char** errptr) { + rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t); + Status s = db->rep->Get(options->rep, db->rep->DefaultColumnFamily(), + Slice(key, keylen), &v->rep); + if (!s.ok()) { + delete (v); + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + return NULL; + } + return v; +} + +rocksdb_pinnableslice_t* rocksdb_get_pinned_cf( + rocksdb_t* 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 = 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 NULL; + } + return v; +} + +void rocksdb_pinnableslice_destroy(rocksdb_pinnableslice_t* v) { delete v; } + +const char* rocksdb_pinnableslice_value(const rocksdb_pinnableslice_t* v, + size_t* vlen) { + if (!v) { + *vlen = 0; + return NULL; + } + + *vlen = v->rep.size(); + return v->rep.data(); +} } // end extern "C" #endif // !ROCKSDB_LITE diff --git a/db/c_test.c b/db/c_test.c index 9677f8509..9a45922c2 100644 --- a/db/c_test.c +++ b/db/c_test.c @@ -126,6 +126,32 @@ static void CheckGetCF( Free(&val); } +static void CheckPinGet(rocksdb_t* db, const rocksdb_readoptions_t* options, + const char* key, const char* expected) { + char* err = NULL; + size_t val_len; + const char* val; + rocksdb_pinnableslice_t* p; + p = rocksdb_get_pinned(db, options, key, strlen(key), &err); + CheckNoError(err); + val = rocksdb_pinnableslice_value(p, &val_len); + CheckEqual(expected, val, val_len); + rocksdb_pinnableslice_destroy(p); +} + +static void CheckPinGetCF(rocksdb_t* db, const rocksdb_readoptions_t* options, + rocksdb_column_family_handle_t* handle, + const char* key, const char* expected) { + char* err = NULL; + size_t val_len; + const char* val; + rocksdb_pinnableslice_t* p; + p = rocksdb_get_pinned_cf(db, options, handle, key, strlen(key), &err); + CheckNoError(err); + val = rocksdb_pinnableslice_value(p, &val_len); + CheckEqual(expected, val, val_len); + rocksdb_pinnableslice_destroy(p); +} static void CheckIter(rocksdb_iterator_t* iter, const char* key, const char* val) { @@ -789,6 +815,13 @@ int main(int argc, char** argv) { } } + StartPhase("pin_get"); + { + CheckPinGet(db, roptions, "box", "c"); + CheckPinGet(db, roptions, "foo", "hello"); + CheckPinGet(db, roptions, "notfound", NULL); + } + StartPhase("approximate_sizes"); { int i; @@ -1000,11 +1033,13 @@ int main(int argc, char** argv) { CheckNoError(err); CheckGetCF(db, roptions, handles[1], "foo", "hello"); + CheckPinGetCF(db, roptions, handles[1], "foo", "hello"); rocksdb_delete_cf(db, woptions, handles[1], "foo", 3, &err); CheckNoError(err); CheckGetCF(db, roptions, handles[1], "foo", NULL); + CheckPinGetCF(db, roptions, handles[1], "foo", NULL); rocksdb_writebatch_t* wb = rocksdb_writebatch_create(); rocksdb_writebatch_put_cf(wb, handles[1], "baz", 3, "a", 1); @@ -1017,6 +1052,9 @@ int main(int argc, char** argv) { CheckGetCF(db, roptions, handles[1], "baz", NULL); CheckGetCF(db, roptions, handles[1], "bar", NULL); CheckGetCF(db, roptions, handles[1], "box", "c"); + CheckPinGetCF(db, roptions, handles[1], "baz", NULL); + CheckPinGetCF(db, roptions, handles[1], "bar", NULL); + CheckPinGetCF(db, roptions, handles[1], "box", "c"); rocksdb_writebatch_destroy(wb); const char* keys[3] = { "box", "box", "barfooxx" }; diff --git a/include/rocksdb/c.h b/include/rocksdb/c.h index cf8eb9932..975f62c94 100644 --- a/include/rocksdb/c.h +++ b/include/rocksdb/c.h @@ -111,6 +111,7 @@ typedef struct rocksdb_envoptions_t rocksdb_envoptions_t; typedef struct rocksdb_ingestexternalfileoptions_t rocksdb_ingestexternalfileoptions_t; typedef struct rocksdb_sstfilewriter_t rocksdb_sstfilewriter_t; typedef struct rocksdb_ratelimiter_t rocksdb_ratelimiter_t; +typedef struct rocksdb_pinnableslice_t rocksdb_pinnableslice_t; /* DB operations */ @@ -1222,6 +1223,17 @@ extern ROCKSDB_LIBRARY_API void rocksdb_delete_file_in_range_cf( // to free memory that was malloc()ed extern ROCKSDB_LIBRARY_API void rocksdb_free(void* ptr); +extern rocksdb_pinnableslice_t* rocksdb_get_pinned( + rocksdb_t* db, const rocksdb_readoptions_t* options, const char* key, + size_t keylen, char** errptr); +extern rocksdb_pinnableslice_t* rocksdb_get_pinned_cf( + rocksdb_t* db, const rocksdb_readoptions_t* options, + rocksdb_column_family_handle_t* column_family, const char* key, + size_t keylen, char** errptr); +extern void rocksdb_pinnableslice_destroy(rocksdb_pinnableslice_t* v); +extern const char* rocksdb_pinnableslice_value(const rocksdb_pinnableslice_t* t, + size_t* vlen); + #ifdef __cplusplus } /* end extern "C" */ #endif