Skip to content

Commit

Permalink
feat: add c api for basic kv usage
Browse files Browse the repository at this point in the history
Signed-off-by: Jian Zhang <[email protected]>
  • Loading branch information
zz-jason committed Aug 9, 2024
1 parent 48d6374 commit 2899da7
Show file tree
Hide file tree
Showing 15 changed files with 611 additions and 13 deletions.
5 changes: 2 additions & 3 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"COUNTERS_LEVEL": "none",
"ENABLE_PROFILING": "OFF",
"BUILD_SHARED_LIBS": "OFF"
"ENABLE_PROFILING": "OFF"
}
},
{
Expand Down Expand Up @@ -68,4 +67,4 @@
}
}
]
}
}
82 changes: 82 additions & 0 deletions examples/c/BasicKvExample.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "leanstore/leanstore-c.h"

int main() {
LeanStoreHandle* storeHandle =
CreateLeanStore(1, "/tmp/leanstore/examples/BasicKvExample", 2, 0, 1);
BasicKvHandle* kvHandle = CreateBasicKV(storeHandle, 0, "testTree1");

StringSlice keySlice;
keySlice.mData="Hello";
keySlice.mSize=strlen(keySlice.mData);

StringSlice valSlice;
valSlice.mData = "World";
valSlice.mSize = strlen(valSlice.mData);

{
// insert a key value
LeanStoreError error = BasicKvInsert(kvHandle, 0, keySlice, valSlice);
if (error != kOk) {
printf("insert value failed: %d\n", error);
return error;
}
}

// lookup a key
{
String valStr = CreateString(NULL, 0);
LeanStoreError error = BasicKvLookup(kvHandle, 1, keySlice, &valStr);
if (error != 0) {
printf("lookup value failed: %d\n", error);
return error;
}
printf("%.*s, %.*s\n", (int)keySlice.mSize, keySlice.mData, (int)valStr.mSize, valStr.mData);

// cleanup the value string
DestroyString(&valStr);
}

// insert more key-values
{
StringSlice keySlice2;
keySlice2.mData="Hello2";
keySlice2.mSize=strlen(keySlice2.mData);

StringSlice valSlice2;
valSlice2.mData = "World2";
valSlice2.mSize = strlen(valSlice2.mData);
LeanStoreError error = BasicKvInsert(kvHandle, 0, keySlice2, valSlice2);
if (error != kOk) {
printf("insert value failed: %d\n", error);
return error;
}
}

// iterate over the keys
{
BasicKvIterHandle* iterHandle = CreateBasicKvIter(kvHandle);
if (iterHandle == NULL) {
printf("create iterator failed\n");
return -1;
}

uint8_t succeed = BasicKvIterBegin(iterHandle, 0);
while (succeed) {
StringSlice key = BasicKvIterKey(iterHandle);
StringSlice val = BasicKvIterVal(iterHandle);
printf("%.*s, %.*s\n", (int)key.mSize, key.mData, (int)val.mSize, val.mData);

succeed = BasicKvIterNext(iterHandle, 0);
}
}

// cleanup the basic kv handle
DestroyBasicKV(kvHandle);

// cleanup the store handle
DestroyLeanStore(storeHandle);
}
23 changes: 23 additions & 0 deletions examples/c/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ------------------------------------------------------------------------------
# Example for using the library
# ------------------------------------------------------------------------------

cmake_minimum_required(VERSION 3.10)
project(leanstore-examples C)

# Set gcc standard to c11
set(CMAKE_C_STANDARD 11)

# Set the leanstore include directory
option(LEANSTORE_INCLUDE_DIR "Path to the leanstore include directory" "")
message(STATUS "LEANSTORE_INCLUDE_DIR: ${LEANSTORE_INCLUDE_DIR}")

# Set the leanstore library directory, add it to the linker search path
option(LEANSTORE_LIBRARY_DIR "Path to the leanstore library directory" "")
message(STATUS "LEANSTORE_LIBRARY_DIR: ${LEANSTORE_LIBRARY_DIR}")
link_directories(${LEANSTORE_LIBRARY_DIR})

