diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp index e19c524..5f59fc4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp @@ -1,6 +1,34 @@ #include "SharedMemory.h" #include "Config.h" +/* +Function: invalidateMapping +Description: Releases all mapping resources and resets the mapping to an invalid state. +Parameters: + - mapping: MappingInfo&, mapping information and handles +Returns: + - None +*/ +static void invalidateMapping(MappingInfo& mapping) +{ + if (mapping.mappedView != nullptr) + { + UnmapViewOfFile(mapping.mappedView); + mapping.mappedView = nullptr; + } + if (mapping.mappingHandle != NULL) + { + CloseHandle(mapping.mappingHandle); + mapping.mappingHandle = NULL; + } + if (mapping.fileHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(mapping.fileHandle); + mapping.fileHandle = INVALID_HANDLE_VALUE; + } + mapping.mappedCapacity = 0; +} + /* Function: createOrOpenMapping Description: Creates or opens a file mapping and maps it into the process address space. @@ -31,8 +59,7 @@ bool SharedMemory::createOrOpenMapping(MappingInfo& mapping) LARGE_INTEGER fileSize; if (!GetFileSizeEx(mapping.fileHandle, &fileSize)) { - CloseHandle(mapping.fileHandle); - mapping.fileHandle = INVALID_HANDLE_VALUE; + invalidateMapping(mapping); return false; } bool isNewFile = (fileSize.QuadPart == 0); @@ -43,14 +70,12 @@ bool SharedMemory::createOrOpenMapping(MappingInfo& mapping) newSize.QuadPart = sizeof(FileHeader) + initialCapacity * mapping.recordSize; if (!SetFilePointerEx(mapping.fileHandle, newSize, NULL, FILE_BEGIN)) { - CloseHandle(mapping.fileHandle); - mapping.fileHandle = INVALID_HANDLE_VALUE; + invalidateMapping(mapping); return false; } if (!SetEndOfFile(mapping.fileHandle)) { - CloseHandle(mapping.fileHandle); - mapping.fileHandle = INVALID_HANDLE_VALUE; + invalidateMapping(mapping); return false; } } @@ -64,8 +89,7 @@ bool SharedMemory::createOrOpenMapping(MappingInfo& mapping) NULL); if (mapping.mappingHandle == NULL) { - CloseHandle(mapping.fileHandle); - mapping.fileHandle = INVALID_HANDLE_VALUE; + invalidateMapping(mapping); return false; } mapping.mappedView = @@ -77,13 +101,15 @@ bool SharedMemory::createOrOpenMapping(MappingInfo& mapping) 0); if (mapping.mappedView == nullptr) { - CloseHandle(mapping.mappingHandle); - CloseHandle(mapping.fileHandle); - mapping.mappingHandle = NULL; - mapping.fileHandle = INVALID_HANDLE_VALUE; + invalidateMapping(mapping); + return false; + } + FileHeader* header = getHeader(mapping); + if (header == nullptr) + { + invalidateMapping(mapping); return false; } - FileHeader* header = reinterpret_cast(mapping.mappedView); if (isNewFile) { header->recordCount = 0; @@ -103,22 +129,7 @@ Returns: */ void SharedMemory::closeMapping(MappingInfo& mapping) { - if (mapping.mappedView != nullptr) - { - UnmapViewOfFile(mapping.mappedView); - mapping.mappedView = nullptr; - } - if (mapping.mappingHandle != NULL) - { - CloseHandle(mapping.mappingHandle); - mapping.mappingHandle = NULL; - } - if (mapping.fileHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(mapping.fileHandle); - mapping.fileHandle = INVALID_HANDLE_VALUE; - } - mapping.mappedCapacity = 0; + invalidateMapping(mapping); } /* @@ -135,7 +146,6 @@ FileHeader* SharedMemory::getHeader(MappingInfo& mapping) { return nullptr; } - return reinterpret_cast(mapping.mappedView); } @@ -229,3 +239,92 @@ size_t SharedMemory::getCapacity(MappingInfo& mapping) } return header->capacity; } + +/* +Function: resizeMapping +Description: Resizes the file mapping to the specified capacity. +Parameters: + - mapping: MappingInfo&, mapping information and handles + - newCapacity: size_t, new mapping capacity +Returns: + - bool: True if the resize succeeded, otherwise false +*/ +bool SharedMemory::resizeMapping(MappingInfo& mapping, size_t newCapacity) +{ + FileHeader* header = getHeader(mapping); + if (header == nullptr) + { + invalidateMapping(mapping); + return false; + } + header->capacity = newCapacity; + if (!FlushViewOfFile(mapping.mappedView, sizeof(FileHeader))) + { + return false; + } + if (!UnmapViewOfFile(mapping.mappedView)) + { + return false; + } + mapping.mappedView = nullptr; + CloseHandle(mapping.mappingHandle); + mapping.mappingHandle = NULL; + LARGE_INTEGER newSize; + newSize.QuadPart = sizeof(FileHeader) + newCapacity * mapping.recordSize; + if (!SetFilePointerEx(mapping.fileHandle, newSize, NULL, FILE_BEGIN)) + { + invalidateMapping(mapping); + return false; + } + if (!SetEndOfFile(mapping.fileHandle)) + { + invalidateMapping(mapping); + return false; + } + mapping.mappingHandle = + CreateFileMappingA( + mapping.fileHandle, + NULL, + PAGE_READWRITE, + 0, + 0, + NULL); + if (mapping.mappingHandle == NULL) + { + invalidateMapping(mapping); + return false; + } + mapping.mappedView = + MapViewOfFile( + mapping.mappingHandle, + FILE_MAP_ALL_ACCESS, + 0, + 0, + 0); + if (mapping.mappedView == nullptr) + { + invalidateMapping(mapping); + return false; + } + mapping.mappedCapacity = newCapacity; + return true; +} + +/* +Function: ensureCapacityForInsert +Description: Ensures that the mapping has space for at least one additional record, growing it if necessary. +Parameters: + - mapping: MappingInfo&, mapping information and handles +Returns: + - bool: True if capacity is available, otherwise false +*/ +bool SharedMemory::ensureCapacityForInsert(MappingInfo& mapping) +{ + size_t recordCount = getRecordCount(mapping); + size_t capacity = getCapacity(mapping); + if (recordCount < capacity) + { + return true; + } + return resizeMapping(mapping, capacity * 2); +} \ No newline at end of file