404d217504
- Remove FileManager and related file-based persistence logic - Remove obsolete observer persistence utilities - Remove unused service APIs and includes - Delete duplicate DataStore mutex stubs - Perform general dead-code cleanup
238 lines
9.3 KiB
C++
238 lines
9.3 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"
|
|
#include "User.h"
|
|
#include "Notification.h"
|
|
#include "Service.h"
|
|
#include "ComboPackage.h"
|
|
#include "InventoryItem.h"
|
|
#include "ServiceBooking.h"
|
|
#include "JobCard.h"
|
|
#include "Invoice.h"
|
|
|
|
class DataStore
|
|
{
|
|
private:
|
|
DataStore();
|
|
~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_serviceManagementObservers;
|
|
MappingInfo m_paymentManagementObservers;
|
|
MappingInfo m_inventoryManagementObservers;
|
|
util::Map<std::string, TrackedRecord<User>> m_userCache;
|
|
util::Map<std::string, TrackedRecord<Notification>> m_notificationCache;
|
|
util::Map<std::string, TrackedRecord<Service>> m_serviceCache;
|
|
util::Map<std::string, TrackedRecord<ComboPackage>> m_comboPackageCache;
|
|
util::Map<std::string, TrackedRecord<InventoryItem>> m_inventoryItemCache;
|
|
util::Map<std::string, TrackedRecord<ServiceBooking>> m_serviceBookingCache;
|
|
util::Map<std::string, TrackedRecord<JobCard>> m_jobCardCache;
|
|
util::Map<std::string, TrackedRecord<Invoice>> m_invoiceCache;
|
|
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, User*> getServiceManagementObservers();
|
|
util::Map<std::string, User*> getPaymentManagementObservers();
|
|
util::Map<std::string, User*> getInventoryManagementObservers();
|
|
void saveUsers();
|
|
void saveNotifications();
|
|
void saveServices();
|
|
void saveComboPackages();
|
|
void saveInventoryItems();
|
|
void saveServiceBookings();
|
|
void saveJobCards();
|
|
void saveInvoices();
|
|
void saveServiceManagementObservers(util::Map<std::string, User*>& observers);
|
|
void savePaymentManagementObservers(util::Map<std::string, User*>& observers);
|
|
void saveInventoryManagementObservers(util::Map<std::string, User*>& 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);
|
|
template<typename TObject> void clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache);
|
|
template<typename TObject> void refreshCache(util::Map<std::string, TrackedRecord<TObject>>&cache, util::Map<std::string, TrackedRecord<TObject>>&refreshedCache);
|
|
util::Map<std::string, User*> getObservers(MappingInfo& mapping);
|
|
void saveObservers(MappingInfo& mapping, util::Map<std::string, User*>& observers);
|
|
};
|
|
|
|
/*
|
|
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.
|
|
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);
|
|
record.slotIndex = recordCount;
|
|
}
|
|
record.state = RecordState::CLEAN;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: clearCache
|
|
Description: Releases all objects owned by the cache and
|
|
clears the cache contents.
|
|
Parameters:
|
|
- cache: Cache to be cleared.
|
|
Returns:
|
|
- None
|
|
*/
|
|
template<typename TObject>
|
|
void DataStore::clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache)
|
|
{
|
|
for (int index = 0; index < cache.getSize(); ++index)
|
|
{
|
|
delete cache.getValueAt(index).data;
|
|
cache.getValueAt(index).data = nullptr;
|
|
}
|
|
cache.clear();
|
|
}
|
|
|
|
/*
|
|
Function: refreshCache
|
|
Description: Refreshes the cache while preserving object addresses
|
|
for records that already exist. Existing objects are
|
|
updated in-place so that pointers held elsewhere remain
|
|
valid after the refresh.
|
|
Parameters:
|
|
- cache: Existing cache to refresh.
|
|
- refreshedCache: Newly loaded cache contents.
|
|
Returns:
|
|
- None
|
|
*/
|
|
template<typename TObject>
|
|
void DataStore::refreshCache(util::Map<std::string, TrackedRecord<TObject>>& cache, util::Map<std::string, TrackedRecord<TObject>>& refreshedCache)
|
|
{
|
|
util::Map<std::string, TrackedRecord<TObject>> oldCache = cache;
|
|
cache.clear();
|
|
for (int index = 0; index < refreshedCache.getSize(); ++index)
|
|
{
|
|
const std::string& id = refreshedCache.getKeyAt(index);
|
|
TrackedRecord<TObject>& refreshedRecord = refreshedCache.getValueAt(index);
|
|
int oldIndex = oldCache.find(id);
|
|
if (oldIndex != -1)
|
|
{
|
|
TrackedRecord<TObject>& oldRecord = oldCache.getValueAt(oldIndex);
|
|
*oldRecord.data = *refreshedRecord.data;
|
|
oldRecord.slotIndex = refreshedRecord.slotIndex;
|
|
oldRecord.state = refreshedRecord.state;
|
|
delete refreshedRecord.data;
|
|
refreshedRecord.data = oldRecord.data;
|
|
}
|
|
cache.insert(id, refreshedRecord);
|
|
}
|
|
for (int index = 0; index < oldCache.getSize(); ++index)
|
|
{
|
|
const std::string& id = oldCache.getKeyAt(index);
|
|
if (cache.find(id) == -1)
|
|
{
|
|
delete oldCache.getValueAt(index).data;
|
|
}
|
|
}
|
|
} |