#ifdef _WIN32 #define _CRT_SECURE_NO_WARNINGS #define _CRT_NONSTDC_NO_WARNINGS #include #include #include "../Win32/w32def.h" #endif // _WIN32 #include #include #include #include #ifdef __linux__ #include #include #include #include #include #endif // __linux__ #include #include #include #include "defines.h" #include "shmrot.h" ///////////////////////////////////////////////////////////////////////////// #define _FILES_DIRECTORY "/tmp" ///////////////////////////////////////////////////////////////////////////// #define _SHMROT_ENTRY_FLAG_VALID 0x00000001 ///////////////////////////////////////////////////////////////////////////// // {99df2b86-f904-425d-9fcc-c83c329d0937} DEFINE_UUID(GUID_SHMROT, 0x99df2b86, 0xf904, 0x425d, 0x9f, 0xcc, 0xc8, 0x3c, 0x32, 0x9d, 0x09, 0x37); ///////////////////////////////////////////////////////////////////////////// CShmROT::CShmROT(void) : m_pTable(NULL) { } CShmROT::~CShmROT(void) { Release(); } bool CShmROT::Create(void) { TRACE("CShmROT::Create!\n"); int nRet = m_shmRot.Create(GUID_SHMROT, sizeof(SHMROT)); if( nRet >= 0 && (m_pTable = (LPSHMROT)m_shmRot.Attach())) { if(nRet == 1) { m_pTable->version = _ROT_CURRENT_VERSION; m_pTable->maxEntries = _ROT_MAX_TABLE_ENTRIES; m_pTable->entrySize = (uint32_t)sizeof(SHMROT_ENTRY); } else if(nRet == 0) { if(m_pTable->version != _ROT_CURRENT_VERSION) { // ... } } return true; } return false; } void CShmROT::Release(void) { if(m_pTable) { TRACE("CShmROT::Release!\n"); m_shmRot.Detach(m_pTable); m_shmRot.Release(); m_pTable = NULL; } } void CShmROT::ForceReleaseMutex(void) { m_shmRot.ForceReleaseMutex(); } CShm* CShmROT::AcquireShm(const char *pszUuid, size_t nSizeElement, size_t nCntElements, const char *pszDescName) { if(!m_pTable) { TRACE("CShmROT::AcquireShm: ROT not initialized!\n"); return NULL; } uuid_t uuid; CShm *pShm = NULL; if(!_uuid_parse(pszUuid, &uuid)) { TRACE("CShmROT::AcquireShm: invalid uuid!\n"); return NULL; } int nIndexFound = -1; int nFirstUnusedIndex = -1; for(int i = 0; i < (int)m_pTable->maxEntries; i++) { SHMROT_ENTRY &re = m_pTable->rot[i]; if(re.flags & _SHMROT_ENTRY_FLAG_VALID) { if(!_uuid_compare(&re.uuid, &uuid)) { nIndexFound = i; break; } } else if(nFirstUnusedIndex == -1) { nFirstUnusedIndex = i; } } if(nIndexFound >= 0) // found existing entry { SHMROT_ENTRY &re = m_pTable->rot[nIndexFound]; bool bMatch = (re.nSizeElement == nSizeElement) && (re.nCntElements == nCntElements); if(bMatch) { TRACE("CShmROT::AcquireShm: Found matching SHM entry!\n"); if((pShm = new CShm)) { if(pShm->Create(uuid, nSizeElement * nCntElements) < 0) { pShm->Release(); delete pShm; pShm = NULL; TRACE("CShmROT::AcquireShm: Failed to create new CShm!\n"); } else { re.nCntHandles++; } } else { TRACE("CShmROT::AcquireShm: Failed to allocate new CShm!\n"); } } else { TRACE("CShmROT::AcquireShm: SHM uuid exists, but size does not match!\n"); } } else if(nFirstUnusedIndex >= 0) // next free slot { TRACE("CShmROT::AcquireShm: Create new SHM entry!\n"); SHMROT_ENTRY &re = m_pTable->rot[nFirstUnusedIndex]; if((pShm = new CShm)) { if(pShm->Create(uuid, nSizeElement * nCntElements) < 0) { pShm->Release(); delete pShm; pShm = NULL; TRACE("CShmROT::AcquireShm: Failed to create new CShm!\n"); } else { re.flags = _SHMROT_ENTRY_FLAG_VALID; re.nSizeElement = (uint32_t)nSizeElement; re.nCntElements = (uint32_t)nCntElements; re.nCntHandles = 1; _uuid_copy(&re.uuid, &uuid); memset(re.szDescName, 0, sizeof(re.szDescName)); if(pszDescName) { size_t nLen = strlen(pszDescName); if(nLen > 0) { if(nLen >= _ROT_MAX_ENTRY_NAME) nLen = _ROT_MAX_ENTRY_NAME - 1; memcpy(re.szDescName, pszDescName, nLen); re.szDescName[nLen] = '\0'; } } } } else { TRACE("CShmROT::AcquireShm: Failed to allocate new CShm!\n"); } } else { TRACE("CShmROT::AcquireShm: SHM uuid not found and no slot available!\n"); } return pShm; } void CShmROT::ReleaseShm(CShm *pShm) { if(pShm) { const uuid_t &ruuid = pShm->Uuid(); for(int i = 0; i < (int)m_pTable->maxEntries; i++) { SHMROT_ENTRY &re = m_pTable->rot[i]; if(!_uuid_compare(&re.uuid, &ruuid)) { if(re.flags & _SHMROT_ENTRY_FLAG_VALID) { if(re.nCntHandles > 0) --re.nCntHandles; if(re.nCntHandles == 0) re.flags &= ~_SHMROT_ENTRY_FLAG_VALID; } break; } } pShm->Release(); delete pShm; } } int CShmROT::Lock(void) { return m_shmRot.Lock(); } int CShmROT::Unlock(void) { return m_shmRot.Unlock(); } void CShmROT::DumpEntries(CShmHandleMap &map) { if(!m_pTable) { printf("CShmROT::DumpEntries: ROT not initialized!\n"); return; } char szUuid[_UUID_STRING_LEN + 1]; Lock(); for(int i = 0; i < (int)m_pTable->maxEntries; i++) { SHMROT_ENTRY &re = m_pTable->rot[i]; if(re.flags & _SHMROT_ENTRY_FLAG_VALID) { unsigned long nAttached = 0; _uuid_unparse(&re.uuid, szUuid, sizeof(szUuid)); if(re.nCntHandles > 0) { CShm *pShm = map.LookupShm(re.uuid); if(pShm) nAttached = pShm->GetNumAttached(); } printf( "uuid: '%s',\n" \ " flags: 0x%08x,\n" \ " size of element: %u,\n" \ " number of elements: %u,\n" \ " name: '%s',\n" \ " number of handles: %u,\n" \ " number of pointers: %lu\n", szUuid, re.flags, re.nSizeElement, re.nCntElements, re.szDescName, re.nCntHandles, nAttached); fflush(stdout); } } Unlock(); }