# Rules to build BasicKvExample
add_executable(BasicKvExample BasicKvExample.c)
target_link_libraries(BasicKvExample leanstore)
target_include_directories(BasicKvExample PUBLIC ${LEANSTORE_INCLUDE_DIR})
43 changes: 43 additions & 0 deletions examples/c/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Examples

## 1. Build the leanstore library

```sh
cd $LEANSTORE_HOME
cmake --preset=debug
cmake --build build/debug -j `nproc`
cmake --install build/debug
```

The leanstore library should be found in `$LEANSTORE/dist/debug` after the above commands.

## 2. Build the example

```sh
cd $LEANSTORE_HOME/examples/c

# generate build files with leanstore library
cmake -B build -S . \
-DLEANSTORE_INCLUDE_DIR=$LEANSTORE_HOME/dist/debug/include \
-DLEANSTORE_LIBRARY_DIR=$LEANSTORE_HOME/dist/debug/lib

# build the example
cmake --build build -j `nproc`

# run the example
./build/BasicKvExample
```

Or you can directly build the example:

```sh
cd $LEANSTORE_HOME/examples/c

# build with leanstore library
gcc -o basickv-example BasicKvExample.c \
-L$LEANSTORE_HOME/dist/debug/lib -lleanstore -lstdc++ \
-I$LEANSTORE_HOME/dist/debug/include

# run with LD_LIBRARY_PATH set to the leanstore library path
LD_LIBRARY_PATH=$LEANSTORE_HOME/dist/debug/lib ./basickv-example
```
File renamed without changes.
4 changes: 1 addition & 3 deletions examples/CMakeLists.txt → examples/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
# ------------------------------------------------------------------------------

cmake_minimum_required(VERSION 3.10)
project(leanstore-examples
VERSION 0.1.0
DESCRIPTION "Examples for using the leanstore library")
project(leanstore-examples CXX)

# Set gcc standard to c++23
set(CMAKE_CXX_STANDARD 23)
Expand Down
12 changes: 10 additions & 2 deletions examples/README.md → examples/cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@ The leanstore library should be found in `$LEANSTORE/dist/debug` after the above
## 2. Build the example

