회사에서 하는 업무중에서 직접적으로 돈과 관련 된 부분이 하나 있다.
고객에게 전달하는 파일의 양이 많을 때 사용하는 기술로
많은 큰파일을 전달할 시에 만약 고객이 이전 버전의 파일이 있다면 그파일과의 차분만 전달하고
그 차분파일(델타파일)을 이용해서 파일을 복구하면 전송시 드는 각종비용(특히 트래픽 사용량)을
줄이는 기술이다.
이 기술의 변형은 굉장히 많지만 이러한 생각이 기본적으로 나오게 된 곳은
웹서버에서 트래픽을 줄이기위한 기술에서 출발했다고 한다.
위의 까지는 서론이었고...
자 회사에서 지금까지 적용해서 사용했던 기술은 다음과 같다.
mspatch API : http://msdn2.microsoft.com/en-us/library/ms811406.aspx
mspatchc.dll 로 델타를 생성하고
mspatcha.dll 로 델타를 적용한다.
그리고 모든 windows OS를 지원하고 unix 계열의 지원은 되지 않는다.
하지만 관련 모듈이 16MB 에서 알려지지 않은 심각한 문제가 발생되었다.
아래 부분에 상세한 코드 및 설명이 있다.
-------------------------------------------------------------------------
BOOL CMakeDeltaCacheBase::MakeDeltaFile(LPCTSTR szFrom, LPCTSTR szDest, LPCTSTR szDelta, int nDeltaEngineType)
{
PATCH_OLD_FILE_INFO_A ofi;
ofi.SizeOfThisStruct = sizeof(PATCH_OLD_FILE_INFO_A);
ofi.OldFileName = szFrom;
ofi.IgnoreRangeCount = 0;
ofi.RetainRangeCount = 0;
CFileStatus st;
CFile::GetStatus(szDest, st);
ULONG lflags = (st.m_size >= 8 * 1024 * 1024) ? (PATCH_OPTION_USE_LZX_BEST | PATCH_OPTION_USE_LZX_LARGE) : PATCH_OPTION_USE_LZX_A;
if (PATCH_OPTION_USE_LZX_A != lflags)
{
logOutput("File size over 8MB option changed : %s\n", szDest);
}
BOOL bResult = CreatePatchFileEx(1, &ofi, szDest, szDelta, lflags, NULL, NULL, NULL);
if(!bResult)
{
DWORD dwError = ::GetLastError();
m_strErrorMessage = szarrMSC_ErrMessage[dwError - 0xC00E3101];
logOutput("[error] MakeDeltaFile(%s) ErrorCode(0x%08x)\n", szDest, ::GetLastError());
return FALSE;
}
Return TRUE;
}
BOOL CMakeDeltaCacheBase::ApplyDeltaFile(LPCTSTR szFrom, LPCTSTR szDest, LPCTSTR szDelta, int nDeltaEngineType)
{
BOOL bResult = ApplyPatchToFileEx(szDelta, szFrom, szDest, PATCH_OPTION_USE_LZX_A, NULL, NULL);
if(!bResult)
{
DWORD dwError = ::GetLastError();
m_strErrorMessage = szarrMSA_ErrMessage[dwError - 0xC00E4101];
logOutput("[error] ApplyDeltaFile(%s) ErrorCode(0x%08X))\n", szDest, ::GetLastError());
return FALSE;
}
return TRUE;
}
위의 두개의 함수를 통해 mspatchc.dll 과 mspatcha.dll 을 사용하는데
CreatePatchFileEx() 함수의 세번째 파라미터에 들어가는 szDest 파일의 크기가 16MB보다 큰 경우 CreatePatchFileEx() 통해서 델타파일이 생성되나
ApplyPatchToFileEx() 함수를 적용하면 ERROR_PATCH_DECODE_FAILURE 에러가 발생됨
-------------------------------------------------------------------------
이 문제를 MS에 문의 하였으나 깜깜 무소식...
그래서 해당 문제를 해결하기 위해 한동한 google에서 binary delta compression 을 주제로 검색을 하게 되었다.
ms, wikipedia 등등에서 검색을 해보니 다음과 같은 것으로 정리되었다.
1. vcdiff http://www.faqs.org/rfcs/rfc3284.html
2. xdelta http://xdelta.org/
3. msdelta http://msdn2.microsoft.com/en-us/library/bb267312.aspx
4. zdelta http://cis.poly.edu/zdelta/
간단히 설명하면
1. vcdiff : 델타에 관련된 논문. 아 어렵다...여기까지
2. xdelta : 최신 버전은 xdelta3 로 소스까지 있으며 속도는 가장 빠른 것으로 보인다.
3. msdelta : vista 부터 적용된 업데이트 관련 델타 엔진, ms에서 사용중임
4. zdelta : zlib을 바탕으로 수정된 것으로 매우 빠르고 델타생성 크기가 적절하다!
이중 zdelta는 속도와 델타파일의 크기가 매우 만족스러웠다.
msdelta 는 일단 mspatch API에서 발생되었던 문제 16MB 큰파일에 대한 처리가 해결되었으나 델타생성시 매우 긴 시간이 걸린다.
물론 델타의 크기가 매우 작은 장점이 있다. 델타 적용 속도는 zdelta와 비슷하거나 약간 더 걸리는 정도임.
기존의 mspatch가 평균적으로 봤을 때 크기는 가장 작다.
xdelta는 그냥 평범하다고 하는 편이 나을 것 같다. 물론 이곳에 적지 않는 그 기능상으로 문제가 많은 것들도 많지만 위의 리스트에서 보면 평범하다는 것이다.
그래서 zdelta library를 사용하기로 결정하고 회사내의 모든 파일을 적용해 봤는데...
어라라... 파일크기 1.58MB vxd 파일의 델타비교시 그냥 zip으로 압축한것과 동일한 크기의
델타파일이 생성되는 문제가 있었다.
하도 이상해서 이리저리 테스트 해보고 소스를 봤지만 흐...결코 쉽지 않았다.
그래서 해당 홈피에서 관련자 e메일 주소를 찾아서 이 내용을 영문으로 된 글을 보냈으나...
1MB 이상에서는 아주 비슷한 파일이라도 문제가 발생할 수 있다는 요지의 답변만 받았다.
차기버전이 준비중이지만 언제 나올지 모른다나 ㅜ.ㅜ
관련 소스를 더 보고 있어야 할지 고민중이다.
일단 사내의 모든 파일이 16MB보다 작다면 계속 mspatch API를 써야 할 것 같은데.
unix 로의 적용을 위해서는 zdelta를 적용하고 싶지만 문제가 있을 수 있고...
사내의 분들과 토론해본 결과 일단 해당 문제를 적절하게 해결하고
해당 기술은 보유해야 한다는 결론으로 나고 있다.
시간이 되면 zdelta 의 소스를 좀더 분석해야 할 것 같다.
그 이 후에 ...
http://dalhee.wowdns.com/tt/somy/trackback/78
에서는 16MB 제한이 있다는 것은 최근에 MS에서 나온 msdelta.dll 관련 문서
http://msdn2.microsoft.com/en-us/library/bb267312.aspx
에서 확인할 수 있었다.
(흠...최신문서에는 파일 크기에 대한 언급이 사라졌군...예전엔 언급이 있었었는데
16MB 제한이 있고 msdelta는 32MB 제한이 있다고...)
하지만 회사에서 잘 사용하던 델타 생성라이브러리 (mspatchc.dll) 이 최근들에
특정파일에 대해서 ERROR_PATCH_ENCODE_FAILURE = 0xC00E3101 오류를
내면서 델타를 만들지 못하는 문제가 심심치 않게 발생되었다.
이것으로 인해 ms 유료서비스를 받았지만 관련 문제에 대해서 이런 저런 답변을 받지
못하고 16MB 제한에 대한 것이 스펙이라는 말만 듣고서는 끝났다.
(하지만 이 DLL로 확인을 해보니 16MB 이상의 파일도 정상적으로 생성되었다!!! 해결!!!)
오늘 일하다가 갑자기 최신버전을 찾아볼까? 라는 생각에 구글신님에게 물어봐도
뾰족한 답을 듣지 못하다가 갑자기 MS SDK 최신버전에 혹시 있지 않을까? 라는 생각에
테스트를 위해서 설치한 VS2008 설치 폴더에 찾아보니!!!
기존에 사용하던 것보다 더 최신인 mspatchc.dll 을 찾을 수 있었다!!!
버전은 6.0.6000.16384 였고 기존에는 5.2.3760.0 였었다.
새로운 파일을 가지고 델타생성에 문제가 있던 셋에 테스트 해보니 성공!!!!!!! (으아앗!!!!!!)
정말 황당 그자체였다!!!
유료서비스를 받아도 못 해결했는데 이렇게 해결이 되다니!!!
버그 수정판이었고 해당 파일은 98에서도 정상적으로 동작함을 확인하였다.
출처: http://dalhee.wowdns.com/