Add get_column_family_metadata() and related functions to C API (#10207)

Summary:
* Add metadata related structs and functions in C API, including
  - `rocksdb_get_column_family_metadata()` and `rocksdb_get_column_family_metadata_cf()`
     that returns `rocksdb_column_family_metadata_t`.
  - `rocksdb_column_family_metadata_t` and its get functions & destroy function.
  - `rocksdb_level_metadata_t` and its and its get functions & destroy function.
  - `rocksdb_file_metadata_t` and its and get functions & destroy functions.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10207

Test Plan:
Extend the existing c_test.c to include additional checks for column_family_metadata
inside CheckCompaction.

Reviewed By: riversand963

Differential Revision: D37305209

Pulled By: ajkr

fbshipit-source-id: 0a5183206353acde145f5f9b632c3bace670aa6e
main
Yueh-Hsuan Chiang 3 years ago committed by Facebook GitHub Bot
parent a16e2ff82a
commit e103b87296
  1. 5
      HISTORY.md
  2. 125
      db/c.cc
  3. 90
      db/c_test.c
  4. 122
      include/rocksdb/c.h

@ -29,6 +29,11 @@
* `rocksdb_comparator_with_ts_create` to create timestamp aware comparator
* Put, Get, Delete, SingleDelete, MultiGet APIs has corresponding timestamp aware APIs with suffix `with_ts`
* And Add C API's for Transaction, SstFileWriter, Compaction as mentioned [here](https://github.com/facebook/rocksdb/wiki/User-defined-Timestamp-(Experimental))
* Add metadata related structs and functions in C API, including
* `rocksdb_get_column_family_metadata()` and `rocksdb_get_column_family_metadata_cf()` to obtain `rocksdb_column_family_metadata_t`.
* `rocksdb_column_family_metadata_t` and its get functions & destroy function.
* `rocksdb_level_metadata_t` and its and its get functions & destroy function.
* `rocksdb_file_metadata_t` and its and get functions & destroy functions.
* The contract for implementations of Comparator::IsSameLengthImmediateSuccessor has been updated to work around a design bug in `auto_prefix_mode`.
* The API documentation for `auto_prefix_mode` now notes some corner cases in which it returns different results than `total_order_seek`, due to design bugs that are not easily fixed. Users using built-in comparators and keys at least the size of a fixed prefix length are not affected.
* Obsoleted the NUM_DATA_BLOCKS_READ_PER_LEVEL stat and introduced the NUM_LEVEL_READ_PER_MULTIGET and MULTIGET_COROUTINE_COUNT stats

@ -59,6 +59,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;
@ -78,6 +79,7 @@ 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;
@ -105,6 +107,7 @@ 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;
@ -178,6 +181,15 @@ struct rocksdb_cache_t {
};
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; };
@ -5131,6 +5143,119 @@ 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;
}

