e5787dfb98
Changes: - Added SharedMemory module for file-backed memory-mapped storage - Added MappingInfo, FileHeader, RecordState and TrackedRecord infrastructure - Replaced CSV-based serialization with binary struct serialization - Added DataStore initialization and shutdown lifecycle management - Added datastore mutex synchronization for multi-process access - Added shared-memory mapping configuration for all datastore entities - Added generic loadRecords and saveRecords template infrastructure - Added automatic datastore directory creation and .dat file storage - Updated configuration to use binary datastore files and initial capacities - Added enum underlying types for serialization compatibility - Added password masking support for login, registration and password change flows - Added Visual Studio project configuration for shared-memory components - Prepared datastore for multi-process shared-memory persistence
171 lines
7.2 KiB
C++
171 lines
7.2 KiB
C++
/*
|
|
File: DataStore.h
|
|
Description: Declares the DataStore singleton class responsible for managing collections of users, services, combo packages, service bookings, job cards, inventory items, invoices, and payments in the Vehicle Service Management System.
|
|
Author: Trenser
|
|
Date: 19-May-2026
|
|
*/
|
|
|
|
#pragma once
|
|
#include <windows.h>
|
|
#include <string>
|
|
#include "Map.h"
|
|
#include "MappingInfo.h"
|
|
#include "TrackedRecord.h"
|
|
#include "SharedMemory.h"
|
|
class User;
|
|
class Notification;
|
|
class Service;
|
|
class ComboPackage;
|
|
class InventoryItem;
|
|
class ServiceBooking;
|
|
class JobCard;
|
|
class Invoice;
|
|
class Payment;
|
|
|
|
class DataStore
|
|
{
|
|
private:
|
|
DataStore();
|
|
DataStore(const DataStore&) = delete;
|
|
DataStore& operator=(const DataStore&) = delete;
|
|
DataStore(DataStore&&) = delete;
|
|
DataStore& operator=(DataStore&&) = delete;
|
|
HANDLE m_globalMutex;
|
|
MappingInfo m_users;
|
|
MappingInfo m_notifications;
|
|
MappingInfo m_services;
|
|
MappingInfo m_comboPackages;
|
|
MappingInfo m_inventoryItems;
|
|
MappingInfo m_serviceBookings;
|
|
MappingInfo m_jobCards;
|
|
MappingInfo m_invoices;
|
|
MappingInfo m_payments;
|
|
MappingInfo m_serviceManagementObservers;
|
|
MappingInfo m_paymentManagementObservers;
|
|
MappingInfo m_inventoryManagementObservers;
|
|
public:
|
|
static DataStore& getInstance();
|
|
bool initialize();
|
|
void shutdown();
|
|
util::Map<std::string, TrackedRecord<User>> getUsers();
|
|
util::Map<std::string, TrackedRecord<Notification>> getNotifications();
|
|
util::Map<std::string, TrackedRecord<Service>> getServices();
|
|
util::Map<std::string, TrackedRecord<ComboPackage>> getComboPackages();
|
|
util::Map<std::string, TrackedRecord<InventoryItem>> getInventoryItems();
|
|
util::Map<std::string, TrackedRecord<ServiceBooking>> getServiceBookings();
|
|
util::Map<std::string, TrackedRecord<JobCard>> getJobCards();
|
|
util::Map<std::string, TrackedRecord<Invoice>> getInvoices();
|
|
util::Map<std::string, TrackedRecord<Payment>> getPayments();
|
|
util::Map<std::string, TrackedRecord<std::string>> getServiceManagementObservers();
|
|
util::Map<std::string, TrackedRecord<std::string>> getPaymentManagementObservers();
|
|
util::Map<std::string, TrackedRecord<std::string>> getInventoryManagementObservers();
|
|
void saveUsers(util::Map<std::string, TrackedRecord<User>>& users);
|
|
void saveNotifications(util::Map<std::string, TrackedRecord<Notification>>& notifications);
|
|
void saveServices(util::Map<std::string, TrackedRecord<Service>>& services);
|
|
void saveComboPackages(util::Map<std::string, TrackedRecord<ComboPackage>>& comboPackages);
|
|
void saveInventoryItems(util::Map<std::string, TrackedRecord<InventoryItem>>& inventoryItems);
|
|
void saveServiceBookings(util::Map<std::string, TrackedRecord<ServiceBooking>>& bookings);
|
|
void saveJobCards(util::Map<std::string, TrackedRecord<JobCard>>& jobCards);
|
|
void saveInvoices(util::Map<std::string, TrackedRecord<Invoice>>& invoices);
|
|
void savePayments(util::Map<std::string, TrackedRecord<Payment>>& payments);
|
|
void saveServiceManagementObservers(util::Map<std::string, TrackedRecord<std::string>>& observers);
|
|
void savePaymentManagementObservers(util::Map<std::string, TrackedRecord<std::string>>& observers);
|
|
void saveInventoryManagementObservers(util::Map<std::string, TrackedRecord<std::string>>& observers);
|
|
bool lockDataStore();
|
|
bool unlockDataStore();
|
|
private:
|
|
template<typename TObject, typename TSerialized>
|
|
util::Map<std::string, TrackedRecord<TObject>> loadRecords(MappingInfo& mapping);
|
|
template<typename TObject, typename TSerialized>
|
|
void saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records);
|
|
};
|
|
|
|
/*
|
|
Function: loadRecords
|
|
Description: Loads all serialized records from the specified
|
|
shared-memory mapping, deserializes them into
|
|
application objects, and returns them as a map
|
|
of tracked records. Each loaded record is marked
|
|
as CLEAN and assigned its corresponding slot index
|
|
within the mapping so that future modifications
|
|
can be written back efficiently.
|
|
Parameter:
|
|
- mapping: Reference to the mapping containing the
|
|
serialized records.
|
|
Return type:
|
|
util::Map<std::string, TrackedRecord<TObject>>
|
|
A map containing all loaded records keyed by
|
|
their unique identifier.
|
|
*/
|
|
template<typename TObject, typename TSerialized>
|
|
util::Map<std::string, TrackedRecord<TObject>> DataStore::loadRecords(MappingInfo& mapping)
|
|
{
|
|
util::Map<std::string, TrackedRecord<TObject>> records;
|
|
SharedMemory::ensureLatestMapping(mapping);
|
|
size_t recordCount = SharedMemory::getRecordCount(mapping);
|
|
for (size_t index = 0; index < recordCount; ++index)
|
|
{
|
|
TSerialized* serialized = static_cast<TSerialized*>(SharedMemory::getRecordAddress(mapping,index));
|
|
TObject* object = TObject::deserialize(*serialized);
|
|
TrackedRecord<TObject> trackedRecord;
|
|
trackedRecord.data = object;
|
|
trackedRecord.state = RecordState::CLEAN;
|
|
trackedRecord.slotIndex = index;
|
|
records.insert(object->getId(), trackedRecord);
|
|
}
|
|
return records;
|
|
}
|
|
|
|
/*
|
|
Function: saveRecords
|
|
Description: Persists all modified and newly added records
|
|
contained in the provided map to the specified
|
|
shared-memory mapping. Modified records overwrite
|
|
their existing slots, while new records are
|
|
appended to the end of the mapping. Records marked
|
|
as CLEAN are ignored. After persistence, all
|
|
temporary objects owned by the tracked records are
|
|
destroyed to release memory.
|
|
Parameter:
|
|
- mapping: Reference to the mapping where records are
|
|
stored.
|
|
- records: Map containing the records to be persisted.
|
|
Return type: void
|
|
*/
|
|
template<typename TObject, typename TSerialized> void DataStore::saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records)
|
|
{
|
|
SharedMemory::ensureLatestMapping(mapping);
|
|
for (int index = 0; index < records.getSize(); ++index)
|
|
{
|
|
TrackedRecord<TObject>& record = records.getValueAt(index);
|
|
if (record.state == RecordState::CLEAN)
|
|
{
|
|
continue;
|
|
}
|
|
TSerialized serialized = record.data->serialize();
|
|
if (record.state == RecordState::MODIFIED)
|
|
{
|
|
TSerialized* destination = static_cast<TSerialized*>(SharedMemory::getRecordAddress(mapping, record.slotIndex));
|
|
if (destination)
|
|
{
|
|
*destination = serialized;
|
|
}
|
|
}
|
|
else if (record.state == RecordState::NEW_RECORD)
|
|
{
|
|
if (!SharedMemory::ensureCapacityForInsert(mapping))
|
|
{
|
|
continue;
|
|
}
|
|
size_t recordCount = SharedMemory::getRecordCount(mapping);
|
|
TSerialized* destination = static_cast<TSerialized*>(SharedMemory::getRecordAddress(mapping, recordCount));
|
|
*destination = serialized;
|
|
SharedMemory::setRecordCount(mapping, recordCount + 1);
|
|
}
|
|
}
|
|
for (int index = 0; index < records.getSize(); ++index)
|
|
{
|
|
delete records.getValueAt(index).data;
|
|
records.getValueAt(index).data = nullptr;
|
|
}
|
|
} |