Skip to content

Commit

Permalink
load and dump map
Browse files Browse the repository at this point in the history
  • Loading branch information
shuwens committed Oct 28, 2024
1 parent 34334c9 commit 9ef7ef9
Show file tree
Hide file tree
Showing 5 changed files with 365 additions and 31 deletions.
8 changes: 8 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@ executable(
# install: true,
# )

executable(
'test_map',
files('src/tests/map_test.cc'),
dependencies: [zstore_deps] + [dependency('_spdk')],
link_args: spdk_link_args,
install: true,
)

executable(
'test_simple_object',
files('src/tests/simple_object_test.cc'),
Expand Down
23 changes: 17 additions & 6 deletions src/include/zstore_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#include <unistd.h>

namespace net = boost::asio; // from <boost/asio.hpp>
using zstore_map = boost::concurrent_flat_map<ObjectKeyHash, MapEntry>;
using zstore_bloom_filter = boost::concurrent_flat_set<ObjectKeyHash>;
using ZstoreMap = boost::concurrent_flat_map<ObjectKeyHash, MapEntry>;
using ZstoreBloomFilter = boost::concurrent_flat_set<ObjectKeyHash>;

class Device;
class Zone;
Expand All @@ -22,7 +22,13 @@ class ZstoreController
{
public:
int PopulateDevHash();
int PopulateMap(bool bogus);
int PopulateMap();
Result<void> DumpAllMap();
Result<void> ReadAllMap();

void writeMapToFile(const std::string &filename);
void readMapFromFile(const std::string &filename);

// Result<void> PopulateMap(bool bogus, int key_experiment);
// Result<void> PopulateDevHash(int key_experiment);

Expand All @@ -38,14 +44,14 @@ class ZstoreController
std::shared_mutex mDevHashMutex;

// ZStore Map: this maps key to tuple of ZNS target and lba
zstore_map mMap;
ZstoreMap mMap;

// ZStore Bloom Filter: this maintains a bloom filter of hashes of
// object name (key).
//
// For simplicity, right now we are just using a set to keep track of
// the hashes
zstore_bloom_filter mBF;
ZstoreBloomFilter mBF;

// Object APIs
Result<bool> SearchBF(const ObjectKeyHash &key_hash);
Expand All @@ -64,7 +70,7 @@ class ZstoreController
net::io_context &mIoc_;

~ZstoreController();
int Init(bool object, int key_experiment);
int Init(bool object, int key_experiment, int phase);

// threads
void initIoThread();
Expand All @@ -83,6 +89,7 @@ class ZstoreController
int GetQueueDepth() { return mQueueDepth; };
void setQueuDepth(int queue_depth) { mQueueDepth = queue_depth; };
void setKeyExperiment(int key) { mKeyExperiment = key; };
void setPhase(int phase) { mPhase = phase; };

void SetEventPoller(spdk_poller *p) { mEventsPoller = p; }
void SetCompletionPoller(spdk_poller *p) { mCompletionPoller = p; }
Expand Down Expand Up @@ -218,6 +225,10 @@ class ZstoreController
// 6: GC
// 7: Checkpoint

int mPhase;
// 1: prepare
// 2: run

private:
// number of devices
int mN;
Expand Down
47 changes: 27 additions & 20 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "include/zstore_controller.h"
#include "spdk/env.h"
#include "spdk/thread.h"
#include "src/include/utils.h"
#include <bits/stdc++.h>
#include <boost/asio/executor_work_guard.hpp>
#include <cassert>
Expand All @@ -21,7 +22,7 @@ int main(int argc, char **argv)
}

int key_experiment = std::stoull(argv[1]);
int dummy = std::stoull(argv[2]);
int phase = std::stoull(argv[2]);

int rc;
struct spdk_env_opts opts;
Expand Down Expand Up @@ -53,30 +54,36 @@ int main(int argc, char **argv)

net::io_context ioc{Configuration::GetNumHttpThreads()};
gZstoreController = new ZstoreController(std::ref(ioc));
gZstoreController->Init(false, key_experiment);
gZstoreController->Init(false, key_experiment, phase);

log_info("Starting HTTP server with port 2000!\n");

// gZstoreController->mIoc_.run();
// FIXME only tput on Zstore2Dev1
while (1) {
// auto etime = std::chrono::high_resolution_clock::now();
// auto delta =
// std::chrono::duration_cast<std::chrono::microseconds>(
// etime - gZstoreController->stime)
// .count();
// auto tput =
// gZstoreController->mTotalCounts * g_micro_to_second /
// delta;
//
// log_info("Total IO {}, total time {}ms, throughput {} IOPS",
// gZstoreController->mTotalCounts, delta, tput);
// {
// gZstoreController->stime =
// std::chrono::high_resolution_clock::now();
// gZstoreController->mTotalCounts = 0;
// }
sleep(1);
// while (1) {
// auto etime = std::chrono::high_resolution_clock::now();
// auto delta =
// std::chrono::duration_cast<std::chrono::microseconds>(
// etime - gZstoreController->stime)
// .count();
// auto tput =
// gZstoreController->mTotalCounts * g_micro_to_second /
// delta;
//
// log_info("Total IO {}, total time {}ms, throughput {} IOPS",
// gZstoreController->mTotalCounts, delta, tput);
// {
// gZstoreController->stime =
// std::chrono::high_resolution_clock::now();
// gZstoreController->mTotalCounts = 0;
// }
// sleep(1);
// }

sleep(30);
if (gZstoreController->mPhase == 2 && gZstoreController->mPhase == 1) {
log_info("Prepare phase is done, dumping all map and bloom filter");
gZstoreController->DumpAllMap();
}

gZstoreController->Drain();
Expand Down
160 changes: 160 additions & 0 deletions src/tests/map_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include "../include/types.h"
#include "../include/zstore_controller.h"
#include <fstream>
#include <iostream>
#include <string>
#include <tuple>

using namespace std;

// Type definitions
using ObjectKey = std::string;
using ObjectKeyHash = unsigned char *;
using TargetDev = std::string;
using Lba = uint64_t;
using Length = uint32_t;

// Device types and map entry
using TargetLbaTuple = std::tuple<TargetDev, Lba, Length>;
using MapEntry = std::tuple<TargetLbaTuple, TargetLbaTuple, TargetLbaTuple>;
// using MapType = boost::container::concurrent_flat_map<ObjectKeyHash,
// MapEntry>;

// Helper function to write a single string to the file
void writeString(std::ofstream &outFile, const std::string &str)
{
size_t size = str.size();
outFile.write(reinterpret_cast<const char *>(&size), sizeof(size));
outFile.write(str.c_str(), size);
}

// Helper function to read a single string from the file
std::string readString(std::ifstream &inFile)
{
size_t size;
inFile.read(reinterpret_cast<char *>(&size), sizeof(size));
std::string str(size, '\0');
inFile.read(&str[0], size);
return str;
}

// Function to write the map to a file
void writeMapToFile(const ZstoreMap &map, const std::string &filename)
{
std::ofstream outFile(filename, std::ios::binary);
if (!outFile) {
std::cerr << "Error opening file for writing: " << filename
<< std::endl;
return;
}

size_t mapSize = 0;
map.visit_all([&mapSize](auto &x) { ++mapSize; });

// Write the map size
outFile.write(reinterpret_cast<const char *>(&mapSize), sizeof(mapSize));

// Iterate over each key-value pair and write them to the file
map.visit_all([&outFile](auto &x) {
// Serialize the key
outFile.write(reinterpret_cast<const char *>(x.first),
32); // Assuming 32-byte hash

// Serialize the entry
auto writeTargetLbaTuple = [&outFile](const TargetLbaTuple &tuple) {
writeString(outFile, std::get<0>(tuple)); // TargetDev
outFile.write(reinterpret_cast<const char *>(&std::get<1>(tuple)),
sizeof(Lba)); // Lba
outFile.write(reinterpret_cast<const char *>(&std::get<2>(tuple)),
sizeof(Length)); // Length
};
writeTargetLbaTuple(std::get<0>(x.second));
writeTargetLbaTuple(std::get<1>(x.second));
writeTargetLbaTuple(std::get<2>(x.second));
});
}

// Function to read the map from a file
ZstoreMap readMapFromFile(const std::string &filename)
{
std::ifstream inFile(filename, std::ios::binary);
if (!inFile) {
std::cerr << "Error opening file for reading: " << filename
<< std::endl;
return {};
}

ZstoreMap map;
size_t mapSize;
inFile.read(reinterpret_cast<char *>(&mapSize), sizeof(mapSize));

for (size_t i = 0; i < mapSize; ++i) {
// Deserialize the key
unsigned char *key = new unsigned char[32];
inFile.read(reinterpret_cast<char *>(key), 32);

// Deserialize the entry
auto readTargetLbaTuple = [&inFile]() -> TargetLbaTuple {
std::string dev = readString(inFile);
Lba lba;
Length length;
inFile.read(reinterpret_cast<char *>(&lba), sizeof(Lba));
inFile.read(reinterpret_cast<char *>(&length), sizeof(Length));
return std::make_tuple(dev, lba, length);
};

MapEntry entry = std::make_tuple(
readTargetLbaTuple(), readTargetLbaTuple(), readTargetLbaTuple());
map.emplace(key, entry);
}

return map;
}

int main()
{
ZstoreMap mMap;

// Sample data
unsigned char key1[32] = "sample_key_1";
unsigned char key2[32] = "sample_key_2";
MapEntry entry1 = {std::make_tuple("device1", 1000, 256),
std::make_tuple("device2", 2000, 512),
std::make_tuple("device3", 3000, 128)};
MapEntry entry2 = {std::make_tuple("device1", 1500, 128),
std::make_tuple("device2", 2500, 256),
std::make_tuple("device3", 3500, 64)};
mMap.emplace(key1, entry1);
mMap.emplace(key2, entry2);

// Write the map to a file
std::string filename = "mMap_data.bin";
writeMapToFile(mMap, filename);

// Read the map back from the file
ZstoreMap loadedMap = readMapFromFile(filename);

// Print the loaded map
loadedMap.visit_all([](auto &x) {
std::cout << "Key: " << x.first << "\n";
std::tuple<
std::tuple<std::basic_string<char>, unsigned long, unsigned int>,
std::tuple<std::basic_string<char>, unsigned long, unsigned int>,
std::tuple<std::basic_string<char>, unsigned long, unsigned int>>
big_tuple = x.second;
auto first = std::get<0>(big_tuple);
std::cout << " Device: " << std::get<0>(first)
<< ", LBA: " << std::get<1>(first)
<< ", Length: " << std::get<2>(first) << "\n";
auto second = std::get<1>(big_tuple);
std::cout << " Device: " << std::get<0>(second)
<< ", LBA: " << std::get<1>(second)
<< ", Length: " << std::get<2>(second) << "\n";
auto third = std::get<2>(big_tuple);
std::cout << " Device: " << std::get<0>(third)
<< ", LBA: " << std::get<1>(third)
<< ", Length: " << std::get<2>(third) << "\n";
});

return 0;
}
Loading

0 comments on commit 9ef7ef9

Please sign in to comment.