Add fetchSublist method to BinaryTable for improved data retrieval

This commit is contained in:
ImBenji
2025-10-10 12:37:34 +01:00
parent cf983c8d96
commit b15d11a5a4
11 changed files with 2362 additions and 611 deletions

View File

@@ -0,0 +1,50 @@
#include <iostream>
#include <filesystem>
#include "../binary_table.h"
void printAddressTable(bt::BinaryTable& table) {
// We can't access getAddressTable directly, so let's use a different approach
// Try to retrieve all known keys and see what happens
std::vector<std::string> keys = {"key1", "key2", "key3"};
for (const std::string& key : keys) {
try {
auto ref = table.getReference(key);
std::cout << " " << key << " -> address " << ref.getPointer().address()
<< " (type " << static_cast<int>(ref.getType()) << ")" << std::endl;
} catch (const std::exception& e) {
std::cout << " " << key << " -> ERROR: " << e.what() << std::endl;
}
}
}
int main() {
using namespace bt;
const std::string filename = "debug_addr_table.bin";
if (std::filesystem::exists(filename)) {
std::filesystem::remove(filename);
}
BinaryTable table(filename);
table.initialize();
std::cout << "=== Testing Address Table Corruption ===\n" << std::endl;
std::cout << "Initial state (empty):" << std::endl;
printAddressTable(table);
std::cout << "\n1. After storing key1:" << std::endl;
table.set<int32_t>("key1", 100);
printAddressTable(table);
std::cout << "\n2. After storing key2:" << std::endl;
table.set<int32_t>("key2", 200);
printAddressTable(table);
std::cout << "\n3. After storing key3:" << std::endl;
table.set<int32_t>("key3", 300);
printAddressTable(table);
return 0;
}

61
cpp/debug/debug_alloc.cpp Normal file
View File

@@ -0,0 +1,61 @@
#include <iostream>
#include <filesystem>
#include "../binary_table.h"
int main() {
using namespace bt;
const std::string filename = "debug_alloc.bin";
if (std::filesystem::exists(filename)) {
std::filesystem::remove(filename);
}
BinaryTable table(filename);
table.initialize();
std::cout << "=== Testing Memory Allocation Issues ===\n" << std::endl;
// Store first key and see what address it gets
std::cout << "1. Storing first key..." << std::endl;
table.set<int32_t>("key1", 100);
// Get the address where key1's value was stored
auto addressTable1 = table.getReference("key1").getPointer();
std::cout << " key1 value stored at: " << addressTable1.address() << std::endl;
// Store second key and see what addresses are used
std::cout << "2. Storing second key..." << std::endl;
table.set<int32_t>("key2", 200);
auto addressTable2 = table.getReference("key2").getPointer();
std::cout << " key2 value stored at: " << addressTable2.address() << std::endl;
// Check if key1 is still accessible
std::cout << "3. Checking if key1 is still accessible..." << std::endl;
try {
int32_t val1 = table.get<int32_t>("key1");
std::cout << " ✅ key1 still works: " << val1 << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ key1 broken: " << e.what() << std::endl;
// Let's see what's actually stored at key1's address
try {
auto ref = table.getReference("key1");
std::cout << " key1 type is: " << static_cast<int>(ref.getType()) << std::endl;
} catch (const std::exception& e2) {
std::cout << " Can't even get type: " << e2.what() << std::endl;
}
}
std::cout << "\n=== Address Comparison ===\n" << std::endl;
std::cout << "key1 address: " << addressTable1.address() << std::endl;
std::cout << "key2 address: " << addressTable2.address() << std::endl;
if (addressTable1.address() == addressTable2.address()) {
std::cout << "💥 SAME ADDRESS! This proves the bug!" << std::endl;
} else {
std::cout << "Addresses are different, issue is elsewhere" << std::endl;
}
return 0;
}

View File

@@ -0,0 +1,69 @@
#include <iostream>
#include <filesystem>
#include "../binary_table.h"
int main() {
using namespace bt;
const std::string filename = "debug_multi.bin";
if (std::filesystem::exists(filename)) {
std::filesystem::remove(filename);
}
BinaryTable table(filename);
table.initialize();
std::cout << "=== Testing Multi-Key Storage ===" << std::endl;
// Store first key
std::cout << "1. Storing first key..." << std::endl;
table.set<int32_t>("key1", 100);
// Try to read it back
try {
int32_t val1 = table.get<int32_t>("key1");
std::cout << " ✅ First key retrieved: " << val1 << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ First key failed: " << e.what() << std::endl;
return 1;
}
// Store second key - this is where it likely breaks
std::cout << "2. Storing second key..." << std::endl;
table.set<int32_t>("key2", 200);
// Try to read second key
try {
int32_t val2 = table.get<int32_t>("key2");
std::cout << " ✅ Second key retrieved: " << val2 << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ Second key failed: " << e.what() << std::endl;
}
// Try to read first key again - this will likely fail
std::cout << "3. Re-reading first key..." << std::endl;
try {
int32_t val1_again = table.get<int32_t>("key1");
std::cout << " ✅ First key still accessible: " << val1_again << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ First key now broken: " << e.what() << std::endl;
std::cout << " 💥 CONFIRMED: Table breaks after storing 2+ keys!" << std::endl;
}
// Store third key to see if pattern continues
std::cout << "4. Storing third key..." << std::endl;
try {
table.set<int32_t>("key3", 300);
int32_t val3 = table.get<int32_t>("key3");
std::cout << " ✅ Third key works: " << val3 << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ Third key failed: " << e.what() << std::endl;
}
std::cout << "\n=== Conclusion ===" << std::endl;
std::cout << "The issue is definitely in the address table management" << std::endl;
std::cout << "when storing multiple keys. Single key = perfect," << std::endl;
std::cout << "multiple keys = corruption." << std::endl;
return 0;
}

