Skip to content

Instantly share code, notes, and snippets.

@M0nteCarl0
Created January 23, 2023 17:03
Show Gist options
  • Save M0nteCarl0/58f2be01f260094b65f1b7ed990bde9c to your computer and use it in GitHub Desktop.
Save M0nteCarl0/58f2be01f260094b65f1b7ed990bde9c to your computer and use it in GitHub Desktop.
C++ File RAM Cache implentation for high speed detectors
#include "CriticalSection.h"
CriticalSection::CriticalSection() {
Init();
}
CriticalSection::CriticalSection(const char * Decription) {
Init();
_Description = Decription;
}
const char * CriticalSection::GetDescription(void) {
return _Description.data();
}
CriticalSection::~CriticalSection() {
}
void CriticalSection::Enter(void) {
EnterCriticalSection(&_Sec);
}
void CriticalSection::Leave(void) {
LeaveCriticalSection(&_Sec);
}
void CriticalSection::Init(void) {
InitializeCriticalSection(&_Sec);
}
#ifndef _CS_
#define _CS_
#include <Windows.h>
#include <string>
class CriticalSection {
public:
CriticalSection();
CriticalSection(const char* Decription);
const char* GetDescription(void);
~CriticalSection();
void Enter(void);
void Leave(void);
private:
void Init(void);
CRITICAL_SECTION _Sec;
std::string _Description;
};
#endif
#include "RAM_Cache.h"
RAM_Cache::RAM_Cache(void) {
_MaximumFileInStorage = 0;
_IsFull = 0;
_SizeStorageInBytes = 0;
_MaximumStorageInBytes = 0;
_LastFindedFileIndex = 0;
_ErrorCode = RAM_CacheError_EmptyStorage;
_WritePolicy = RAM_Cache_WritePolicyNormal;
_FileIterator = 0;
}
RAM_Cache::~RAM_Cache(void) {
Clean();
}
bool RAM_Cache::FindFile(const char* FilePath) {
bool Flag = false;
if (_Storage.size() != 0) {
if (FilePath != nullptr) {
_ErrorCode = RAM_CacheError_FileNotFound;
for (size_t i = 0; i < _Storage.size(); i++) {
if (_Storage[i].PathToFile != nullptr) {
if (strcmp(_Storage[i].PathToFile, FilePath) == 0) {
Flag = true;
_ErrorCode = RAM_CacheError_OK;
_LastFindedFileIndex = i;
break;
}
}
}
}
else {
_ErrorCode = RAM_CacheError_EmptyFilePath;
}
}
else {
_ErrorCode = RAM_CacheError_EmptyStorage;
}
return Flag;
}
void RAM_Cache::ChangeFileData(const char * FilePath, uint8_t * BuffeData, size_t FileSize) {
if (FindFile(FilePath)) {
if (_Storage[_LastFindedFileIndex].Buffer) {
if (_Storage[_LastFindedFileIndex].FileSize > FileSize) {
memcpy(_Storage[_LastFindedFileIndex].Buffer, BuffeData, FileSize);
}
}
else {
delete[] _Storage[_LastFindedFileIndex].Buffer;
try {
_Storage[_LastFindedFileIndex].Buffer = new uint8_t[FileSize];
memcpy(_Storage[_LastFindedFileIndex].Buffer, BuffeData, FileSize);
}
catch (const std::bad_alloc) {
_ErrorCode = RAM_CacheError_MemoryAllocationForFileFalied;
}
}
}
}
void RAM_Cache::RemoveFile(const char * FilePath){
if (FindFile(FilePath)) {
delete[] _Storage[_LastFindedFileIndex].Buffer;
delete[] _Storage[_LastFindedFileIndex].PathToFile;
_Storage.erase(_Storage.begin() + _LastFindedFileIndex);
_Storage.shrink_to_fit();
}
}
bool RAM_Cache::AddFile(const char * FilePath, uint8_t * BuffeData, size_t FileSize) {
bool Flag = false;
RAM_CacheNode Node;
if (!FindFile(FilePath)) {
if (FilePath) {
if (BuffeData) {
if (_WritePolicy == RAM_Cache_WritePolicyNormal) {
if (_MaximumFileInStorage != 0) {
if (_MaximumFileInStorage == _Storage.size()) {
_ErrorCode = RAM_CacheError_NotWritenbyLimitFileCount;
Flag = false;
return Flag;
}
}
if (_MaximumStorageInBytes != 0) {
if (_SizeStorageInBytes == _MaximumStorageInBytes) {
_ErrorCode = RAM_CacheError_NotWritenbyLimitMemoryUsage;
Flag = false;
return Flag;
}
}
Node.PathToFile = new(nothrow)char[strlen(FilePath) + 1];
Node.Buffer = new(nothrow)uint8_t[FileSize];
if (Node.PathToFile && Node.Buffer) {
Node.FileSize = FileSize;
strcpy(Node.PathToFile, FilePath);
memcpy(Node.Buffer, BuffeData, FileSize);
_ErrorCode = RAM_CacheError_OK;
Flag = true;
_Storage.push_back(Node);
_SizeStorageInBytes += FileSize;
}
else {
Flag = false;
_ErrorCode = RAM_CacheError_MemoryAllocationForFileFalied;
}
}
if (_WritePolicy == RAM_Cache_WritePolicyOverwriteWhenFull) {
if (_MaximumFileInStorage != 0) {
if (_MaximumFileInStorage > _Storage.size()) {
_IsFull = 0;
}
else {
_FileIterator = 0;
_IsFull = 1;
}
}
else {
_ErrorCode = RAM_CacheError_NotWritenbyEmptyLimitFileCount;
Flag = false;
return Flag;
}
if (_MaximumStorageInBytes != 0) {
if (_SizeStorageInBytes < _MaximumStorageInBytes) {
_IsFull = 0;
}
else {
_FileIterator = 0;
_IsFull = 1;
}
}
if (!_IsFull) {
Node.PathToFile = new(nothrow)char[strlen(FilePath) + 1];
Node.Buffer = new(nothrow) uint8_t[FileSize];
if (Node.PathToFile && Node.PathToFile) {
Node.FileSize = FileSize;
strcpy(Node.PathToFile, FilePath);
memcpy(Node.Buffer, BuffeData, FileSize);
_ErrorCode = RAM_CacheError_OK;
Flag = true;
_Storage.push_back(Node);
_SizeStorageInBytes += FileSize;
}
else {
_ErrorCode = RAM_CacheError_MemoryAllocationForFileFalied;
Flag = false;
}
}
else {
if (_FileIterator == _Storage.size() - 1) { _FileIterator = 0; }
if (_Storage[_FileIterator].Buffer) {
delete[] _Storage[_FileIterator].Buffer;
_SizeStorageInBytes -= _Storage[_FileIterator].FileSize;
}
if (_Storage[_FileIterator].PathToFile) {
delete[] _Storage[_FileIterator].PathToFile;
}
_Storage[_FileIterator].Buffer = new (nothrow) uint8_t[FileSize];
_Storage[_FileIterator].PathToFile = new(nothrow) char[strlen(FilePath) + 1];
if (_Storage[_FileIterator].Buffer && _Storage[_FileIterator].PathToFile) {
_Storage[_FileIterator].FileSize = FileSize;
strcpy(_Storage[_FileIterator].PathToFile, FilePath);
memcpy(_Storage[_FileIterator].Buffer, BuffeData, FileSize);
_ErrorCode = RAM_CacheError_OK;
_SizeStorageInBytes += FileSize;
Flag = true;
_FileIterator++;
}
else {
_Storage[_FileIterator].FileSize = 0;
_ErrorCode = RAM_CacheError_MemoryAllocationForFileFalied;
Flag = false;
}
}
}
}
else {
_ErrorCode = RAM_CacheError_EmptyFileBuffer;
}
}
else {
_ErrorCode = RAM_CacheError_EmptyFilePath;
}
}
return Flag;
}
bool RAM_Cache::CacheBLOBData(const char* BlobName, uint8_t* BuffeData, size_t FileSize) {
return AddFile(BlobName, BuffeData, FileSize);
}
void RAM_Cache::Clean(void) {
_ErrorCode = RAM_CacheError_EmptyStorage;
if (_Storage.size() != 0) {
for (size_t i = 0; i < _Storage.size(); i++) {
RemoveFile(_Storage[i].PathToFile);
}
}
_Storage.clear();
}
uint8_t * RAM_Cache::GetFileData(const char * FilePath, size_t& FileSize) {
uint8_t * Data = nullptr;
FileSize = 0;
if (FindFile(FilePath)) {
FileSize = _Storage[_LastFindedFileIndex].FileSize;
Data = _Storage[_LastFindedFileIndex].Buffer;
}
return Data;
}
size_t RAM_Cache::GetMaximumFileInStorage(void) {
return _MaximumFileInStorage;
}
size_t RAM_Cache::GetSizeStorageSizeInBytes(void) {
return _SizeStorageInBytes;
}
size_t RAM_Cache::GetMaximumStorageInBytes(void) {
return _MaximumStorageInBytes;
}
void RAM_Cache::SetMaximumFileInStorage(size_t MaximumFileInStorage) {
this->_MaximumFileInStorage = MaximumFileInStorage;
}
void RAM_Cache::SetWritePolicy(RAM_Cache_WritePolicy WritePolicy) {
this->_WritePolicy = WritePolicy;
}
vector<string> RAM_Cache::GetFileNameList(void) {
_StoredFileNamesList.clear();
if (_Storage.size() != 0) {
for (size_t i = 0; i < _Storage.size(); i++) {
_StoredFileNamesList.push_back(_Storage[i].PathToFile);
}
}
return _StoredFileNamesList;
}
#ifndef _RAM_CACHE_
#define _RAM_CACHE_
#include <memory.h>
#include <vector>
#include <stdint.h>
#include "CriticalSection.h"
using namespace std;
typedef struct RAM_CacheNode {
char* PathToFile;
uint8_t* Buffer;
size_t FileSize;
}RAM_CacheNode;
enum RAM_Cache_WritePolicy {
RAM_Cache_WritePolicyNormal,
RAM_Cache_WritePolicyOverwriteWhenFull,
RAM_Cache_WritePolicyMaximumDRAMUsage,
};
enum RAM_CacheError {
RAM_CacheError_OK,
RAM_CacheError_FileNotFound,
RAM_CacheError_EmptyStorage,
RAM_CacheError_EmptyFilePath,
RAM_CacheError_EmptyFileBuffer,
RAM_CacheError_MemoryAllocationForFileFalied,
RAM_CacheError_NotWritenbyMemoryNotEnogh,
RAM_CacheError_NotWritenbyLimitFileCount,
RAM_CacheError_NotWritenbyEmptyLimitFileCount,
RAM_CacheError_NotWritenbyLimitMemoryUsage,
RAM_CacheError_NotWritenbybyEmptyLimitMemoryUsage,
};
/*************************************************************************************************
* Module for work with RAM Buffer(POSIX)
*
* Initial version: 13.07.19
* last update: 19.11.20
*
*
*
***************************************************************************************************/
class RAM_Cache {
public:
RAM_Cache(void);
~RAM_Cache(void);
bool FindFile(const char* FilePath);
void ChangeFileData(const char* FilePath, uint8_t* BuffeData, size_t FileSize);
void RemoveFile(const char* FilePath);
bool AddFile(const char* FilePath, uint8_t* BuffeData, size_t FileSize);
bool CacheBLOBData(const char* BlobName, uint8_t* BuffeData, size_t FileSize);
void Clean(void);
uint8_t* GetFileData(const char* FilePath, size_t& FileSize);
size_t GetMaximumFileInStorage(void);
size_t GetSizeStorageSizeInBytes(void);
size_t GetMaximumStorageInBytes(void);
void SetMaximumFileInStorage(size_t MaximumFileInStorage);
void SetWritePolicy(RAM_Cache_WritePolicy WritePolicy);
RAM_CacheError GetErrorCode(void) { return _ErrorCode;};
vector<string> GetFileNameList(void);
private:
vector<RAM_CacheNode> _Storage;
vector<string> _StoredFileNamesList;
CriticalSection _Section;
size_t _MaximumFileInStorage;
size_t _IsFull;
size_t _SizeStorageInBytes;
size_t _MaximumStorageInBytes;
size_t _LastFindedFileIndex;
size_t _FileIterator;
RAM_CacheError _ErrorCode;
RAM_Cache_WritePolicy _WritePolicy;
};
#endif // DEBUG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment