From 38f237366e011d0695be53f0a22031b8c6227d48 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 5 Feb 2025 23:27:01 -0500 Subject: [PATCH] adding leveldb --- .gitmodules | 3 ++ CMakeLists.txt | 11 ++++ external/leveldb_bliss | 1 + src/bliss/bench_leveldb.h | 80 ++++++++++++++++++++++++++++ src/bliss_bench.cpp | 3 ++ tests/CMakeLists.txt | 2 + tests/bliss_index_tests.h | 3 +- tests/test_leveldb/CMakeLists.txt | 9 ++++ tests/test_leveldb/leveldb_tests.cpp | 40 ++++++++++++++ 9 files changed, 151 insertions(+), 1 deletion(-) create mode 160000 external/leveldb_bliss create mode 100644 src/bliss/bench_leveldb.h create mode 100644 tests/test_leveldb/CMakeLists.txt create mode 100644 tests/test_leveldb/leveldb_tests.cpp diff --git a/.gitmodules b/.gitmodules index 4e22ebf..bc228f8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ path = external/rocksdb url = git@github.com:BU-DiSC/rocksdb.git branch = sortedness +[submodule "external/leveldb_bliss"] + path = external/leveldb_bliss + url = git@github.com:JslYoon/leveldb_bliss.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 768a14f..15c6af7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,10 @@ project(bliss_benchmark VERSION 1.0 LANGUAGES CXX ) +set(BUILD_TESTING OFF CACHE BOOL "Disable testing" FORCE) +set(LEVELDB_BUILD_TESTS OFF CACHE BOOL "Disable LevelDB tests" FORCE) + + include(ExternalProject) message(STATUS "CXX : ${CMAKE_CXX_COMPILER}") set(CMAKE_CXX_STANDARD 17) @@ -54,6 +58,7 @@ add_library(bliss OBJECT ${CMAKE_SOURCE_DIR}/src/bliss/bench_skiplist.h ${CMAKE_SOURCE_DIR}/src/bliss/bench_pgm.h ${CMAKE_SOURCE_DIR}/src/bliss/bench_art.h + ${CMAKE_SOURCE_DIR}/src/bliss/bench_leveldb.h ) target_compile_features(bliss PUBLIC @@ -97,3 +102,9 @@ add_executable(bliss_bench src/bliss_bench.cpp) target_link_libraries(bliss_bench PUBLIC bliss ) + +add_subdirectory(${CMAKE_SOURCE_DIR}/external/leveldb_bliss) +target_include_directories(bliss PUBLIC ${CMAKE_SOURCE_DIR}/external/leveldb_bliss/include) +target_link_libraries(bliss PRIVATE leveldb) + +include_directories(${CMAKE_SOURCE_DIR}/external/leveldb_bliss/include) \ No newline at end of file diff --git a/external/leveldb_bliss b/external/leveldb_bliss new file mode 160000 index 0000000..434e20f --- /dev/null +++ b/external/leveldb_bliss @@ -0,0 +1 @@ +Subproject commit 434e20fc8ffa4e048218cc7259bee20689bdad0b diff --git a/src/bliss/bench_leveldb.h b/src/bliss/bench_leveldb.h new file mode 100644 index 0000000..48523f5 --- /dev/null +++ b/src/bliss/bench_leveldb.h @@ -0,0 +1,80 @@ +#ifndef BLISS_BENCH_LEVELDB +#define BLISS_BENCH_LEVELDB + +#include +#include +#include +#include +#include + +#include "bliss/bliss_index.h" +#include "leveldb/db.h" + +namespace bliss { + +template +class BlissLevelDBIndex : public BlissIndex { + public: + leveldb::DB* db_; + + + BlissLevelDBIndex() { + leveldb::Options options; + options.create_if_missing = true; + + std::string db_path = "/tmp/bliss_leveldb_index"; + leveldb::Status status = leveldb::DB::Open(options, db_path, &db_); + if (!status.ok()) { + std::cerr << "Failed to open LevelDB at " << db_path << ": " + << status.ToString() << std::endl; + std::exit(1); + } + } + + + void bulkload(std::vector> values) override { + for (const auto& kv : values) { + put(kv.first, kv.second); + } + } + + + bool get(KEY_TYPE key) override { + std::string key_str = to_string(key); + std::string value; + leveldb::Status status = db_->Get(leveldb::ReadOptions(), key_str, &value); + return status.ok(); + } + + + void put(KEY_TYPE key, VALUE_TYPE value) override { + std::string key_str = to_string(key); + std::string value_str = to_string(value); + leveldb::Status status = db_->Put(leveldb::WriteOptions(), key_str, value_str); + if (!status.ok()) { + std::cerr << "LevelDB put error: " << status.ToString() << std::endl; + } + } + + + void end_routine() override { + delete db_; + } + + private: + template + std::string to_string(const T& t) { + std::ostringstream oss; + oss << t; + return oss.str(); + } + + + std::string to_string(const std::string& s) { + return s; + } +}; + +} // namespace bliss + +#endif // BLISS_BENCH_LEVELDB diff --git a/src/bliss_bench.cpp b/src/bliss_bench.cpp index 7150f6f..6085f80 100644 --- a/src/bliss_bench.cpp +++ b/src/bliss_bench.cpp @@ -13,6 +13,7 @@ #include "bliss/bench_art.h" #include "bliss/bench_btree.h" #include "bliss/bench_lipp.h" +#include "bliss/bench_leveldb.h" #include "bliss/bench_skiplist.h" #include "bliss/bliss_index.h" #include "bliss/util/args.h" @@ -179,6 +180,8 @@ int main(int argc, char *argv[]) { index.reset(new bliss::BlissARTIndex()); } else if (config.index == "pgm") { index.reset(new bliss::BlissPGMIndex()); + } else if (config.index == "leveldb") { + index.reset(new bliss::BlissLevelDBIndex()); } else { spdlog::error(config.index + " not implemented yet", 1); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0999169..21fa206 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,3 +19,5 @@ add_subdirectory(test_lipp) add_subdirectory(test_btree) add_subdirectory(test_skiplist) add_subdirectory(test_art) +add_subdirectory(test_leveldb) + diff --git a/tests/bliss_index_tests.h b/tests/bliss_index_tests.h index e11200c..1e80565 100644 --- a/tests/bliss_index_tests.h +++ b/tests/bliss_index_tests.h @@ -20,6 +20,7 @@ #include "bliss/bench_lipp.h" #include "bliss/bench_skiplist.h" #include "bliss/bench_pgm.h" +#include "bliss/bench_leveldb.h" #include "bliss/bliss_index.h" #include "bliss/util/args.h" #include "bliss/util/config.h" @@ -36,7 +37,7 @@ class BlissIndexTest : public testing::Test { protected: std::unique_ptr> index; - std::string indexes[6] = {"alex", "lipp", "btree", "skiplist", "pgm", "art"}; + std::string indexes[7] = {"alex", "lipp", "btree", "skiplist", "pgm", "art", "leveldb"}; int num_keys = 100000; diff --git a/tests/test_leveldb/CMakeLists.txt b/tests/test_leveldb/CMakeLists.txt new file mode 100644 index 0000000..b44a9ac --- /dev/null +++ b/tests/test_leveldb/CMakeLists.txt @@ -0,0 +1,9 @@ +get_filename_component(EXEC ${CMAKE_CURRENT_SOURCE_DIR} NAME) +file(GLOB_RECURSE CPP_TESTS "*_tests.cpp") +add_executable(${EXEC} ${CPP_TESTS}) +target_link_libraries(${EXEC} PRIVATE +bliss +bliss_test_infra +GTest::gtest_main) +include(GoogleTest) +gtest_discover_tests(${EXEC}) \ No newline at end of file diff --git a/tests/test_leveldb/leveldb_tests.cpp b/tests/test_leveldb/leveldb_tests.cpp new file mode 100644 index 0000000..82882a3 --- /dev/null +++ b/tests/test_leveldb/leveldb_tests.cpp @@ -0,0 +1,40 @@ +#include "bliss_index_tests.h" + +class LevelDBTest : public BlissIndexTest {}; + +TEST_F(LevelDBTest, TestLevelDB_Sanity) { + index.reset(new bliss::BlissLevelDBIndex()); + std::vector data; + int key = 100; + int value = 123; + index->put(key, value); + EXPECT_TRUE(index->get(key)); +} + +TEST_F(LevelDBTest, TestLevelDB_Sorted) { + index.reset(new bliss::BlissLevelDBIndex()); + std::vector data; + GenerateData(data, num_keys); + + auto insert_start = data.begin(); + auto insert_end = data.end(); + executor::execute_inserts(*index, insert_start, insert_end); + + for (auto key : data) { + EXPECT_TRUE(index->get(key)); + } +} + +TEST_F(LevelDBTest, TestLevelDB_Random) { + index.reset(new bliss::BlissLevelDBIndex()); + std::vector data; + GenerateData(data, num_keys, false); + + auto insert_start = data.begin(); + auto insert_end = data.end(); + executor::execute_inserts(*index, insert_start, insert_end); + + for (auto key : data) { + EXPECT_TRUE(index->get(key)); + } +} \ No newline at end of file