View File

@@ -0,0 +1,47 @@
#include <iostream>
#include <filesystem>
#include "../binary_table.h"
int main() {
using namespace bt;
const std::string filename = "debug_simple.bin";
if (std::filesystem::exists(filename)) {
std::filesystem::remove(filename);
}
BinaryTable table(filename);
table.initialize();
std::cout << "1. Storing key1..." << std::endl;
table.set<int32_t>("key1", 100);
std::cout << "2. Reading key1..." << std::endl;
try {
int32_t val = table.get<int32_t>("key1");
std::cout << " ✅ key1 = " << val << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ key1 failed: " << e.what() << std::endl;
}
std::cout << "3. Storing key2..." << std::endl;
table.set<int32_t>("key2", 200);
std::cout << "4. Reading key2..." << std::endl;
try {
int32_t val = table.get<int32_t>("key2");
std::cout << " ✅ key2 = " << val << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ key2 failed: " << e.what() << std::endl;
}
std::cout << "5. Re-reading key1..." << std::endl;
try {
int32_t val = table.get<int32_t>("key1");
std::cout << " ✅ key1 = " << val << std::endl;
} catch (const std::exception& e) {
std::cout << " ❌ key1 failed: " << e.what() << std::endl;
}
return 0;
}

View File

@@ -0,0 +1,105 @@
#include <iostream>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include "../binary_table.h"
void dumpFile(const std::string& filename) {
std::ifstream file(filename, std::ios::binary);
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> data(size);
file.read(reinterpret_cast<char*>(data.data()), size);
std::cout << "File size: " << size << " bytes" << std::endl;
for (size_t i = 0; i < std::min(size, size_t(80)); i++) {
if (i % 16 == 0) std::cout << std::hex << i << ": ";
std::cout << std::hex << std::setfill('0') << std::setw(2) << (int)data[i] << " ";
if (i % 16 == 15) std::cout << std::endl;
}
if (size % 16 != 0) std::cout << std::endl;
}
int main() {
using namespace bt;
const std::string filename = "debug_step.bin";
if (std::filesystem::exists(filename)) {
std::filesystem::remove(filename);
}
BinaryTable table(filename);
table.initialize();
std::cout << "=== Step-by-step Address Table Debug ===\n" << std::endl;
std::cout << "After initialize():" << std::endl;
dumpFile(filename);
std::cout << "\n1. Before storing key1:" << std::endl;
// Try reading the address table header
{
std::ifstream file(filename, std::ios::binary);
int64_t addr;
file.read(reinterpret_cast<char*>(&addr), 8);
std::cout << "Address table pointer: " << addr << std::endl;
}
std::cout << "\n2. Storing key1..." << std::endl;
table.set<int32_t>("key1", 100);
std::cout << "After storing key1:" << std::endl;
dumpFile(filename);
// Try reading the address table
{
std::ifstream file(filename, std::ios::binary);
int64_t addr;
file.read(reinterpret_cast<char*>(&addr), 8);
std::cout << "Address table pointer: " << addr << std::endl;
if (addr != -1) {
file.seekg(addr);
uint8_t type;
int32_t count;
file.read(reinterpret_cast<char*>(&type), 1);
file.read(reinterpret_cast<char*>(&count), 4);
std::cout << "Address table type: " << (int)type << ", count: " << count << std::endl;
}
}
std::cout << "\n3. Storing key2..." << std::endl;
table.set<int32_t>("key2", 200);
std::cout << "After storing key2:" << std::endl;
dumpFile(filename);
// Try reading the address table again
{
std::ifstream file(filename, std::ios::binary);
int64_t addr;
file.read(reinterpret_cast<char*>(&addr), 8);
std::cout << "Address table pointer: " << addr << std::endl;
if (addr != -1) {
file.seekg(addr);
uint8_t type;
int32_t count;
file.read(reinterpret_cast<char*>(&type), 1);
file.read(reinterpret_cast<char*>(&count), 4);
std::cout << "Address table type: " << (int)type << ", count: " << count << std::endl;
// Read the entries
for (int32_t i = 0; i < count && i < 5; i++) {
int64_t keyHash, valueAddr;
file.read(reinterpret_cast<char*>(&keyHash), 8);
file.read(reinterpret_cast<char*>(&valueAddr), 8);
std::cout << "Entry " << i << ": hash=" << keyHash << ", addr=" << valueAddr << std::endl;
}
}
}
return 0;
}