Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor the string interface in c api #108

Merged
merged 1 commit into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 38 additions & 22 deletions examples/c/BasicKvExample.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ int main() {
CreateLeanStore(1, "/tmp/leanstore/examples/BasicKvExample", 2, 0, 1);
BasicKvHandle* kvHandle = CreateBasicKV(storeHandle, 0, "testTree1");

// key-value pair 1
StringSlice keySlice;
keySlice.mData = "Hello";
keySlice.mSize = strlen(keySlice.mData);
Expand All @@ -17,42 +18,44 @@ int main() {
valSlice.mData = "World";
valSlice.mSize = strlen(valSlice.mData);

// key-value pair 2
StringSlice keySlice2;
keySlice2.mData = "Hello2";
keySlice2.mSize = strlen(keySlice2.mData);

StringSlice valSlice2;
valSlice2.mData = "World2";
valSlice2.mSize = strlen(valSlice2.mData);

{
// insert a key value
LeanStoreError error = BasicKvInsert(kvHandle, 0, keySlice, valSlice);
if (error != kOk) {
printf("insert value failed: %d\n", error);
return error;
if (!BasicKvInsert(kvHandle, 0, keySlice, valSlice)) {
printf("insert value failed, key=%.*s, val=%.*s\n", (int)keySlice.mSize, keySlice.mData,
(int)valSlice.mSize, valSlice.mData);
return -1;
}
}

// 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;
String* valStr = BasicKvLookup(kvHandle, 1, keySlice);
if (valStr == NULL) {
printf("lookup value failed, value may not exist, key=%.*s\n", (int)keySlice.mSize,
keySlice.mData);
return -1;
}
printf("%.*s, %.*s\n", (int)keySlice.mSize, keySlice.mData, (int)valStr.mSize, valStr.mData);
printf("%.*s, %.*s\n", (int)keySlice.mSize, keySlice.mData, (int)valStr->mSize, valStr->mData);

// cleanup the value string
DestroyString(&valStr);
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;
if (!BasicKvInsert(kvHandle, 0, keySlice2, valSlice2)) {
printf("insert value failed, key=%.*s, val=%.*s\n", (int)keySlice2.mSize, keySlice2.mData,
(int)valSlice2.mSize, valSlice2.mData);
return -1;
}
}

Expand Down Expand Up @@ -98,6 +101,19 @@ int main() {
DestroyBasicKvIter(iterHandle);
}

// remove key-values
{
if (!BasicKvRemove(kvHandle, 0, keySlice)) {
printf("remove value failed, key=%.*s\n", (int)keySlice.mSize, keySlice.mData);
return -1;
}

if (!BasicKvRemove(kvHandle, 0, keySlice2)) {
printf("remove value failed, key=%.*s\n", (int)keySlice2.mSize, keySlice2.mData);
return -1;
}
}

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

Expand Down
48 changes: 17 additions & 31 deletions include/leanstore/leanstore-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ typedef struct String {
uint64_t mSize;
} String;

//! Creates a new string with the given bytes buffer
String CreateString(const char* data, uint64_t size);
//! Creates a new string, copying the data from the given buffer to the new string
//! @param data the data buffer
//! @param size the size of the data buffer
//! @return the new string, which should be destroyed by the caller with DestroyString()
String* CreateString(const char* data, uint64_t size);

//! Destroys a string
void DestroyString(String* str);
Expand Down Expand Up @@ -53,54 +56,35 @@ LeanStoreHandle* CreateLeanStore(int8_t createFromScratch, const char* storeDir,
//! Deinit and destroy a leanstore instance
void DestroyLeanStore(LeanStoreHandle* handle);

//! LeanStore error codes
typedef enum LeanStoreError {
//! No error
kOk = 0,

//! Unknown error
kUnknownError = 1001,

//! Key already exists
kKeyDuplicated = 2000,

//! Key not found
kKeyNotFound = 2001,

kTransactionConflict = 3000,

//! Space not enough
kSpaceNotEnough = 4000,
} LeanStoreError;

//------------------------------------------------------------------------------
// BasicKV API
//------------------------------------------------------------------------------

typedef struct BasicKvHandle BasicKvHandle;

//! Create a basic key-value store in a leanstore instance at workerId
//! The handle should be destroyed by the caller
//! @return the basic key-value store handle, or nullptr if the creation fails. The handle should be
//! destroyed by the caller with DestroyBasicKV()
BasicKvHandle* CreateBasicKV(LeanStoreHandle* handle, uint64_t workerId, const char* btreeName);

//! Destroy the basic key-value store handle
void DestroyBasicKV(BasicKvHandle* handle);

//! Insert a key-value pair into a basic key-value store at workerId
LeanStoreError BasicKvInsert(BasicKvHandle* handle, uint64_t workerId, StringSlice key,
StringSlice val);
//! @return true if the insert is successful, false otherwise
uint8_t BasicKvInsert(BasicKvHandle* handle, uint64_t workerId, StringSlice key, StringSlice val);

//! Lookup a key in a basic key-value store at workerId
//! NOTE:
//! 1. The old content hold by val will be released and overwritten by the new content
//! 2. The caller should destroy the val after use
LeanStoreError BasicKvLookup(BasicKvHandle* handle, uint64_t workerId, StringSlice key,
String* val);
//! NOTE: The caller should destroy the val after use via DestroyString()
//! @return the value if the key exists, nullptr otherwise
String* BasicKvLookup(BasicKvHandle* handle, uint64_t workerId, StringSlice key);

//! Remove a key in a basic key-value store at workerId
LeanStoreError BasicKvRemove(BasicKvHandle* handle, uint64_t workerId, StringSlice key);
//! @return true if the key is found and removed, false otherwise
uint8_t BasicKvRemove(BasicKvHandle* handle, uint64_t workerId, StringSlice key);

//! Get the size of a basic key-value store at workerId
//! @return the number of entries in the basic key-value store
uint64_t BasicKvNumEntries(BasicKvHandle* handle, uint64_t workerId);

//------------------------------------------------------------------------------
Expand All @@ -112,6 +96,8 @@ uint64_t BasicKvNumEntries(BasicKvHandle* handle, uint64_t workerId);
typedef struct BasicKvIterHandle BasicKvIterHandle;

//! Create an iterator for a basic key-value store at workerId
//! @return the iterator handle, or nullptr if the creation fails. The handle should be destroyed by
//! the caller with DestroyBasicKvIter()
BasicKvIterHandle* CreateBasicKvIter(const BasicKvHandle* handle);

//! Destroy an iterator for a basic key-value store at workerId
Expand Down
85 changes: 32 additions & 53 deletions src/leanstore-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,35 @@
// String API
//------------------------------------------------------------------------------

String CreateString(const char* data, uint64_t size) {
String str;
String* CreateString(const char* data, uint64_t size) {
String* str = new String();

if (data == nullptr || size == 0) {
str.mData = nullptr;
str.mSize = 0;
return str;
}

// allocate memory
str.mData = static_cast<char*>(malloc(size));
if (str.mData == nullptr) {
str.mSize = 0;
str->mData = nullptr;
str->mSize = 0;
return str;
}

// copy data
memcpy(str.mData, data, size);
str.mSize = size;
// allocate memory, copy data
str->mSize = size;
str->mData = new char[size];
memcpy(str->mData, data, size);

return str;
}

void DestroyString(String* str) {
if (str != nullptr) {
if (str->mData == nullptr) {
return;
if (str->mData != nullptr) {
// release memory
delete[] str->mData;
}

free(str->mData);
str->mData = nullptr;
str->mSize = 0;

// release the string object
delete str;
}
}

Expand Down Expand Up @@ -84,24 +81,6 @@ void DestroyLeanStore(LeanStoreHandle* handle) {
delete handle;
}

static LeanStoreError ToLeanStoreError(leanstore::OpCode opCode) {
switch (opCode) {
case leanstore::OpCode::kOK:
return kOk;
case leanstore::OpCode::kNotFound:
return kKeyNotFound;
case leanstore::OpCode::kDuplicated:
return kKeyDuplicated;
case leanstore::OpCode::kAbortTx:
return kTransactionConflict;
case leanstore::OpCode::kSpaceNotEnough:
return kSpaceNotEnough;
case leanstore::OpCode::kOther:
default:
return kUnknownError;
}
}

//------------------------------------------------------------------------------
// BasicKV API
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -140,34 +119,34 @@ void DestroyBasicKV(BasicKvHandle* handle) {
}
}

LeanStoreError BasicKvInsert(BasicKvHandle* handle, uint64_t workerId, StringSlice key,
StringSlice val) {
leanstore::OpCode opCode{leanstore::OpCode::kOK};
uint8_t BasicKvInsert(BasicKvHandle* handle, uint64_t workerId, StringSlice key, StringSlice val) {
uint8_t succeed{false};
handle->mStore->ExecSync(workerId, [&]() {
opCode = handle->mBtree->Insert(leanstore::Slice(key.mData, key.mSize),
leanstore::Slice(val.mData, val.mSize));
auto opCode = handle->mBtree->Insert(leanstore::Slice(key.mData, key.mSize),
leanstore::Slice(val.mData, val.mSize));
succeed = (opCode == leanstore::OpCode::kOK);
});
return ToLeanStoreError(opCode);
return succeed;
}

LeanStoreError BasicKvLookup(BasicKvHandle* handle, uint64_t workerId, StringSlice key,
String* val) {
leanstore::OpCode opCode{leanstore::OpCode::kOK};
String* BasicKvLookup(BasicKvHandle* handle, uint64_t workerId, StringSlice key) {
String* val{nullptr};
handle->mStore->ExecSync(workerId, [&]() {
auto copyValueOut = [&](leanstore::Slice valSlice) {
DestroyString(val); // release old content
*val = CreateString(reinterpret_cast<const char*>(valSlice.data()), valSlice.size());
val = CreateString(reinterpret_cast<const char*>(valSlice.data()), valSlice.size());
};
opCode = handle->mBtree->Lookup(leanstore::Slice(key.mData, key.mSize), copyValueOut);
handle->mBtree->Lookup(leanstore::Slice(key.mData, key.mSize), copyValueOut);
});
return ToLeanStoreError(opCode);
return val;
}

LeanStoreError BasicKvRemove(BasicKvHandle* handle, uint64_t workerId, StringSlice key) {
leanstore::OpCode opCode{leanstore::OpCode::kOK};
handle->mStore->ExecSync(
workerId, [&]() { opCode = handle->mBtree->Remove(leanstore::Slice(key.mData, key.mSize)); });
return ToLeanStoreError(opCode);
uint8_t BasicKvRemove(BasicKvHandle* handle, uint64_t workerId, StringSlice key) {
uint8_t succeed{false};
handle->mStore->ExecSync(workerId, [&]() {
auto opCode = handle->mBtree->Remove(leanstore::Slice(key.mData, key.mSize));
succeed = (opCode == leanstore::OpCode::kOK);
});
return succeed;
}

uint64_t BasicKvNumEntries(BasicKvHandle* handle, uint64_t workerId) {
Expand Down
Loading