diff --git a/src/include/engine.h b/src/include/engine.h index 24febf9..bcf23b3 100644 --- a/src/include/engine.h +++ b/src/include/engine.h @@ -10,6 +10,7 @@ #include "data.h" #include "stop_register.hpp" #include "storage/disk_map.hpp" +#include "transaction_mainenance.hpp" #include "utils.h" class TicketSystemEngine { #ifdef ENABLE_ADVANCED_FEATURE @@ -47,6 +48,7 @@ class TicketSystemEngine { * optimization, storing IDs pointing to order information */ StopRegister stop_register; + TransactionManager transaction_manager; void PrepareExit(); @@ -63,7 +65,9 @@ class TicketSystemEngine { core_train_data_storage("core_train.idx", data_directory + "/core_train.idx", "core_train.val", data_directory + "/core_train.val"), seats_data_storage("seats.idx", data_directory + "/seats.idx", "seats.val", data_directory + "/seats.val"), - stop_register("stop_register.idx", data_directory + "/stop_register.idx") {} + stop_register("stop_register.idx", data_directory + "/stop_register.idx"), + transaction_manager("txn.data", data_directory + "/txn.data", "queue.idx", data_directory + "/queue.idx", + "order.idx", data_directory + "/order.idx") {} std::string Execute(const std::string &command); // User system diff --git a/src/include/stop_register.hpp b/src/include/stop_register.hpp index da69b22..ed62e06 100644 --- a/src/include/stop_register.hpp +++ b/src/include/stop_register.hpp @@ -7,6 +7,7 @@ #include "storage/bpt.hpp" #include "storage/buffer_pool_manager.h" #include "storage/driver.h" +#include "utils.h" struct stop_register_t { hash_t station_ID_hash; hash_t train_ID_hash; @@ -155,6 +156,46 @@ class StopRegister : public DataDriverBase { ++it_from; } } + inline StopRegister::DirectTrainInfo RequestSingleTrain(hash_t train_ID_hash, int date, hash_t from_station_hash, + hash_t to_station_hash, bool &success) { + const static int June_1st_2024 = 152; + auto it_from = bpt_indexer->lower_bound_const({from_station_hash, train_ID_hash, 1}); + auto it_to = bpt_indexer->lower_bound_const({to_station_hash, train_ID_hash, 0}); + if (it_from == bpt_indexer->end_const() || it_to == bpt_indexer->end_const()) { + success = false; + return {}; + } + const auto &key_from = it_from.GetKey(); + const auto &key_to = it_to.GetKey(); + if (key_from.train_ID_hash != train_ID_hash || key_to.train_ID_hash != train_ID_hash || + key_from.station_ID_hash != from_station_hash || key_to.station_ID_hash != to_station_hash || + key_from.type != 1 || key_to.type != 0) { + success = false; + return {}; + } + const auto &value_from = it_from.GetValue(); + const auto &value_to = it_to.GetValue(); + int true_saleDate_beg = (*reinterpret_cast(&value_from)).saleDate_beg + June_1st_2024; + int true_saleDate_end = (*reinterpret_cast(&value_from)).saleDate_end + June_1st_2024; + int leave_time_offset = (*reinterpret_cast(&value_from)).vis_time_offset; + int startTime = key_from.startTime; + int actual_time = startTime + leave_time_offset; + int delta_days = actual_time / 1440; + if (date - delta_days < true_saleDate_beg || date - delta_days > true_saleDate_end) { + success = false; + return {}; + } + StopRegister::DirectTrainInfo entry; + entry.train_ID_hash = key_from.train_ID_hash; + entry.actual_start_date = date - delta_days; + entry.leave_time_stamp = entry.actual_start_date * 1440 + actual_time; + entry.from_stop_id = key_from.stop_id; + entry.saleDate_beg = true_saleDate_beg; + entry.arrive_time_stamp = entry.actual_start_date * 1440 + startTime + + (*reinterpret_cast(&value_to)).vis_time_offset; + entry.to_stop_id = key_to.stop_id; + return entry; + } }; #endif \ No newline at end of file diff --git a/src/include/transaction_mainenance.hpp b/src/include/transaction_mainenance.hpp new file mode 100644 index 0000000..b90b500 --- /dev/null +++ b/src/include/transaction_mainenance.hpp @@ -0,0 +1,130 @@ +#ifndef TRANSACTION_MAINTENANCE_HPP +#define TRANSACTION_MAINTENANCE_HPP +#include +#include +#include "basic_defs.h" +#include "data.h" +#include "storage/bpt.hpp" +#include "storage/buffer_pool_manager.h" +#include "storage/disk_manager.h" +#include "storage/driver.h" +#include "storage/single_value_storage.hpp" +struct TransactionData { + char trainID[21]; + char from_station_name[41]; + char to_station_name[41]; + uint8_t status; + uint32_t leave_time_stamp; + uint32_t arrive_time_stamp; + uint32_t num; + uint64_t total_price; +}; +class TransactionManager : public DataDriverBase { + struct queue_index_t { + hash_t train_ID_hash; + uint8_t running_offset; + uint32_t id; + inline bool operator<(const queue_index_t &rhs) const { + if (train_ID_hash != rhs.train_ID_hash) return train_ID_hash < rhs.train_ID_hash; + if (running_offset != rhs.running_offset) return running_offset < rhs.running_offset; + return id < rhs.id; + } + }; + struct order_history_index_t { + hash_t user_ID_hash; + uint32_t id; + inline bool operator<(const order_history_index_t &rhs) const { + if (user_ID_hash != rhs.user_ID_hash) return user_ID_hash < rhs.user_ID_hash; + return id > rhs.id; + } + }; + static const uint32_t queue_index_specai_id = 0; + static const uint32_t order_history_index_special_id = -1; + std::string data_file_identifier; + std::string data_file_path; + DiskManager *data_disk_manager; + BufferPoolManager *data_bpm; + SingleValueStorage *data_storage; + std::string queue_file_identifier; + std::string queue_file_path; + DiskManager *queue_disk_manager; + BufferPoolManager *queue_bpm; + BPlusTreeIndexer> *queue_indexer; + std::string order_history_file_identifier; + std::string order_history_file_path; + DiskManager *order_history_disk_manager; + BufferPoolManager *order_history_bpm; + BPlusTreeIndexer> *order_history_indexer; + + public: + // for satety, all the copy/move operations are deleted, please manage it using pointer + inline TransactionManager(TransactionManager &&) = delete; + inline TransactionManager &operator=(TransactionManager &&) = delete; + inline TransactionManager(const TransactionManager &) = delete; + inline TransactionManager &operator=(const TransactionManager &) = delete; + inline TransactionManager(std::string data_file_identifier_, std::string data_file_path_, + std::string queue_file_identifier_, std::string queue_file_path_, + std::string order_history_file_identifier_, std::string order_history_file_path_) + : data_file_identifier(std::move(data_file_identifier_)), + data_file_path(std::move(data_file_path_)), + queue_file_identifier(std::move(queue_file_identifier_)), + queue_file_path(std::move(queue_file_path_)), + order_history_file_identifier(std::move(order_history_file_identifier_)), + order_history_file_path(std::move(order_history_file_path_)) { + data_disk_manager = new DiskManager(data_file_path); + data_bpm = new BufferPoolManager(100, 5, data_disk_manager); + data_storage = new SingleValueStorage(data_bpm); + queue_disk_manager = new DiskManager(queue_file_path); + queue_bpm = new BufferPoolManager(100, 5, queue_disk_manager); + queue_indexer = new BPlusTreeIndexer>(queue_bpm); + order_history_disk_manager = new DiskManager(order_history_file_path); + order_history_bpm = new BufferPoolManager(100, 5, order_history_disk_manager); + order_history_indexer = + new BPlusTreeIndexer>(order_history_bpm); + } + inline ~TransactionManager() { + delete data_storage; + delete data_bpm; + delete data_disk_manager; + delete queue_indexer; + delete queue_bpm; + delete queue_disk_manager; + delete order_history_indexer; + delete order_history_bpm; + delete order_history_disk_manager; + } + inline virtual sjtu::vector ListFiles() override { + sjtu::vector res; + res.push_back({data_file_identifier, data_file_path, data_disk_manager}); + res.push_back({queue_file_identifier, queue_file_path, queue_disk_manager}); + res.push_back({order_history_file_identifier, order_history_file_path, order_history_disk_manager}); + return res; + } + inline virtual void LockDownForCheckOut() override { + delete data_storage; + delete data_bpm; + delete data_disk_manager; + data_storage = nullptr; + data_bpm = nullptr; + data_disk_manager = nullptr; + delete queue_indexer; + delete queue_bpm; + delete queue_disk_manager; + queue_indexer = nullptr; + queue_bpm = nullptr; + queue_disk_manager = nullptr; + delete order_history_indexer; + delete order_history_bpm; + delete order_history_disk_manager; + order_history_indexer = nullptr; + order_history_bpm = nullptr; + order_history_disk_manager = nullptr; + } + inline virtual void Flush() override { + if (data_storage == nullptr) return; + data_storage->Flush(); + queue_indexer->Flush(); + order_history_indexer->Flush(); + } +}; +#endif \ No newline at end of file diff --git a/src/transaction_system.cpp b/src/transaction_system.cpp index 1e70a04..89ac959 100644 --- a/src/transaction_system.cpp +++ b/src/transaction_system.cpp @@ -48,7 +48,6 @@ std::string TicketSystemEngine::QueryTicket(const std::string &command) { } LOG->debug("date {}={}-{}, from {}, to {}, order by {}", date, RetrieveReadableDate(date).first, RetrieveReadableDate(date).second, from, to, order_by); - // TODO hash_t from_hash = SplitMix64Hash(from), to_hash = SplitMix64Hash(to); std::vector valid_trains; stop_register.QueryDirectTrains(date, from_hash, to_hash, valid_trains); @@ -219,7 +218,11 @@ std::string TicketSystemEngine::BuyTicket(const std::string &command) { LOG->debug("user {}, train {}, date {}={}-{}, from {}, to {}, ticket num {}, accept queue {}", user_name, train_id, date, RetrieveReadableDate(date).first, RetrieveReadableDate(date).second, from, to, ticket_num, accept_queue); - // TODO + hash_t user_ID_hash = SplitMix64Hash(user_name); + if (online_users.find(user_ID_hash) == online_users.end()) { + response_stream << "[" << command_id << "] -1"; + return response_stream.str(); + } response_stream << "[" << command_id << "] BuyTicket"; return response_stream.str(); }