108 lines
2.8 KiB
C++
108 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include <shared_mutex>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <mutex>
|
|
#include <iostream>
|
|
#include <map>
|
|
|
|
/* Max read size is 3MB every time */
|
|
#define MAX_READ_SIZE (3*1024*1024)
|
|
|
|
/* Max write size is 3MB every time */
|
|
#define MAX_WRITE_SIZE (3*1024*1024)
|
|
|
|
/* Port number for target URL */
|
|
#define SERVER_PORT (12344)
|
|
|
|
#define COMMIT_NUM_INVALID (0)
|
|
|
|
#define DUM_FD_START (0xDEADBEEF)
|
|
|
|
#define RPC_TIMEOUT_MS (5000)
|
|
|
|
#define FILE_NAME_DELIMITER (':')
|
|
|
|
|
|
struct WriteEntry
|
|
{
|
|
uint64_t offset;
|
|
uint32_t size;
|
|
uint32_t commit_num;
|
|
char *buffer;
|
|
};
|
|
|
|
struct WriteLog
|
|
{
|
|
std::mutex lock;
|
|
std::vector<WriteEntry *> entries;
|
|
/* The commit number is to signal clients up to what commit it can safely delete
|
|
* This is because in case of commit IO failure, client would know what are committed and
|
|
* what are not so client doesn't resend already-committed writes
|
|
*/
|
|
uint32_t latest_commit;
|
|
|
|
WriteLog()
|
|
{
|
|
latest_commit = 1;
|
|
}
|
|
};
|
|
|
|
struct WSessionInfo
|
|
{
|
|
/* global map from client to filename to commit history */
|
|
std::shared_mutex log_lk;
|
|
std::map<std::string, WriteLog *> log_map;
|
|
|
|
WriteLog* get_write_log(const std::string& path)
|
|
{
|
|
WriteLog* log = nullptr;
|
|
bool free = false;
|
|
|
|
log_lk.lock_shared();
|
|
if (log_map.count(path) != 0) {
|
|
log = log_map[path];
|
|
}
|
|
|
|
log_lk.unlock_shared();
|
|
|
|
if (log == nullptr) {
|
|
|
|
std::cout << "Creating new WriteLog for " << path << std::endl;
|
|
log = new WriteLog;
|
|
|
|
log_lk.lock();
|
|
if (log_map.count(path) == 0) {
|
|
log_map[path] = log;
|
|
} else {
|
|
free = true;
|
|
log = log_map[path];
|
|
}
|
|
log_lk.unlock();
|
|
|
|
if (free) {
|
|
delete log;
|
|
}
|
|
|
|
} else {
|
|
std::cout << "Found existing WriteLog for " << path << std::endl;
|
|
}
|
|
|
|
return log;
|
|
}
|
|
|
|
/* Wsession is used to identify whether the server has failed.
|
|
* wsession is generated every time the server starts, and it's supposed to be unique
|
|
* for distinct server instances. Clients query for this session number upon init
|
|
* If a server has failed and restarted then it acknowledges commits even when there
|
|
* is nothing to commit. After receiving invalid wsession a client is expected to update
|
|
* its stored wsession number resent all writes stored for the file */
|
|
uint64_t wsession;
|
|
|
|
WSessionInfo()
|
|
{
|
|
wsession = (uint64_t) std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
std::chrono::system_clock::now().time_since_epoch()).count();
|
|
}
|
|
}; |