Skip to content

Commit

Permalink
Update & Delete finished
Browse files Browse the repository at this point in the history
  • Loading branch information
kkli08 committed Nov 6, 2024
1 parent 991aade commit 6462de1
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 46 deletions.
22 changes: 22 additions & 0 deletions LSMTree/LSMTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,25 @@ void LSMTree::printLevelSizes() const {
cout << "Level " << i+1 << " maximum size = " << levelMaxSizes[i] << endl;
}
}


void LSMTree::setBufferPoolParameters(size_t capacity, EvictionPolicy policy) {
bufferPoolCapacity = capacity;
bufferPoolPolicy = policy;

// Update existing DiskBTrees
for (auto& sst : levels) {
if (sst == nullptr) continue;
sst->setBufferPoolParameters(capacity, policy);
}
}

long long LSMTree::getTotalCacheHits() const {
long long totalCacheHit = 0;
for(auto sst : levels) {
if (sst == nullptr) continue;
totalCacheHit+=sst->getCacheHit();
}

return totalCacheHit;
}
8 changes: 8 additions & 0 deletions LSMTree/LSMTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class LSMTree {
// print LSM-Tree structure
void printTree() const;
void printLevelSizes() const;

// set Buffer Pool Parameter
void setBufferPoolParameters(size_t capacity, EvictionPolicy policy);
long long getTotalCacheHits() const;

private:
// Level 0 is always the in-memory memtable
std::unique_ptr<Memtable> memtable; // Level 0
Expand Down Expand Up @@ -87,6 +92,9 @@ class LSMTree {
// Disable copy and assignment
LSMTree(const LSMTree&) = delete;
LSMTree& operator=(const LSMTree&) = delete;

size_t bufferPoolCapacity;
EvictionPolicy bufferPoolPolicy;
};

#endif // LSMTREE_H
68 changes: 60 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ inspired by modern databases like [LevelDB](https://github.com/google/leveldb)
and [RocksDB](https://github.com/facebook/rocksdb), and supports multiple data
types using C++ Templates and Protocol Buffers.

### Structure
| Level | Data Structure |
|------------------|------------------------------------|
| `Memory`, `L0` | `Memtable` using `RB Tree` |
| `Disk/SSD`, `L1+` | `DiskBTree` using `Static B+ Tree` |

### [Database Operations](https://kkli08.github.io/VeloxDB/api/#database-operations)

#### **_VeloxDB::Open(string db_name)_**
Expand Down Expand Up @@ -52,7 +58,10 @@ MyDB->Put("Hello", 1e8LL); // string -> long long
#### **_VeloxDB::Get(const KeyValueWrapper& key)_**
Retrieves a value from the database based on the key. Supports multiple data types.
```c++
template<typename K, typename V>
void VeloxDB::Put(K key, V value)
```
```c++
#include "VeloxDB/VeloxDB.h"
#include "kv/KeyValue.h"
Expand Down Expand Up @@ -87,25 +96,68 @@ if(result.isEmpty()){
}
```
#### **_VeloxDB::Scan(KeyValueWrapper smallestKey, KeyValueWrapper largestKey)_**
Scans the database for key-value pairs within a specified key range. The results are returned in sorted key order.

```c++
template<typename K1, typename K2>
std::vector<KeyValueWrapper> VeloxDB::Scan(K1 small_key, K2 large_key)
```
```c++
#include "VeloxDB/VeloxDB.h"
// Scan for key-value pairs within a range
auto MyDB = std::make_unique<VeloxDB>();
MyDB->Open("database_name");
// Scan by key
std::set<KeyValueWrapper> results = MyDB->Scan(1, 10);
std::vector<KeyValueWrapper> results = MyDB->Scan(1, 10);
// Scan by `KeyValueWrapper` instance
std::set<KeyValueWrapper> results = MyDB->Scan(KeyValueWrapper(1, ""), KeyValueWrapper(10, ""));
std::vector<KeyValueWrapper> results = MyDB->Scan(KeyValueWrapper(1, ""), KeyValueWrapper(10, ""));
```
#### **_VeloxDB::Update(KeyValueWrapper KeyToUpdate)_** (TBA)
This will allow the updating of key-value pairs within the database.
#### **_Template<typename K, typename V> VeloxDB::Update(K Key, V Value)_**
This will allow the updating of key-value pairs within the database.
#### **_VeloxDB::Delete(KeyValueWrapper Key)_** (TBA)
This will allow the deletion of key-value pairs from the database.
(_VeloxDB::Put_ actually would achieve the same result)
```c++
template<typename K, typename V>
int VeloxDB::Update(K key, V value)
```
```c++
#include "VeloxDB/VeloxDB.h"
// Example of inserting different data types
auto MyDB = std::make_unique<VeloxDB>();
MyDB->Open("database_name");
int Key = 1;
MyDB->Put(Key, 100); // int -> int
// update values with 'A'
if(MyDB->Update(Key, 'A')){
// success update
}else{
// No pair found by Key
}
// update values with "Hello World"
MyDB->Update(Key, "Hello World");
```
#### **_Template<typename K> VeloxDB::Delete(K Key)_**
This will allow the deletion of key-value pair from the database.
It will delete the kv pair by insert a new kv pair with the largest sequential number and
set `Tombstone` to `true`. It will not been saved into SST file by the next **`Merge`** Operation
inside LSM Tree structure.
```c++
template<typename K>
void VeloxDB::Delete(K key)
```
```c++
#include "VeloxDB/VeloxDB.h"
// Example of inserting different data types
auto MyDB = std::make_unique<VeloxDB>();
MyDB->Open("database_name");
int Key = 1;
MyDB->Put(Key, 100); // int -> int
// delete values with 'A'
MyDB->Delete(Key); // equal to MyDB->Put(Key, 'A');
```
### [**Buffer Pool Operation**](https://kkli08.github.io/VeloxDB/api/#buffer-pool-operation)
Expand Down
22 changes: 22 additions & 0 deletions VeloxDB/VeloxDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,27 @@ std::vector<KeyValueWrapper> VeloxDB::Scan(const KeyValueWrapper& small_key, con
return vectorResult;
}

// Delete method
void VeloxDB::Delete(KeyValueWrapper& keyValueWrapper) {
check_if_open();
keyValueWrapper.setTombstone(true);
lsmTree->put(keyValueWrapper);
}

// Update method
int VeloxDB::Update(const KeyValueWrapper& keyValueWrapper) {
check_if_open();
KeyValueWrapper seached_pair = lsmTree->get(keyValueWrapper);

if (seached_pair.isDefault()) {
cerr << "Failed to update database, No pair found with: " << endl;
keyValueWrapper.printKeyValue();
return 0;
}
lsmTree->put(keyValueWrapper);
return 1;
}

// Helper function to set path
void VeloxDB::set_path(const fs::path& db_path) {
path = db_path;
Expand All @@ -106,6 +127,7 @@ void VeloxDB::setBufferPoolParameters(size_t capacity, EvictionPolicy policy) {

// Set buffer pool parameters in LSMTree or underlying components
// TODO: Implement buffer pool parameters in LSMTree components

}

// Print cache hit information
Expand Down
13 changes: 13 additions & 0 deletions VeloxDB/VeloxDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ class VeloxDB {
template<typename K1, typename K2>
std::vector<KeyValueWrapper> Scan(K1 small_key, K2 large_key);

// DELETE
void Delete(KeyValueWrapper& keyValueWrapper);
// Overloaded Delete method (takes a key and uses it for lookup)
template<typename K>
void Delete(K key);

// UPDATE
int Update(const KeyValueWrapper& keyValueWrapper);
// Overloaded Update method (takes a key and uses it for lookup)
template<typename K, typename V>
int Update(K key, V value);


// Set buffer pool parameters
void setBufferPoolParameters(size_t capacity, EvictionPolicy policy);
void printCacheHit() const;
Expand Down
18 changes: 18 additions & 0 deletions VeloxDB/VeloxDB.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,21 @@ std::vector<KeyValueWrapper> VeloxDB::Scan(K1 small_key, K2 large_key) {
KeyValueWrapper kvLargeKey(large_key, "");
return Scan(kvSmallKey, kvLargeKey);
}

// Overloaded Delete method to simplify retrieval by passing a key directly
template<typename K>
void VeloxDB::Delete(K key) {
check_if_open();
// Convert the key to a KeyValueWrapper and call the existing Get method
KeyValueWrapper kvWrapper(key, "");
return Delete(kvWrapper);
}

// Overloaded Update method to simplify retrieval by passing a key directly
template<typename K, typename V>
int VeloxDB::Update(K key, V value) {
check_if_open();
// Convert the key to a KeyValueWrapper and call the existing Get method
KeyValueWrapper kvWrapper(key, value);
return Update(kvWrapper);
}
78 changes: 54 additions & 24 deletions documentation/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,12 @@ MyDB->Close(); // close

### Data Operations

#### **_Template<typename K, typename V> VeloxDB::Put(K key, V value)_**
Inserts a key-value pair into the database, where both the key and value can be of various types (int, double, string, etc.).

```c++
#include "VeloxDB/VeloxDB.h"
// Example of inserting different data types
auto MyDB = std::make_unique<VeloxDB>();
MyDB->Open("database_name");
// put
MyDB->Put(1, 100); // int -> int
MyDB->Put(1.5, 'A'); // double -> char
MyDB->Put("Hello", 1e8LL); // string -> long long
```
#### **_VeloxDB::Get(const KeyValueWrapper& key)_**
Retrieves a value from the database based on the key. Supports multiple data types.
```c++
template<typename K, typename V>
void VeloxDB::Put(K key, V value)
```
```c++
#include "VeloxDB/VeloxDB.h"
#include "kv/KeyValue.h"
Expand All @@ -57,7 +46,7 @@ MyDB->Put(1.5, 'A');
MyDB->Put("Hello", 1e8LL);
// Retrieve the value by key
auto result1 = MyDB->Get("Hello"); // get
auto result1 = MyDB->Get("Hello");
long long value1 = result1.kv.long_value(); // 1e8
string key1 = result1.kv.string_key(); // "Hello"
Expand All @@ -80,27 +69,68 @@ if(result.isEmpty()){
}
```


#### **_VeloxDB::Scan(KeyValueWrapper smallestKey, KeyValueWrapper largestKey)_**
Scans the database for key-value pairs within a specified key range. The results are returned in sorted key order.

```c++
template<typename K1, typename K2>
std::vector<KeyValueWrapper> VeloxDB::Scan(K1 small_key, K2 large_key)
```
```c++
#include "VeloxDB/VeloxDB.h"
// Scan for key-value pairs within a range
auto MyDB = std::make_unique<VeloxDB>();
MyDB->Open("database_name");
// Scan by key
std::set<KeyValueWrapper> results = MyDB->Scan(1, 10); // scan
std::vector<KeyValueWrapper> results = MyDB->Scan(1, 10);
// Scan by `KeyValueWrapper` instance
std::set<KeyValueWrapper> results = MyDB->Scan(KeyValueWrapper(1, ""), KeyValueWrapper(10, ""));
std::vector<KeyValueWrapper> results = MyDB->Scan(KeyValueWrapper(1, ""), KeyValueWrapper(10, ""));
```

#### **_VeloxDB::Update(KeyValueWrapper KeyToUpdate)_**
(TBA)
#### **_Template<typename K, typename V> VeloxDB::Update(K Key, V Value)_**
This will allow the updating of key-value pairs within the database.

#### **_VeloxDB::Delete(KeyValueWrapper Key)_**
(TBA)
This will allow the deletion of key-value pairs from the database.
(_VeloxDB::Put_ actually would achieve the same result)
```c++
template<typename K, typename V>
int VeloxDB::Update(K key, V value)
```
```c++
#include "VeloxDB/VeloxDB.h"
// Example of inserting different data types
auto MyDB = std::make_unique<VeloxDB>();
MyDB->Open("database_name");
int Key = 1;
MyDB->Put(Key, 100); // int -> int
// update values with 'A'
if(MyDB->Update(Key, 'A')){
// success update
}else{
// No pair found by Key
}
// update values with "Hello World"
MyDB->Update(Key, "Hello World");
```

#### **_Template<typename K> VeloxDB::Delete(K Key)_**
This will allow the deletion of key-value pair from the database.
It will delete the kv pair by insert a new kv pair with the largest sequential number and
set `Tombstone` to `true`. It will not been saved into SST file by the next **`Merge`** Operation
inside LSM Tree structure.
```c++
template<typename K>
void VeloxDB::Delete(K key)
```
```c++
#include "VeloxDB/VeloxDB.h"
// Example of inserting different data types
auto MyDB = std::make_unique<VeloxDB>();
MyDB->Open("database_name");
int Key = 1;
MyDB->Put(Key, 100); // int -> int
// delete values with 'A'
MyDB->Delete(Key); // equal to MyDB->Put(Key, 'A');
```

### **Buffer Pool Operation**

Expand Down
Loading

0 comments on commit 6462de1

Please sign in to comment.