```sh
cd $LEANSTORE_HOME/examples
cmake -B build -S . -DLEANSTORE_INCLUDE_DIR=$LEANSTORE_HOME/dist/debug/include -DLEANSTORE_LIBRARY_DIR=$LEANSTORE_HOME/dist/debug/lib
cd $LEANSTORE_HOME/examples/cpp

# generate build files with leanstore library
cmake -B build -S . \
-DLEANSTORE_INCLUDE_DIR=$LEANSTORE_HOME/dist/debug/include \
-DLEANSTORE_LIBRARY_DIR=$LEANSTORE_HOME/dist/debug/lib

# build the example
cmake --build build -j `nproc`

# run the example
./build/BasicKvExample
```
4 changes: 4 additions & 0 deletions include/leanstore/Slice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class Slice : public std::basic_string_view<uint8_t> {
: std::basic_string_view<uint8_t>(reinterpret_cast<const uint8_t*>(data), std::strlen(data)) {
}

Slice(const char* data, size_t size)
: std::basic_string_view<uint8_t>(reinterpret_cast<const uint8_t*>(data), size) {
}

std::string ToString() const {
return std::string(reinterpret_cast<const char*>(data()), size());
}
Expand Down
2 changes: 1 addition & 1 deletion include/leanstore/StoreOption.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class StoreOption {
// ---------------------------------------------------------------------------

//! The number of worker threads.
uint32_t mWorkerThreads = 4;
uint64_t mWorkerThreads = 4;

//! The WAL buffer size for each worker (bytes).
uint64_t mWalBufferSize = 10 * 1024 * 1024;
Expand Down
2 changes: 2 additions & 0 deletions include/leanstore/btree/core/BTreeIteratorInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace btree {

class BTreeIteratorInterface {
public:
virtual ~BTreeIteratorInterface() = default;

virtual bool Seek(Slice key) = 0;
virtual bool SeekForPrev(Slice key) = 0;
virtual bool SeekExact(Slice key) = 0;
Expand Down
39 changes: 39 additions & 0 deletions include/leanstore/btree/core/BTreePessimisticIterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class BTreePessimisticIterator : public BTreeIteratorInterface {
//! The working btree, all the seek operations are based on this tree.
BTreeGeneric& mBTree;

//! The latch mode on the leaf node.
const LatchMode mMode;

//! mFuncEnterLeaf is called when the target leaf node is found.
Expand Down Expand Up @@ -134,6 +135,25 @@ class BTreePessimisticIterator : public BTreeIteratorInterface {
mBuffer() {
}

//! move constructor
BTreePessimisticIterator(BTreePessimisticIterator&& other)
: mBTree(other.mBTree),
mMode(other.mMode),
mFuncEnterLeaf(std::move(other.mFuncEnterLeaf)),
mFuncExitLeaf(std::move(other.mFuncExitLeaf)),
mFuncCleanUp(std::move(other.mFuncCleanUp)),
mSlotId(other.mSlotId),
mIsPrefixCopied(other.mIsPrefixCopied),
mGuardedLeaf(std::move(other.mGuardedLeaf)),
mGuardedParent(std::move(other.mGuardedParent)),
mLeafPosInParent(other.mLeafPosInParent),
mBuffer(std::move(other.mBuffer)),
mFenceSize(other.mFenceSize),
mIsUsingUpperFence(other.mIsUsingUpperFence) {
other.mSlotId = -1;
other.mLeafPosInParent = -1;
}

void SetEnterLeafCallback(LeafCallback cb) {
mFuncEnterLeaf = cb;
}
Expand Down Expand Up @@ -201,6 +221,25 @@ class BTreePessimisticIterator : public BTreeIteratorInterface {
return true;
}

bool HasNext() {
// iterator is not initialized, return false
if (mSlotId == -1) {
return false;
}

// If we are not at the end of the leaf, return true
if (mSlotId < mGuardedLeaf->mNumSeps - 1) {
return true;
}

// No more keys in the BTree, return false
if (mGuardedLeaf->mUpperFence.mLength == 0) {
return false;
}

return true;
}

virtual bool Next() override {
COUNTERS_BLOCK() {
WorkerCounters::MyCounters().dt_next_tuple[mBTree.mTreeId]++;
Expand Down
15 changes: 11 additions & 4 deletions include/leanstore/buffer-manager/GuardedBufferFrame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class SharedGuardedBufferFrame;
template <typename T>
class GuardedBufferFrame {
public:
//! The buffer manager who manages the guarded buffer frame. Used to reclaim
//! the buffer frame, buffer manager must be set when keep alive is false.
//! The buffer manager who manages the guarded buffer frame. Used to reclaim the buffer frame,
//! buffer manager must be set when keep alive is false.
BufferManager* mBufferManager = nullptr;

//! The guarded buffer frame. Latch mode is determined by mGuard.
Expand All @@ -32,6 +32,8 @@ class GuardedBufferFrame {
//! The latch guard of this buffer frame
HybridGuard mGuard;

//! Whether to keep the buffer frame alive after the guard is released. If false, the buffer frame
//! will be reclaimed by the buffer manager.
bool mKeepAlive = true;

public:
Expand All @@ -51,8 +53,13 @@ class GuardedBufferFrame {
JUMPMU_PUSH_BACK_DESTRUCTOR_BEFORE_JUMP();
}

GuardedBufferFrame(GuardedBufferFrame& other) = delete; // Copy constructor
GuardedBufferFrame(GuardedBufferFrame&& other) = delete; // Move constructor
GuardedBufferFrame(GuardedBufferFrame& other) = delete; // Copy constructor

GuardedBufferFrame(GuardedBufferFrame&& other) {
// call the move assignment
*this = std::move(other);
JUMPMU_PUSH_BACK_DESTRUCTOR_BEFORE_JUMP();
}

GuardedBufferFrame(BufferManager* bufferManager, BufferFrame* bf, bool keepAlive = true)
: mBufferManager(bufferManager),
Expand Down
Loading

0 comments on commit 2899da7

Please sign in to comment.