Skip to content
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
Binary file modified btree_test
Binary file not shown.
Binary file added content_addressable_demo
Binary file not shown.
Binary file modified content_hash_demo
Binary file not shown.
Binary file added deduplication_demo
Binary file not shown.
6 changes: 5 additions & 1 deletion include/btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include<string>
#include "fraction.h"
#include "page_manager.h"
#include "content_storage.h"

/*
* BTree that stores the BTreeNodes, ensures it is balanced
Expand All @@ -16,6 +17,8 @@ class BTree {
private:
Page<KeyType>* root;
int maxKeysPerNode; // Maximum keys in each node
ContentStorage<KeyType> content_storage;

void insertNonFull(Page<KeyType>* root, const KeyType& key, const ValueType& value);
void splitChild(Page<KeyType>* parent, int index, Page<KeyType>* child);

Expand All @@ -25,10 +28,11 @@ class BTree {
void mergeNodes(Page<KeyType>* parent, int index);

public:
BTree(int maxKeys); // Constructor declaration
BTree(int maxKeys);
void insert(const KeyType& key, const ValueType& value);
void deleteKey(const KeyType& key);
ValueType* search(const KeyType& key); // Public search method
void printStorageStats() const;

Page<KeyType> findKey(Page<KeyType>* node, const KeyType& key);

Expand Down
100 changes: 100 additions & 0 deletions include/content_storage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <memory>
#include <string>
#include <iostream>
#include "page_manager.h"

template <typename KeyType>
class ContentStorage {
private:
// Map content hash to actual page data
std::unordered_map<std::string, std::shared_ptr<Page<KeyType>>> content_map;

// Map page ID to content hash for reverse lookup
std::unordered_map<uint16_t, std::string> page_to_hash;

// Next available page ID
uint16_t next_page_id = 1;

public:
// Store a page and return its page ID
uint16_t storePage(const Page<KeyType>& page) {
// Update the page's content hash
Page<KeyType> page_copy = page;
page_copy.updateContentHash();
std::string content_hash = page_copy.getContentHash();

// Check if we already have this content
auto it = content_map.find(content_hash);
if (it != content_map.end()) {
// Content already exists, return existing page ID
std::cout << "Deduplication: Found existing content with hash " << content_hash
<< ", reusing page ID " << it->second->header.page_id << std::endl;
return it->second->header.page_id;
}

// New content, assign a new page ID
page_copy.header.page_id = next_page_id++;
page_to_hash[page_copy.header.page_id] = content_hash;
content_map[content_hash] = std::make_shared<Page<KeyType>>(page_copy);

std::cout << "Stored new content with hash " << content_hash
<< " as page ID " << page_copy.header.page_id << std::endl;
return page_copy.header.page_id;
}

// Retrieve a page by its page ID
std::shared_ptr<Page<KeyType>> getPage(uint16_t page_id) {
auto hash_it = page_to_hash.find(page_id);
if (hash_it == page_to_hash.end()) {
return nullptr; // Page not found
}

auto content_it = content_map.find(hash_it->second);
if (content_it == content_map.end()) {
return nullptr; // Content not found (shouldn't happen)
}

return content_it->second;
}

// Get statistics about storage usage
void printStats() const {
std::cout << "\n=== Content Storage Statistics ===" << std::endl;
std::cout << "Total unique content blocks: " << content_map.size() << std::endl;
std::cout << "Total page IDs assigned: " << page_to_hash.size() << std::endl;
std::cout << "Next available page ID: " << next_page_id << std::endl;

if (content_map.size() > 0) {
size_t total_keys = 0;
size_t total_data = 0;
for (const auto& pair : content_map) {
total_keys += pair.second->keys.size();
total_data += pair.second->data.size();
}
std::cout << "Total keys stored: " << total_keys << std::endl;
std::cout << "Total data bytes: " << total_data << std::endl;
}
std::cout << "===================================" << std::endl;
}

// Check if a page with given content already exists
bool hasContent(const Page<KeyType>& page) {
Page<KeyType> page_copy = page;
page_copy.updateContentHash();
return content_map.find(page_copy.getContentHash()) != content_map.end();
}

// Get the page ID for existing content
uint16_t getPageIdForContent(const Page<KeyType>& page) {
Page<KeyType> page_copy = page;
page_copy.updateContentHash();
auto it = content_map.find(page_copy.getContentHash());
if (it != content_map.end()) {
return it->second->header.page_id;
}
return 0;
}
};
32 changes: 29 additions & 3 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,22 @@ OBJECTS = $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEMO_SOURCES = src/Btree.cpp src/content_hash_demo.cpp src/page_manager.cpp
DEMO_OBJECTS = $(DEMO_SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)

# Content addressable demo
ADDRESSABLE_SOURCES = src/Btree.cpp src/content_addressable_demo.cpp src/page_manager.cpp
ADDRESSABLE_OBJECTS = $(ADDRESSABLE_SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)

# Deduplication demo
DEDUP_SOURCES = src/Btree.cpp src/deduplication_demo.cpp src/page_manager.cpp
DEDUP_OBJECTS = $(DEDUP_SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)

# Target executables
TARGET = btree_test
DEMO_TARGET = content_hash_demo
ADDRESSABLE_TARGET = content_addressable_demo
DEDUP_TARGET = deduplication_demo

# Default target
all: $(TARGET) $(DEMO_TARGET)
all: $(TARGET) $(DEMO_TARGET) $(ADDRESSABLE_TARGET) $(DEDUP_TARGET)

# Create object directory if it doesn't exist
$(OBJDIR):
Expand All @@ -34,9 +44,17 @@ $(TARGET): $(OBJECTS)
$(DEMO_TARGET): $(DEMO_OBJECTS)
$(CXX) $(DEMO_OBJECTS) -o $(DEMO_TARGET)

# Link addressable demo executable
$(ADDRESSABLE_TARGET): $(ADDRESSABLE_OBJECTS)
$(CXX) $(ADDRESSABLE_OBJECTS) -o $(ADDRESSABLE_TARGET)

# Link deduplication demo executable
$(DEDUP_TARGET): $(DEDUP_OBJECTS)
$(CXX) $(DEDUP_OBJECTS) -o $(DEDUP_TARGET)

# Clean build files
clean:
rm -rf $(OBJDIR) $(TARGET) $(DEMO_TARGET)
rm -rf $(OBJDIR) $(TARGET) $(DEMO_TARGET) $(ADDRESSABLE_TARGET) $(DEDUP_TARGET)

# Run the test
run: $(TARGET)
Expand All @@ -46,4 +64,12 @@ run: $(TARGET)
demo: $(DEMO_TARGET)
./$(DEMO_TARGET)

.PHONY: all clean run demo
# Run the addressable demo
addressable: $(ADDRESSABLE_TARGET)
./$(ADDRESSABLE_TARGET)

# Run the deduplication demo
dedup: $(DEDUP_TARGET)
./$(DEDUP_TARGET)

.PHONY: all clean run demo addressable dedup
Loading
Loading