mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
315 lines
8.5 KiB
C++
315 lines
8.5 KiB
C++
/***************************************************************
|
|
|
|
CShareMemArray
|
|
|
|
øàáëîí êëàññà äëÿ ðàáîòû ñ èìåíîâàííîé
|
|
Shared-ïàìÿòüþ. Ðåàëèçàâàíû çàãðóçêà ìàññèâà
|
|
èç ïàìÿòè è ñîõðàíåíèå â ïàìÿòü.
|
|
|
|
***************************************************************/
|
|
|
|
#pragma once
|
|
#pragma warning( disable : 4996 4244) // No CRT-secure warning
|
|
|
|
#include <atlcoll.h>
|
|
#include "ASCUtils.h" // CSyncAccess class definition
|
|
|
|
#define AVS_USER_NAME_LEN 1024
|
|
|
|
// Ñòàòóñ õðàíèëèùà (îøèáêà, óæå ñîçäàíî, íîâîå)
|
|
enum TSMAStatus {SMAS_ERROR, SMAS_ALREADYEXISTS, SMAS_NEW};
|
|
|
|
// Õðàíèëèùå
|
|
template <typename STOR_TYPE>
|
|
class CShareMemArray
|
|
{
|
|
protected:
|
|
HANDLE m_hAccessMutex; // Ìüþòåêñ äëÿ áåçîïàñíîãî äîñòóïà ê Shared-Memory
|
|
HANDLE m_hMapFile; // Õåíäë íà map òàáëèöû
|
|
STOR_TYPE *m_pArray; // Óêàçàòåëü íà ìàññèâ
|
|
LONG64 m_nSize; // Ðàçìåð òàáëèöû
|
|
CString m_sMutexName; // Èìÿ ìüþòåêñà
|
|
CString m_sMapName; // Èìÿ ìàïïà
|
|
TSMAStatus m_sStatus;
|
|
|
|
protected:
|
|
// ×èòàåì èç ïàìÿòè
|
|
bool ReadFromSharedMem(LONG64 nIndex, STOR_TYPE &nValue)
|
|
{
|
|
if (NULL == m_pArray)
|
|
{
|
|
m_sStatus = SMAS_ERROR;
|
|
return false;
|
|
}
|
|
|
|
__try
|
|
{
|
|
STOR_TYPE *pTable = (STOR_TYPE *) (((BYTE *) m_pArray) + sizeof(LONG64)); // sizeof(LONG64) - ðàçìåð òàáëèöû
|
|
nValue = pTable[nIndex];
|
|
}
|
|
__except(EXCEPTION_IN_PAGE_ERROR == GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
|
{
|
|
// Failed to read from the view.
|
|
ATLTRACE2("CIndexerStorage::ReadFromSharedMem()\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Ïèøåì â ïàìÿòü
|
|
bool WriteToSharedMem(LONG64 nIndex, STOR_TYPE aValue)
|
|
{
|
|
if (NULL == m_pArray)
|
|
{
|
|
m_sStatus = SMAS_ERROR;
|
|
return false;
|
|
}
|
|
|
|
__try
|
|
{
|
|
STOR_TYPE *pTable = (STOR_TYPE *) (((BYTE *) m_pArray) + sizeof(LONG64)); // sizeof(LONG64) - ðàçìåð òàáëèöû
|
|
pTable[nIndex] = aValue;
|
|
}
|
|
__except(EXCEPTION_IN_PAGE_ERROR == GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
|
{
|
|
// Failed to read from the view.
|
|
ATLTRACE2("Error CIndexerStorage::WriteToSharedMem(#i)\n", nIndex);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Çàãðóçêà òàáëèöû èíäåêñîâ èç SharedMemory
|
|
bool SaveTable_unsync(CAtlArray<STOR_TYPE> &aTable)
|
|
{
|
|
if ((NULL == m_pArray) || (NULL == m_hMapFile))
|
|
{
|
|
m_sStatus = SMAS_ERROR;
|
|
return false; // Çàùèòà îò äóðàêà
|
|
}
|
|
|
|
bool bRes = true;
|
|
|
|
// Çàùèòà îò äóðàêà
|
|
LONG64 nCopyCount = (m_nSize <= (LONG64) aTable.GetCount()) ? m_nSize : aTable.GetCount();
|
|
|
|
// Ñîõðàíÿåì ðàçìåð òàáëèöû
|
|
Size_unsync(m_nSize);
|
|
|
|
// êîïèðóåì èç ïàìÿòè â ìàññèâ (safe)
|
|
for (LONG64 nIndex = 0; nIndex < nCopyCount; nIndex++)
|
|
{
|
|
bRes &= WriteToSharedMem (nIndex, aTable[nIndex]);
|
|
}
|
|
|
|
return bRes;
|
|
}
|
|
|
|
// Ñîõðàíåíèå òàáëèöû èíäåêñîâ èç SharedMemory
|
|
bool LoadTable_unsync(CAtlArray<STOR_TYPE> &aTable)
|
|
{
|
|
if ((NULL == m_pArray) || (NULL == m_hMapFile))
|
|
{
|
|
m_sStatus = SMAS_ERROR;
|
|
return false; // Çàùèòà îò äóðàêà
|
|
}
|
|
|
|
aTable.RemoveAll();
|
|
|
|
// Îïðåäåëÿåì ðàçìåð
|
|
m_nSize = Size_unsync();
|
|
|
|
STOR_TYPE nValue;
|
|
|
|
// êîïèðóåì èç ïàìÿòè â ìàññèâ
|
|
for (DWORD nIndex = 0; nIndex < m_nSize; nIndex++)
|
|
{
|
|
if (ReadFromSharedMem(nIndex, nValue))
|
|
{
|
|
// Äîáàâëÿåì â òàáëèöó
|
|
aTable.Add(nValue);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Ðàçìåð
|
|
LONG64 Size_unsync()
|
|
{
|
|
LONG64 nValue = -1;
|
|
|
|
if (NULL == m_pArray)
|
|
{
|
|
m_sStatus = SMAS_ERROR;
|
|
return nValue;
|
|
}
|
|
|
|
__try
|
|
{
|
|
LONG64 *pSize = (LONG64 *) m_pArray;
|
|
nValue = *pSize;
|
|
}
|
|
__except(EXCEPTION_IN_PAGE_ERROR == GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
|
{
|
|
// Failed to read from the view.
|
|
ATLTRACE2("CIndexerStorage::Size_unsync()\n");
|
|
return -1;
|
|
}
|
|
return nValue;
|
|
}
|
|
|
|
void Size_unsync(LONG64 aSize)
|
|
{
|
|
if (NULL == m_pArray)
|
|
{
|
|
m_sStatus = SMAS_ERROR;
|
|
return;
|
|
}
|
|
|
|
__try
|
|
{
|
|
LONG64 *pSize = (LONG64*) m_pArray; // sizeof(LONG64) - ðàçìåð òàáëèöû
|
|
*pSize = aSize;
|
|
}
|
|
__except(EXCEPTION_IN_PAGE_ERROR == GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
|
{
|
|
// Failed to read from the view.
|
|
ATLTRACE2("Error CIndexerStorage::Size_unsync(LONG64 aSize)\n");
|
|
}
|
|
}
|
|
|
|
public:
|
|
// aSize - ðàçìåð òàáëèöû èíäåêñàöèè (êîë-âî ïîëóñåêóíä),
|
|
// Id - äîïîëíèòåëüíûé èäåêòèôèêàòîð, ÷òîá ìîæíî áûëî ñîçäàâàòü ìíîãî ñòîðåéäæåé äëÿ îäíîãî ôàéëà
|
|
CShareMemArray(CString &aFileName, LONG64 aSize, DWORD aId = ISID_DEFAULT):
|
|
m_hMapFile(NULL), m_nSize(aSize), m_pArray(NULL), m_sStatus(SMAS_ERROR)
|
|
{
|
|
// "Âûòàñêèâàåì" èìÿ ôàéëà
|
|
TCHAR aDrive[_MAX_DRIVE];
|
|
TCHAR aDir[_MAX_DIR];
|
|
TCHAR aFName[_MAX_FNAME];
|
|
TCHAR aExt[_MAX_EXT];
|
|
|
|
_tsplitpath (aFileName.GetBuffer(), aDrive, aDir, aFName, aExt);
|
|
//_wsplitpath_s (aFileName.GetBuffer(), aDrive, _MAX_DRIVE, aDir, _MAX_DIR, aFName, _MAX_FNAME, aExt, _MAX_EXT);
|
|
|
|
// Äîïîëíèòåëüíî ôîðìèðóåì óíèêàëüíûå ñèìâîëû äëÿ ýòîãî ïóòè, ÷òîáû âêëþ÷èòü â èìÿ ôàéëà
|
|
DWORD dwPathID = 0;
|
|
TCHAR tcPathIDItem = 0;
|
|
|
|
// Ïîäñ÷èòûâàåì êîíòðîëüíóþ ñóììó äëÿ ïóòè
|
|
for (int i = 0; i < (int) _tcslen(aDir); i++)
|
|
{
|
|
tcPathIDItem ^= aDir[i];
|
|
dwPathID ^= dwPathID << 1;
|
|
dwPathID += (DWORD) tcPathIDItem;
|
|
}
|
|
|
|
// Ïîäñ÷èòûâàåì êîíòðîëüíóþ ñóììó äëÿ ðàñøèðåíèÿ
|
|
DWORD dwExtID = 0;
|
|
TCHAR tcExtIDItem = 0;
|
|
for (int i = 0; i < (int) _tcslen(aExt); i++)
|
|
{
|
|
tcExtIDItem ^= aExt[i];
|
|
dwExtID ^= dwExtID << 1;
|
|
dwExtID += (DWORD) tcExtIDItem;
|
|
}
|
|
|
|
// Ôîðìèðóåì èìÿ ìóòåêñà è ìàïà
|
|
// Ýòîò êîä íå ðàáîòàåò åñëè çàøëî äâà ïîëüçîâàòåëÿ è êàæäûé çàïóñêàåò ñâîþ êîïèþ ïðèëîæåíèÿ.
|
|
// Ôè÷à â èìåíîâàíèè ìüþòåêñà.
|
|
//  íà÷àëå èìåíè ìüþòåêñà äîëæíî ñòîÿòü "Global\"
|
|
// ØóëüãàÈâàí: "Global\" íå ïðîõîäèò íà Win7, åñëè ïðîãà çàïóùåíà íå ïîä àäìèíîì
|
|
m_sMutexName.Format(_T("Local\\avs_mutex%u_%s_%06x_%06I64x_%06x"), aId, aFName, dwPathID, aSize, dwExtID);
|
|
m_sMapName.Format(_T("Local\\avs_storage%u_%s_%06x_%06I64x_%06x"), aId, aFName, dwPathID, aSize, dwExtID);
|
|
|
|
// äîáàâëÿåì èìÿ þçåðà
|
|
TCHAR pBufferUserName[AVS_USER_NAME_LEN];
|
|
DWORD dwBufferUserNameLen = AVS_USER_NAME_LEN;
|
|
GetUserName(pBufferUserName, &dwBufferUserNameLen);
|
|
|
|
CString strUserName(pBufferUserName, dwBufferUserNameLen);
|
|
m_sMutexName += strUserName;
|
|
m_sMapName += strUserName;
|
|
|
|
// Ñîçäàåì ìüþòåêñ
|
|
m_hAccessMutex = CreateMutex(NULL, FALSE, m_sMutexName.GetBuffer());
|
|
|
|
// Äàëåå âñå äåëàåì "ïîä ìóòåêñîì" :)
|
|
CSynchAccess oAccess = m_hAccessMutex;
|
|
|
|
// Ñîçäàåì ìàï
|
|
ATLTRACE2("CShareMemArray()::CShareMemArray(): m_nSize = %d\n", m_nSize);
|
|
|
|
ULARGE_INTEGER nMappingSize;
|
|
nMappingSize.QuadPart = m_nSize * sizeof(STOR_TYPE) + sizeof(LONG64);
|
|
|
|
m_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, nMappingSize.HighPart, nMappingSize.LowPart, m_sMapName.GetBuffer());
|
|
if (NULL == m_hMapFile)
|
|
{
|
|
// Îøèáêà
|
|
ATLTRACE2("CShareMemArray::CShareMemArray():CreateFileMapping() FAILS (0x%x)!\n", GetLastError());
|
|
m_sStatus = SMAS_ERROR;
|
|
}
|
|
else
|
|
{
|
|
// Âñå îê!
|
|
m_sStatus = (GetLastError() == ERROR_ALREADY_EXISTS) ? SMAS_ALREADYEXISTS : SMAS_NEW;
|
|
ATLTRACE2 (SMAS_ALREADYEXISTS == m_sStatus ? "CShareMemArray: open existing!\n" : "CShareMemArray: create new!\n");
|
|
|
|
// ñîçäàåì View of file
|
|
m_pArray = (STOR_TYPE *) MapViewOfFile(m_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, (SIZE_T) nMappingSize.QuadPart);
|
|
if (NULL == m_pArray)
|
|
{
|
|
// Îøèáêà
|
|
ATLTRACE2("CShareMemArray::CShareMemArray():MapViewOfFile() FAILS (0x%x)!\n", GetLastError());
|
|
m_sStatus = SMAS_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual ~CShareMemArray()
|
|
{
|
|
if (m_pArray) UnmapViewOfFile(m_pArray); // óäàëÿåì view
|
|
if (NULL != m_hMapFile) CloseHandle(m_hMapFile); // óäàëÿåì ìàï
|
|
if (NULL != m_hAccessMutex) CloseHandle(m_hAccessMutex); // Óäàëÿåì ìüþòåêñ
|
|
}
|
|
|
|
public:
|
|
|
|
// Ñîõðàíèòü òàáëèöó â øàðåä-ìåìîðè
|
|
bool Save(CAtlArray<STOR_TYPE> &aTable)
|
|
{
|
|
CSynchAccess oAccess = m_hAccessMutex;
|
|
return SaveTable_unsync(aTable);
|
|
}
|
|
|
|
// Çàãðóçèòü òàáëèöó
|
|
bool Load(CAtlArray<STOR_TYPE> &aTable)
|
|
{
|
|
CSynchAccess oAccess = m_hAccessMutex;
|
|
return LoadTable_unsync(aTable);
|
|
}
|
|
|
|
// Ðàçìåð ïîëó÷åíèå
|
|
LONG64 Size()
|
|
{
|
|
CSynchAccess oAccess = m_hAccessMutex;
|
|
return Size_unsync();
|
|
}
|
|
|
|
/*void Size(LONG64 aSize)
|
|
{
|
|
CSynchAccess oAccess = m_hAccessMutex;
|
|
Size_unsync(aSize);
|
|
}*/
|
|
|
|
// Ïîëó÷åíèå ñòàòóñà
|
|
TSMAStatus Status(void) const
|
|
{
|
|
CSynchAccess oAccess = m_hAccessMutex;
|
|
return m_sStatus;
|
|
}
|
|
};
|
|
|