fast/Plugin/Plc/CEXMemFileQueue.cpp

434 lines
10 KiB
C++
Raw Normal View History

2025-01-20 10:30:01 +08:00
#include "stdafx.h"
#include "CEXMemFileQueue.h"
#include <sys/timeb.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <windows.h>
#include <algorithm>
#include <codecvt>
#include <regex>
#include <string>
// <20><>ȡ<EFBFBD><C8A1>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>YYYYMMDDhhmmssSSS
std::string formatTimeAsString(int lIndexEx)
{
SYSTEMTIME st;
GetLocalTime(&st);
std::ostringstream oss;
// <20><><EFBFBD><EFBFBD>
oss << std::setw(4) << std::setfill('0') << (st.wYear % 10000);
// <20>·ݺ<C2B7><DDBA><EFBFBD><EFBFBD><EFBFBD>
oss << std::setw(2) << std::setfill('0') << st.wMonth;
oss << std::setw(2) << std::setfill('0') << st.wDay;
// Сʱ<D0A1><CAB1><EFBFBD><EFBFBD><EFBFBD>Ӻ<EFBFBD><D3BA><EFBFBD>
oss << std::setw(2) << std::setfill('0') << st.wHour;
oss << std::setw(2) << std::setfill('0') << st.wMinute;
oss << std::setw(2) << std::setfill('0') << st.wSecond;
//__timeb64 tb;
//_ftime64_s(&tb); // <20><>ȡ<EFBFBD><C8A1>ǰʱ<C7B0><EFBFBD><E4A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//oss << std::setw(3) << std::setfill('0') << tb.millitm; // <20><><EFBFBD><EFBFBD><EBA3AC>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><E6B2B9>
oss << std::setw(6) << std::setfill('0') << lIndexEx; // <20><>ֹ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return oss.str();
}
//<2F><>ȡһ<C8A1><D2BB>ָ<EFBFBD><D6B8>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> lType<70><65>ʾ<EFBFBD><CABE>ȡ<EFBFBD><C8A1><EFBFBD>ͣ<EFBFBD>1<EFBFBD><31><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>2<EFBFBD><32><EFBFBD>ļ<EFBFBD><C4BC>У<EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD>
static void traverse_directory_ansi(const char* directory_path, std::vector<std::string>& files, int lType)
{
char search_path[MAX_PATH];
strcpy_s(search_path, directory_path);
strcat_s(search_path, "\\*");
WIN32_FIND_DATAA find_data;
HANDLE hFind = FindFirstFileA(search_path, &find_data);
if (hFind == INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to open directory: " << directory_path << std::endl;
return;
}
do
{
if (strcmp(find_data.cFileName, ".") == 0 || strcmp(find_data.cFileName, "..") == 0)
{
continue;
}
char full_path[MAX_PATH];
strcpy_s(full_path, directory_path);
strcat_s(full_path, "\\");
strcat_s(full_path, find_data.cFileName);
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//<2F>ݲ<EFBFBD>֧<EFBFBD>ֵݹ<D6B5><DDB9><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
if (1 != lType) files.push_back(find_data.cFileName);
}
else
{
if (2 != lType) files.push_back(find_data.cFileName);
}
} while (FindNextFileA(hFind, &find_data) != 0);
FindClose(hFind);
// <20><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::sort(files.begin(), files.end());
}
CEXMemFileQueue::CEXMemFileQueue(std::string strDataDir)
{
m_strBaseDir = strDataDir;
m_pWriteFileItem = NULL;
m_pReadFileItem = NULL;
m_lReadIndex = 0;
m_lItemCount = 0;
InitializeCriticalSection(&m_cs);
SYSTEMTIME stTime;
GetLocalTime(&stTime);
ChangeDataDate(stTime);
}
CEXMemFileQueue::~CEXMemFileQueue()
{
for (int i = 0; i < (int)m_vecFile.size(); i++)
{
delete m_vecFile[i];
}
m_vecFile.clear();
}
int CEXMemFileQueue::GetItemCount()
{
return m_lItemCount;
}
int CEXMemFileQueue::GetAutoSn()
{
ThreadLock stLock(&m_cs);
m_lAutoSn++;
return m_lAutoSn;
}
int CEXMemFileQueue::ReadItem(void* pData, int lIndex /* = -1 */)
{
ThreadLock stLock(&m_cs);
if (lIndex > m_lItemCount)
{
return -1;
}
if (lIndex >= 0)
{
m_lReadIndex = lIndex;
}
else
{
m_lReadIndex++;
}
if (m_lReadIndex >= m_lItemCount)
{
return -1;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
if (NULL == m_pReadFileItem || m_lReadIndex < m_pReadFileItem->lBeindIndex || m_lReadIndex > m_pReadFileItem->lEndIndex)
{
m_pReadFileItem = NULL;
//<2F><><EFBFBD><EFBFBD>Ѱ<EFBFBD><D1B0>
for (int i = 0; i < (int)m_vecFile.size(); i++)
{
if (m_lReadIndex >= m_vecFile[i]->lBeindIndex && m_lReadIndex <= m_vecFile[i]->lEndIndex)
{
m_pReadFileItem = m_vecFile[i];
break;
}
}
}
if (NULL == m_pReadFileItem)
{
return -1;
}
memcpy(pData, (char*)m_pReadFileItem->pBuf + DATA_FIRST_LINE_SIZE + DATA_LINE_SIZE *(m_lReadIndex- m_pReadFileItem->lBeindIndex), DATA_LINE_SIZE);
return m_lReadIndex;
}
void CEXMemFileQueue::FlushWriteFile()
{
ThreadLock stLock(&m_cs);
if (NULL != m_pWriteFileItem)
{
char acFirstLine[DATA_FIRST_LINE_SIZE+1] = { 0 };
sprintf_s(acFirstLine, "%-15d\n", m_pWriteFileItem->lFileSize);
memcpy((char*)m_pWriteFileItem->pBuf, acFirstLine, DATA_FIRST_LINE_SIZE);
FlushViewOfFile(m_pWriteFileItem->pBuf, m_pWriteFileItem->lFileSize);
}
}
int CEXMemFileQueue::WriteItem(void* pData)
{
ThreadLock stLock(&m_cs);
//<2F>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
SYSTEMTIME stDate;
GetLocalTime(&stDate);
if (stDate.wYear != m_stDataDate.wYear || stDate.wMonth != m_stDataDate.wMonth || stDate.wDay != m_stDataDate.wDay)
{
AutoCleanData(5);
ChangeDataDate(stDate);
}
if (m_pWriteFileItem == NULL || m_pWriteFileItem->lFileSize + DATA_LINE_SIZE > DATA_FILE_SIZE)
{
if (m_pWriteFileItem != NULL)
{
m_pWriteFileItem->lEndIndex = m_lItemCount-1;
FlushWriteFile();
}
m_pWriteFileItem = new CEX_QUEUE_FILE_ITEM;
m_pWriteFileItem->lBeindIndex = m_lItemCount;
m_pWriteFileItem->strFileName = m_strDataDir + "\\" + formatTimeAsString((int)m_vecFile.size()) + ".txt";;
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD>д<EFBFBD>͹<EFBFBD><CDB9><EFBFBD>
m_pWriteFileItem->hFile = CreateFileA(
m_pWriteFileItem->strFileName.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (m_pWriteFileItem->hFile == INVALID_HANDLE_VALUE)
{
TRACE("CreateFile failed\r\n");
delete m_pWriteFileItem;
m_pWriteFileItem = NULL;
return -1;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>------<2D><>һ<EFBFBD>й̶<D0B9>ռ<EFBFBD><D5BC>16<31>ֽڼ<D6BD>¼<EFBFBD>ļ<EFBFBD>ʵ<EFBFBD>ʴ<EFBFBD>С
m_pWriteFileItem->hMapFile = CreateFileMappingA(m_pWriteFileItem->hFile,nullptr,PAGE_READWRITE, 0,DATA_FILE_SIZE+16,nullptr);
if (m_pWriteFileItem->hMapFile == nullptr)
{
TRACE("CreateFileMapping failed\r\n");
delete m_pWriteFileItem;
m_pWriteFileItem = NULL;
return -2;
}
// <20><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><EFBFBD><E4B5BD><EFBFBD>̵ĵ<CCB5>ַ<EFBFBD>ռ<EFBFBD>
m_pWriteFileItem->pBuf = MapViewOfFile( m_pWriteFileItem->hMapFile,FILE_MAP_ALL_ACCESS,0, 0,DATA_FILE_SIZE+16);
if (m_pWriteFileItem->pBuf == nullptr)
{
TRACE("MapViewOfFile failed\r\n");
delete m_pWriteFileItem;
m_pWriteFileItem = NULL;
return -3;
}
FlushWriteFile();//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD>һ<EFBFBD>£<EFBFBD>д<EFBFBD><D0B4><EFBFBD>ļ<EFBFBD>ͷ
m_vecFile.push_back(m_pWriteFileItem);
}
//д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
memcpy((char*)m_pWriteFileItem->pBuf + m_pWriteFileItem->lFileSize, pData, DATA_LINE_SIZE);
m_pWriteFileItem->lFileSize += DATA_LINE_SIZE;
m_pWriteFileItem->lEndIndex = m_lItemCount;
m_lItemCount++;
//ʵʱ<CAB5><CAB1><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
char acFirstLine[DATA_FIRST_LINE_SIZE + 1] = { 0 };
sprintf_s(acFirstLine, "%-15d\n", m_pWriteFileItem->lFileSize);
memcpy((char*)m_pWriteFileItem->pBuf, acFirstLine, DATA_FIRST_LINE_SIZE);
return 0;
}
//<2F>л<EFBFBD><D0BB><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>
void CEXMemFileQueue::ChangeDataDate(SYSTEMTIME stDate)
{
ThreadLock stLock(&m_cs);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>
FlushWriteFile();
m_pReadFileItem = NULL;
m_pWriteFileItem = NULL;
for (int i = 0; i < (int)m_vecFile.size(); i++)
{
delete m_vecFile[i];
}
m_vecFile.clear();
m_lItemCount = 0;
//<2F><><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
m_stDataDate = stDate;
char acDate[32] = { 0 };
sprintf_s(acDate, "%04d-%02d-%02d", m_stDataDate.wYear, m_stDataDate.wMonth, m_stDataDate.wDay);
m_strDataDir = m_strBaseDir + "\\" + acDate;
CreateDirectory(m_strDataDir.c_str(), NULL);
//<2F><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>У<EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
std::vector<std::string> files;
traverse_directory_ansi(m_strDataDir.c_str(), files, 1);
for (int i = 0; i < (int)files.size(); i++)
{
CEX_QUEUE_FILE_ITEM* pTempItem = new CEX_QUEUE_FILE_ITEM;
pTempItem->lBeindIndex = m_lItemCount;
pTempItem->strFileName = m_strDataDir + "\\" + files[i];
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD>д<EFBFBD>͹<EFBFBD><CDB9><EFBFBD>
pTempItem->hFile = CreateFileA(
pTempItem->strFileName.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (pTempItem->hFile == INVALID_HANDLE_VALUE)
{
TRACE("CreateFile failed\r\n");
delete pTempItem;
pTempItem = NULL;
break;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>------<2D><>һ<EFBFBD>й̶<D0B9>ռ<EFBFBD><D5BC>16<31>ֽڼ<D6BD>¼<EFBFBD>ļ<EFBFBD>ʵ<EFBFBD>ʴ<EFBFBD>С
pTempItem->hMapFile = CreateFileMappingA(pTempItem->hFile, nullptr, PAGE_READWRITE, 0, DATA_FILE_SIZE + 16, nullptr);
if (pTempItem->hMapFile == nullptr)
{
TRACE("CreateFileMapping failed\r\n");
delete pTempItem;
pTempItem = NULL;
break;
}
// <20><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><EFBFBD><E4B5BD><EFBFBD>̵ĵ<CCB5>ַ<EFBFBD>ռ<EFBFBD>
pTempItem->pBuf = MapViewOfFile(pTempItem->hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, DATA_FILE_SIZE + 16);
if (pTempItem->pBuf == nullptr)
{
TRACE("MapViewOfFile failed\r\n");
delete pTempItem;
pTempItem = NULL;
break;
}
pTempItem->lFileSize = atoi((char*)pTempItem->pBuf);
m_lItemCount += (pTempItem->lFileSize - DATA_FIRST_LINE_SIZE) / DATA_LINE_SIZE;
pTempItem->lEndIndex = m_lItemCount - 1;
m_vecFile.push_back(pTempItem);
}
m_lAutoSn = m_lItemCount;
if (m_vecFile.size() > 0)
{
m_pWriteFileItem = m_vecFile[m_vecFile.size() - 1];
}
}
static bool isValidDateFormat(const std::string& date)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD>ʽ %04d-%02d-%02d
std::regex datePattern(R"((\d{4})\-(\d{2})-(\d{2}))");
//std::regex datePattern(R"(\d{4}-\d{2}-\d{2})");
std::smatch match;
// <20><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
if (std::regex_match(date, match, datePattern))
{
// <20><>ȡ<EFBFBD><EFBFBD>¡<EFBFBD><C2A1><EFBFBD>
int year = std::stoi(match[1].str());
int month = std::stoi(match[2].str());
int day = std::stoi(match[3].str());
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ч<EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD>1<EFBFBD><31>12֮<32><EFBFBD><E4A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD><31>31֮<31><D6AE><EFBFBD>ȣ<EFBFBD>
if (month < 1 || month > 12 || day < 1 || day > 31)
{
return false;
}
return true;
}
return false;
}
static bool DeleteDirectory(const std::string& dirPath)
{
WIN32_FIND_DATA findFileData;
std::string searchPath = dirPath + _T("\\*");
HANDLE hFind = FindFirstFile(searchPath.c_str(), &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
return false;
}
do
{
std::string filePath;
if (strcmp(findFileData.cFileName, _T(".")) == 0 || strcmp(findFileData.cFileName, _T("..")) == 0)
{
continue;
}
filePath = dirPath + _T("\\") + findFileData.cFileName;
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (!DeleteDirectory(filePath))
{
FindClose(hFind);
return false;
}
}
else
{
if (!DeleteFile(filePath.c_str()))
{
FindClose(hFind);
return false;
}
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
return RemoveDirectory(dirPath.c_str()) != 0;
}
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
std::vector<std::string> CEXMemFileQueue::GetDataList()
{
std::vector<std::string> vecDir;
traverse_directory_ansi(m_strBaseDir.c_str(), vecDir, 2);
std::vector<std::string> vecDate;
//<2F><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
for (int i = 0; i < (int)vecDir.size(); i++)
{
if (isValidDateFormat(vecDir[i].c_str()))
{
vecDate.push_back(vecDir[i].c_str());
}
}
return vecDate;
}
//<2F>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʷ<EFBFBD><CAB7><EFBFBD>ݣ<EFBFBD>lRecvDayΪ<79><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void CEXMemFileQueue::AutoCleanData(int lRecvDay)
{
ThreadLock stLock(&m_cs);
std::vector<std::string> vecDate = GetDataList();
for (int i = 0; i < ((int)vecDate.size()) - 5; i++)
{
DeleteDirectory(m_strBaseDir + "\\" + vecDate[i]);
}
}