@ -272,6 +272,92 @@ static rocksdb_compactionfilter_t* CFilterCreate(
CFilterName);
}
void CheckMetaData(rocksdb_column_family_metadata_t* cf_meta,
const char* expected_cf_name) {
char* cf_name = rocksdb_column_family_metadata_get_name(cf_meta);
assert(strcmp(cf_name, expected_cf_name) == 0);
rocksdb_free(cf_name);
size_t cf_size = rocksdb_column_family_metadata_get_size(cf_meta);
assert(cf_size > 0);
size_t cf_file_count = rocksdb_column_family_metadata_get_size(cf_meta);
assert(cf_file_count > 0);
uint64_t total_level_size = 0;
size_t total_file_count = 0;
size_t level_count = rocksdb_column_family_metadata_get_level_count(cf_meta);
assert(level_count > 0);
for (size_t l = 0; l < level_count; ++l) {
rocksdb_level_metadata_t* level_meta =
rocksdb_column_family_metadata_get_level_metadata(cf_meta, l);
assert(level_meta);
assert(rocksdb_level_metadata_get_level(level_meta) >= (int)l);
uint64_t level_size = rocksdb_level_metadata_get_size(level_meta);
uint64_t file_size_in_level = 0;
size_t file_count = rocksdb_level_metadata_get_file_count(level_meta);
total_file_count += file_count;
for (size_t f = 0; f < file_count; ++f) {
rocksdb_sst_file_metadata_t* file_meta =
rocksdb_level_metadata_get_sst_file_metadata(level_meta, f);
assert(file_meta);
uint64_t file_size = rocksdb_sst_file_metadata_get_size(file_meta);
assert(file_size > 0);
file_size_in_level += file_size;
char* file_name =
rocksdb_sst_file_metadata_get_relative_filename(file_meta);
assert(file_name);
assert(strlen(file_name) > 0);
rocksdb_free(file_name);
size_t smallest_key_len;
char* smallest_key = rocksdb_sst_file_metadata_get_smallestkey(
file_meta, &smallest_key_len);
assert(smallest_key);
assert(smallest_key_len > 0);
size_t largest_key_len;
char* largest_key =
rocksdb_sst_file_metadata_get_largestkey(file_meta, &largest_key_len);
assert(largest_key);
assert(largest_key_len > 0);
rocksdb_free(smallest_key);
rocksdb_free(largest_key);
rocksdb_sst_file_metadata_destroy(file_meta);
}
assert(level_size == file_size_in_level);
total_level_size += level_size;
rocksdb_level_metadata_destroy(level_meta);
}
assert(total_file_count > 0);
assert(cf_size == total_level_size);
}
void GetAndCheckMetaData(rocksdb_t* db) {
rocksdb_column_family_metadata_t* cf_meta =
rocksdb_get_column_family_metadata(db);
CheckMetaData(cf_meta, "default");
rocksdb_column_family_metadata_destroy(cf_meta);
}
void GetAndCheckMetaDataCf(rocksdb_t* db,
rocksdb_column_family_handle_t* handle,
const char* cf_name) {
// Compact to make sure we have at least one sst file to obtain datadata.
rocksdb_compact_range_cf(db, handle, NULL, 0, NULL, 0);
rocksdb_column_family_metadata_t* cf_meta =
rocksdb_get_column_family_metadata_cf(db, handle);
CheckMetaData(cf_meta, cf_name);
rocksdb_column_family_metadata_destroy(cf_meta);
}
static rocksdb_t* CheckCompaction(rocksdb_t* db, rocksdb_options_t* options,
rocksdb_readoptions_t* roptions,
rocksdb_writeoptions_t* woptions) {
@ -304,6 +390,8 @@ static rocksdb_t* CheckCompaction(rocksdb_t* db, rocksdb_options_t* options,
CheckGet(db, roptions, "foo", "foovalue");
CheckGet(db, roptions, "bar", NULL);
CheckGet(db, roptions, "baz", "newbazvalue");
GetAndCheckMetaData(db);
return db;
}
@ -1443,6 +1531,8 @@ int main(int argc, char** argv) {
CheckNoError(err);
rocksdb_iter_destroy(iter);
GetAndCheckMetaDataCf(db, handles[1], cf_names[1]);
rocksdb_drop_column_family(db, handles[1], &err);
CheckNoError(err);
for (i = 0; i < 2; i++) {

@ -110,6 +110,10 @@ typedef struct rocksdb_writeoptions_t rocksdb_writeoptions_t;
typedef struct rocksdb_universal_compaction_options_t rocksdb_universal_compaction_options_t;
typedef struct rocksdb_livefiles_t rocksdb_livefiles_t;
typedef struct rocksdb_column_family_handle_t rocksdb_column_family_handle_t;
typedef struct rocksdb_column_family_metadata_t
rocksdb_column_family_metadata_t;
typedef struct rocksdb_level_metadata_t rocksdb_level_metadata_t;
typedef struct rocksdb_sst_file_metadata_t rocksdb_sst_file_metadata_t;
typedef struct rocksdb_envoptions_t rocksdb_envoptions_t;
typedef struct rocksdb_ingestexternalfileoptions_t rocksdb_ingestexternalfileoptions_t;
typedef struct rocksdb_sstfilewriter_t rocksdb_sstfilewriter_t;
@ -2165,6 +2169,124 @@ extern ROCKSDB_LIBRARY_API void rocksdb_delete_file_in_range_cf(
const char* start_key, size_t start_key_len, const char* limit_key,
size_t limit_key_len, char** errptr);
/* MetaData */
extern ROCKSDB_LIBRARY_API rocksdb_column_family_metadata_t*
rocksdb_get_column_family_metadata(rocksdb_t* db);
/**
* Returns the rocksdb_column_family_metadata_t of the specified
* column family.
*
* Note that the caller is responsible to release the returned memory
* using rocksdb_column_family_metadata_destroy.
*/
extern ROCKSDB_LIBRARY_API rocksdb_column_family_metadata_t*
rocksdb_get_column_family_metadata_cf(
rocksdb_t* db, rocksdb_column_family_handle_t* column_family);
extern ROCKSDB_LIBRARY_API void rocksdb_column_family_metadata_destroy(
rocksdb_column_family_metadata_t* cf_meta);
extern ROCKSDB_LIBRARY_API uint64_t rocksdb_column_family_metadata_get_size(
rocksdb_column_family_metadata_t* cf_meta);
extern ROCKSDB_LIBRARY_API size_t rocksdb_column_family_metadata_get_file_count(
rocksdb_column_family_metadata_t* cf_meta);
extern ROCKSDB_LIBRARY_API char* rocksdb_column_family_metadata_get_name(
rocksdb_column_family_metadata_t* cf_meta);
extern ROCKSDB_LIBRARY_API size_t
rocksdb_column_family_metadata_get_level_count(
rocksdb_column_family_metadata_t* cf_meta);
/**
* Returns the rocksdb_level_metadata_t of the ith level from the specified
* column family metadata.
*
* If the specified i is greater than or equal to the number of levels
* in the specified column family, then NULL will be returned.
*
* Note that the caller is responsible to release the returned memory
* using rocksdb_level_metadata_destroy before releasing its parent
* rocksdb_column_family_metadata_t.
*/
extern ROCKSDB_LIBRARY_API rocksdb_level_metadata_t*
rocksdb_column_family_metadata_get_level_metadata(
rocksdb_column_family_metadata_t* cf_meta, size_t i);
/**
* Releases the specified rocksdb_level_metadata_t.
*
* Note that the specified rocksdb_level_metadata_t must be released
* before the release of its parent rocksdb_column_family_metadata_t.
*/
extern ROCKSDB_LIBRARY_API void rocksdb_level_metadata_destroy(
rocksdb_level_metadata_t* level_meta);
extern ROCKSDB_LIBRARY_API int rocksdb_level_metadata_get_level(
rocksdb_level_metadata_t* level_meta);
extern ROCKSDB_LIBRARY_API uint64_t
rocksdb_level_metadata_get_size(rocksdb_level_metadata_t* level_meta);
extern ROCKSDB_LIBRARY_API size_t
rocksdb_level_metadata_get_file_count(rocksdb_level_metadata_t* level_meta);
/**
* Returns the sst_file_metadata_t of the ith file from the specified level
* metadata.
*
* If the specified i is greater than or equal to the number of files
* in the specified level, then NULL will be returned.
*
* Note that the caller is responsible to release the returned memory
* using rocksdb_sst_file_metadata_destroy before releasing its
* parent rocksdb_level_metadata_t.
*/
extern ROCKSDB_LIBRARY_API rocksdb_sst_file_metadata_t*
rocksdb_level_metadata_get_sst_file_metadata(
rocksdb_level_metadata_t* level_meta, size_t i);
/**
* Releases the specified rocksdb_sst_file_metadata_t.
*
* Note that the specified rocksdb_sst_file_metadata_t must be released
* before the release of its parent rocksdb_level_metadata_t.
*/
extern ROCKSDB_LIBRARY_API void rocksdb_sst_file_metadata_destroy(
rocksdb_sst_file_metadata_t* file_meta);
extern ROCKSDB_LIBRARY_API char*
rocksdb_sst_file_metadata_get_relative_filename(
rocksdb_sst_file_metadata_t* file_meta);
extern ROCKSDB_LIBRARY_API uint64_t
rocksdb_sst_file_metadata_get_size(rocksdb_sst_file_metadata_t* file_meta);
/**
* Returns the smallest key of the specified sst file.
* The caller is responsible for releasing the returned memory.
*
* @param file_meta the metadata of an SST file to obtain its smallest key.
* @param len the out value which will contain the length of the returned key
* after the function call.
*/
extern ROCKSDB_LIBRARY_API char* rocksdb_sst_file_metadata_get_smallestkey(
rocksdb_sst_file_metadata_t* file_meta, size_t* len);
/**
* Returns the smallest key of the specified sst file.
* The caller is responsible for releasing the returned memory.
*
* @param file_meta the metadata of an SST file to obtain its smallest key.
* @param len the out value which will contain the length of the returned key
* after the function call.
*/
extern ROCKSDB_LIBRARY_API char* rocksdb_sst_file_metadata_get_largestkey(
rocksdb_sst_file_metadata_t* file_meta, size_t* len);
/* Transactions */
extern ROCKSDB_LIBRARY_API rocksdb_column_family_handle_t*

Loading…
Cancel
Save