#include "stdafx.h" #if defined(PRE_UNZIP_CHANGE) #include "ZipArchive.h" #include "LauncherSession.h" #include "UnZipProcess.h" extern void TextOut(const TCHAR * format, ...); unsigned int WINAPI _RunThread(void* pData) { CUnZipProcess* pZip = static_cast(pData); pZip->WorkerThread(pZip->GetThreadID()); return 0; } CUnZipProcess::CUnZipProcess(CLauncherSession* pSession, LPCTSTR szFilePath, LPCTSTR szFileName) { m_pLauncherSession = pSession; _tcscpy_s(m_szOutputFolder, szFilePath); _tcscpy_s(m_szFileName, szFileName); m_nThreadCount = 0; m_nMaxZipFileCount = 0; m_nUnzipCount = 0; //¾ÐÃà ÀÛ¾÷¿ë ¾²·¹µå °¹¼ö(CPU¾²·¹µå °¹¼ö /2 + 1(ÃÖ´ë MAX_ZIP_THREAD, ÃÖ¼Ò 2) _SYSTEM_INFO _Info; GetSystemInfo(&_Info); m_nMaxThreadCount = max(_Info.dwNumberOfProcessors/2 + 1, 2); //³Ê¹« ¸¹À¸¸é Á¶ÀýÇØÁØ´Ù m_nMaxThreadCount = min(m_nMaxThreadCount, MAX_ZIP_THREAD); for(int i = 0; i < m_nMaxThreadCount; i++) m_hZipEndEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL); } CUnZipProcess::~CUnZipProcess() { for(int i = 0; i < m_nMaxThreadCount; i++) CloseHandle(m_hZipEndEvent[i]); m_pLauncherSession = NULL; m_nMaxZipFileCount = 0; m_nMaxThreadCount = 0; m_nThreadCount = 0; if(!m_ZipLength.empty()) { for(int i = 0; i < (int)m_ZipLength.size();i++) SAFE_DELETE(m_ZipLength[i]); m_ZipLength.clear(); } m_Zip.Close(); } bool CUnZipProcess::OpenZip() { m_Zip.Open(m_szFileName, CZipArchive::zipOpenReadOnly); return true; } bool CUnZipProcess::UnZip() { if (m_Zip.GetCount() == 0) { TextOut(_T("Unzip File Counting Failed")); return false; } m_nMaxZipFileCount = m_Zip.GetCount(); //¹Ì¸® ¾²·¹µå°¡ ó¸®ÇÒ °ªµéÀ» ¸¸µé¾îÁØ´Ù sZipLength* sZip; int nCur = 0; int nStart = 0; int nEnd = 0; InitializeCriticalSection(&m_CriticalSection); //ÇÑ ¾²·¹µå¿¡ ÇÒ´çÇÒ ÆÄÀÏÀÇ °¹¼ö °è»ê int nTerm = MAX_UNZIP_COUNT_IN_THREAD; if(m_nMaxZipFileCount < (m_nMaxThreadCount * MAX_UNZIP_COUNT_IN_THREAD)) nTerm = m_nMaxZipFileCount / m_nMaxThreadCount; while(1) { for(int k = 0; k < m_nMaxThreadCount;k++) { sZip = (sZipLength*)malloc(sizeof(sZipLength)); nStart = (nCur+k) * nTerm; nEnd = nStart + nTerm; if(nStart >= m_nMaxZipFileCount) break; if(nEnd > m_nMaxZipFileCount) nEnd = m_nMaxZipFileCount; sZip->nStart = nStart; sZip->nEnd = nEnd; m_ZipLength.push_back(sZip); } if(nStart >= m_nMaxZipFileCount) break; nCur = nCur + m_nMaxThreadCount; } UINT tId; for(int i = 0; i < m_nMaxThreadCount; i++) { _beginthreadex(NULL, NULL, _RunThread, this, NULL, &tId); } WaitForMultipleObjects(m_nMaxThreadCount, m_hZipEndEvent, TRUE, INFINITE); DeleteCriticalSection(&m_CriticalSection); //ÆÄÀÏ °¹¼ö, Å©±â üũ CZipFileHeader fh; TCHAR _FilePath[MAX_PATH]; bool IsOk = true; std::vector _vecRetryZip; TextOut(_T("UnZip Success, Check Files")); for(int i = 0;i < m_nMaxZipFileCount; i++) { m_Zip.GetFileInfo(fh, i); //ÆÄÀÏ Å¸ÀÔÀÌ µð·ºÅ丮ÀÎ °æ¿ì ½ºÅµ if(fh.GetOriginalAttributes() & 0x10) continue; //½ÇÁ¦ Æú´õ¿¡¼­ ÆÄÀÏÀ» ã¾Æº»´Ù _sntprintf_s(_FilePath, MAX_PATH, _T("%s\\%s"), m_szOutputFolder, (LPCTSTR)fh.GetFileName()); HANDLE hFile = CreateFile(_FilePath, // file to open GENERIC_READ, // open for reading FILE_SHARE_READ, // share for reading NULL, // default security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if (hFile == INVALID_HANDLE_VALUE) { IsOk = false; _vecRetryZip.push_back(i); continue; } DWORD dwSize = GetFileSize(hFile, NULL) ; // Å©±â È®ÀÎ if (dwSize == 0xFFFFFFFF || dwSize != fh.m_uUncomprSize) { _vecRetryZip.push_back(i); IsOk = false; } CloseHandle(hFile); } // ½ÇÆÐÇÑ °æ¿ì Àç½Ãµµ ÇØÁØ´Ù if(!IsOk) { TextOut(_T("Retry Unzip(Count : %d)"), _vecRetryZip.size()); for(int i = 0; i< (int)_vecRetryZip.size(); i++) { try { IsOk = m_Zip.ExtractFile(_vecRetryZip[i], m_szOutputFolder, true); } catch(...) { IsOk = false; } if(!IsOk) { m_Zip.GetFileInfo(fh, i); TextOut(_T("%s UnZip Failed"), (LPCTSTR)fh.GetFileName()); break; } } } return IsOk; } void CUnZipProcess::WorkerThread(int nThreadID) { bool IsSuccess; int nRetry = 0; CZipArchive zipInThread; zipInThread.OpenFrom(m_Zip); sZipLength* sZip; while(1) { // ¾²·¹µåµéÀÌ ÀÛ¾÷ÇÒ ¹üÀ§¸¦ ¸Å¹ø °¡Á®¿À´Â Çü½Ä // ó¸®ÇÒ ¹üÀ§¸¦ ¹Ì¸® ÁöÁ¤ÇÒ °æ¿ì, ³ªÁß¿¡ ¸ÕÀú ³¡³ª°í Á¾·áµÇ´Â ¾²·¹µå°¡ Á¸ÀçÇϱ⠶§¹® sZip = GetZipLength(); if(sZip == NULL) break; for(ZIP_INDEX_TYPE i = sZip->nStart; i < sZip->nEnd;i++) { nRetry = 0; while(1) { try { IsSuccess = zipInThread.ExtractFile(i, m_szOutputFolder, true); } catch(...) { IsSuccess = false; } if(IsSuccess) { if(m_pLauncherSession) { CZipFileHeader fh; zipInThread.GetFileInfo(fh, i); InterlockedIncrement(&m_nUnzipCount); #if defined(UNICODE) m_pLauncherSession->OnUnzip(fh.GetFileName(), m_nUnzipCount, m_nMaxZipFileCount); #else WCHAR filename[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, fh.GetFileName(), -1, filename, MAX_PATH); m_pLauncherSession->OnUnzip(filename, m_nUnzipCount, m_nMaxZipFileCount); #endif } break; } nRetry++; //¾ÐÃà Ç®±â¿¡ ½ÇÆÐÇÑ °æ¿ì 20ȸ±îÁö Àç½ÃµµÇÔ if(nRetry > 20) break; else Sleep(50); } } SAFE_DELETE(sZip); } zipInThread.Close(); SetEvent(m_hZipEndEvent[nThreadID]); _endthreadex(0); } #endif // #if defined(PRE_UNZIP_CHANGE)