521 lines
23 KiB
C++
Raw Normal View History

// match_in_old.cpp
// sync_client
// Created by housisong on 2019-09-22.
/*
The MIT License (MIT)
Copyright (c) 2019-2023 HouSisong
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "match_in_old.h"
#include "string.h" //memmove
#include <algorithm> //sort, equal_range lower_bound
#include "sync_client_type_private.h"
#include "../../libHDiffPatch/HDiff/private_diff/mem_buf.h"
#include "../../libHDiffPatch/HDiff/private_diff/limit_mem_diff/bloom_filter.h"
#include "../../libParallel/parallel_channel.h"
#include "sync_diff_data.h"
using namespace hdiff_private;
namespace sync_private{
#define check(value,info) { if (!(value)) { throw std::runtime_error(info); } }
#define checkv(value) check(value,"check "#value" error!")
#define kIsSkipMatchedBlock true //true: speed++, but patchSize+
static const int kMatchHitOutLimit =16; //limit match deep
static const size_t kBestReadSize =1024*256; //for sequence read
#if (_IS_USED_MULTITHREAD)
static const size_t kBestMTClipSize=1*1024*1024; //for muti-thread read once
struct _TMatchDatas;
namespace{
struct TMt:public TMtByChannel{
inline explicit TMt(struct _TMatchDatas& _matchDatas)
:matchDatas(_matchDatas),curWorki(0){}
CHLocker readLocker;
CHLocker workiLocker;
CHLocker checkLocker;
volatile size_t curWorki;
struct _TMatchDatas& matchDatas;
inline bool getWorki(size_t worki){
if (curWorki>worki) return false;
CAutoLocker _auto_locker(workiLocker.locker);
if (curWorki==worki){
++curWorki;
return true;
}else
return false;
}
};
}
#endif //_IS_USED_MULTITHREAD
typedef unsigned char TByte;
typedef uint64_t tm_roll_uint;
struct TIndex_comp0{
inline explicit TIndex_comp0(const uint8_t* _hashs,size_t _byteSize)
:hashs(_hashs),byteSize(_byteSize){ }
typedef uint32_t TIndex;
struct TDigest{
const uint8_t* digests;
inline explicit TDigest(const uint8_t* _digests):digests(_digests){}
};
inline bool operator()(const TIndex x,const TDigest& y)const { //for equal_range
return _cmp(hashs+x*byteSize,y.digests,byteSize)<0; }
bool operator()(const TDigest& x,const TIndex y)const { //for equal_range
return _cmp(x.digests,hashs+y*byteSize,byteSize)<0; }
inline bool operator()(const TIndex x, const TIndex y)const {//for sort
return _cmp(hashs+x*byteSize,hashs+y*byteSize,byteSize)<0; }
protected:
const uint8_t* hashs;
size_t byteSize;
public:
inline static int _cmp(const uint8_t* px,const uint8_t* py,size_t byteSize){
const uint8_t* px_end=px+byteSize;
for (;px!=px_end;++px,++py){
int sub=(int)(*px)-(*py);
if (sub!=0) return sub; //value sort
}
return 0;
}
};
struct TIndex_comp01{
inline explicit TIndex_comp01(const uint8_t* _hashs0,size_t _byteSize0,
const uint8_t* _hashs1,size_t _byteSize1)
:hashs0(_hashs0),hashs1(_hashs1),byteSize0(_byteSize0),byteSize1(_byteSize1){ }
typedef uint32_t TIndex;
inline bool operator()(const TIndex x, const TIndex y)const {//for sort
int cmp0=TIndex_comp0::_cmp(hashs0+x*byteSize0,hashs0+y*byteSize0,byteSize0);
if (cmp0!=0)
return cmp0<0;
else
return TIndex_comp0::_cmp(hashs1+x*byteSize1,hashs1+y*byteSize1,byteSize1)<0;
}
protected:
const uint8_t* hashs0;
const uint8_t* hashs1;
size_t byteSize0;
size_t byteSize1;
};
struct TOldDataCache_base {
TOldDataCache_base(const hpatch_TStreamInput* oldStream,hpatch_StreamPos_t oldRollBegin,
hpatch_StreamPos_t oldRollEnd,uint32_t kSyncBlockSize,
hpatch_TChecksum* strongChecksumPlugin,void* _mt=0)
:m_oldStream(oldStream),m_readedPos(oldRollBegin),m_oldRollEnd(oldRollEnd),
m_strongChecksum_buf(0),m_cur(0),m_kSyncBlockSize(kSyncBlockSize),m_checksumByteSize(0),
m_strongChecksumPlugin(strongChecksumPlugin),m_checksumHandle(0),m_mt(_mt){
size_t cacheSize=(size_t)kSyncBlockSize*2;
check((cacheSize>>1)==kSyncBlockSize,"TOldDataCache mem error!");
cacheSize=(cacheSize>=kBestReadSize)?cacheSize:kBestReadSize;
hpatch_StreamPos_t maxDataSize=oldRollPosEnd()-oldRollBegin;
if (cacheSize>maxDataSize) cacheSize=(size_t)maxDataSize;
#if (_IS_USED_MULTITHREAD)
if (_mt)
cacheSize=(size_t)maxDataSize;
#endif
m_checksumHandle=strongChecksumPlugin->open(strongChecksumPlugin);
checkv(m_checksumHandle!=0);
m_checkChecksum=strongChecksumPlugin->open(strongChecksumPlugin);
checkv(m_checkChecksum!=0);
m_checksumByteSize=(uint32_t)m_strongChecksumPlugin->checksumByteSize();
m_cache.realloc(cacheSize+m_checksumByteSize+m_checksumByteSize);
m_cache.reduceSize(cacheSize);
m_strongChecksum_buf=m_cache.data_end();
m_cur=m_cache.data_end();
_cache();
}
~TOldDataCache_base(){
if (m_checksumHandle)
m_strongChecksumPlugin->close(m_strongChecksumPlugin,m_checksumHandle);
if (m_checkChecksum)
m_strongChecksumPlugin->close(m_strongChecksumPlugin,m_checkChecksum);
}
inline hpatch_StreamPos_t oldRollPosEnd()const{ return m_oldRollEnd+m_kSyncBlockSize-1; }
// all:[ oldDataSize + backZeroLen ]
// ^ ^
// oldRollBegin oldRollEnd
//self: [ ]
// ^ ^
// readedPos
//cache: [ ]
// ^
// cur
void _cache(){
const hpatch_StreamPos_t rollPosEnd=oldRollPosEnd();
if (m_readedPos >=rollPosEnd){ m_cur=0; return; } //set end tag
size_t needLen=m_cur-m_cache.data();
if (m_readedPos+needLen>rollPosEnd)
needLen=(size_t)(rollPosEnd-m_readedPos);
memmove(m_cur-needLen,m_cur,m_cache.data_end()-m_cur);
size_t readLen=needLen;
if (m_readedPos+readLen>m_oldStream->streamSize){
if (m_readedPos<m_oldStream->streamSize)
readLen=(size_t)(m_oldStream->streamSize-m_readedPos);
else
readLen=0;
}
if (readLen>0){
TByte* buf=m_cache.data_end()-needLen;
#if (_IS_USED_MULTITHREAD)
TMt* mt=(TMt*)m_mt;
CAutoLocker _autoLocker(mt?mt->readLocker.locker:0);
#endif
check(m_oldStream->read(m_oldStream,m_readedPos,buf,buf+readLen),
"TOldDataCache read oldData error!");
}
size_t zerolen=needLen-readLen;
if (zerolen>0)
memset(m_cache.data_end()-zerolen,0,zerolen);
m_readedPos+=needLen;
m_cur-=needLen;
}
inline bool isEnd()const{ return m_cur==0; }
inline const TByte* calcPartStrongChecksum(size_t outPartBits){
return _calcPartStrongChecksum(m_cur,m_kSyncBlockSize,outPartBits); }
inline const TByte* strongChecksum()const{//must after do calcPartStrongChecksum()
return m_strongChecksum_buf+m_checksumByteSize; }
inline size_t strongChecksumByteSize()const{ return m_checksumByteSize; }
inline hpatch_TChecksum* strongChecksumPlugin()const{ return m_strongChecksumPlugin; }
inline hpatch_checksumHandle checkChecksum()const{ return m_checkChecksum; }
inline hpatch_StreamPos_t curOldPos()const{ return m_readedPos-(m_cache.data_end()-m_cur); }
protected:
const hpatch_TStreamInput* m_oldStream;
hpatch_StreamPos_t m_readedPos;
hpatch_StreamPos_t m_oldRollEnd;
TAutoMem m_cache;
TByte* m_strongChecksum_buf;
TByte* m_cur;
uint32_t m_kSyncBlockSize;
uint32_t m_checksumByteSize;
hpatch_TChecksum* m_strongChecksumPlugin;
hpatch_checksumHandle m_checksumHandle;
hpatch_checksumHandle m_checkChecksum;
void* m_mt;
inline const TByte* _calcPartStrongChecksum(const TByte* buf,size_t bufSize,size_t outPartBits){
TByte* strongChecksum=m_strongChecksum_buf+m_checksumByteSize;
m_strongChecksumPlugin->begin(m_checksumHandle);
m_strongChecksumPlugin->append(m_checksumHandle,buf,buf+bufSize);
m_strongChecksumPlugin->end(m_checksumHandle,strongChecksum,strongChecksum+m_checksumByteSize);
toPartChecksum(m_strongChecksum_buf,outPartBits,strongChecksum,m_checksumByteSize);
return m_strongChecksum_buf;
}
};
struct TOldDataCache:public TOldDataCache_base {
inline TOldDataCache(const hpatch_TStreamInput* oldStream,hpatch_StreamPos_t oldRollBegin,
hpatch_StreamPos_t oldRollEnd,uint32_t kSyncBlockSize,
hpatch_TChecksum* strongChecksumPlugin,void* _mt=0)
:TOldDataCache_base(oldStream,oldRollBegin,oldRollEnd,kSyncBlockSize,
strongChecksumPlugin,_mt){
if (isEnd()) return;
m_rollHash=roll_hash_start(m_cur,m_kSyncBlockSize);
}
bool _cacheAndRoll(){
TOldDataCache_base::_cache();
if (isEnd()) return false;
return roll();
}
inline tm_roll_uint hashValue()const{ return m_rollHash; }
inline bool roll(){
const TByte* curIn=m_cur+m_kSyncBlockSize;
if (curIn!=m_cache.data_end()){
m_rollHash=roll_hash_roll(m_rollHash,m_kSyncBlockSize,*m_cur,*curIn);
++m_cur;
return true;
}else{
return _cacheAndRoll();
}
}
bool nextBlock(){
m_cur+=m_kSyncBlockSize;
if (m_cur+m_kSyncBlockSize>m_cache.data_end()){
TOldDataCache_base::_cache();
if (isEnd()) return false;
}
m_rollHash=roll_hash_start(m_cur,m_kSyncBlockSize);
return true;
}
protected:
tm_roll_uint m_rollHash;
};
static inline hpatch_StreamPos_t _indexMapTo(uint32_t i){
return (hpatch_StreamPos_t)(kBlockType_needSync-1)-i; }
static inline uint32_t _indexMapFrom(hpatch_StreamPos_t pos){
return (uint32_t)((kBlockType_needSync-1)-pos); }
typedef volatile hpatch_StreamPos_t volStreamPos_t;
static bool matchRange(hpatch_StreamPos_t* out_newBlockDataInOldPoss,
const uint32_t* range_begin,const uint32_t* range_end,TOldDataCache_base& oldData,
const TByte* partChecksums,size_t outPartChecksumBits,
TByte* newDataCheckChecksum,hpatch_StreamPos_t kMinRevSameIndex,void* _mt=0){
const TByte* oldPartStrongChecksum=0;
const size_t outPartChecksumSize=_bitsToBytes(outPartChecksumBits);
bool isMatched=false;
int hitOutLimit=kMatchHitOutLimit;
do {
uint32_t newBlockIndex=*range_begin;
volStreamPos_t* pNewBlockDataInOldPos=&out_newBlockDataInOldPoss[newBlockIndex];
if ((*pNewBlockDataInOldPos)>=kMinRevSameIndex){
if (oldPartStrongChecksum==0)
oldPartStrongChecksum=oldData.calcPartStrongChecksum(outPartChecksumBits);
const TByte* newPairStrongChecksum=partChecksums+newBlockIndex*outPartChecksumSize;
if (0==memcmp(oldPartStrongChecksum,newPairStrongChecksum,outPartChecksumSize)){
isMatched=true;
hpatch_StreamPos_t curPos=oldData.curOldPos();
{
#if (_IS_USED_MULTITHREAD)
TMt* mt=(TMt*)_mt;
CAutoLocker _autoLocker(mt?mt->checkLocker.locker:0);
hpatch_StreamPos_t newBlockOldPosBack=*pNewBlockDataInOldPos;
if (newBlockOldPosBack<kMinRevSameIndex){// other thread done?
if ((--hitOutLimit)<=0) break;
}else
#else
hpatch_StreamPos_t newBlockOldPosBack=*pNewBlockDataInOldPos;
#endif
{
while(true){ //hit
(*pNewBlockDataInOldPos)=curPos;
checkChecksumAppendData(newDataCheckChecksum,newBlockIndex,
oldData.strongChecksumPlugin(),oldData.checkChecksum(),
oldData.strongChecksum(),oldData.strongChecksumByteSize());
if (newBlockOldPosBack==kBlockType_needSync)
break;
//next same block
newBlockIndex=_indexMapFrom(newBlockOldPosBack);
pNewBlockDataInOldPos=&out_newBlockDataInOldPoss[newBlockIndex];
newBlockOldPosBack=*pNewBlockDataInOldPos;
}
//continue;
}
}
}else{
if ((--hitOutLimit)<=0) break;
}
}else{
if ((--hitOutLimit)<=0) break;
}
}while ((++range_begin)!=range_end);
return isMatched;
}
struct _TMatchDatas{
hpatch_StreamPos_t* out_newBlockDataInOldPoss;
const TNewDataSyncInfo* newSyncInfo;
const hpatch_TStreamInput* oldStream;
hpatch_TChecksum* strongChecksumPlugin;
const void* filter;
const uint32_t* sorted_newIndexs;
const uint32_t* sorted_newIndexs_table;
size_t kMatchBlockCount;
unsigned int kTableHashShlBit;
uint32_t threadNum;
};
static void _rollMatch(_TMatchDatas& rd,hpatch_StreamPos_t oldRollBegin,
hpatch_StreamPos_t oldRollEnd,void* _mt=0){
if (rd.oldStream->streamSize<rd.newSyncInfo->kSyncBlockSize)
return;
const uint32_t kBlockCount=(uint32_t)TNewDataSyncInfo_blockCount(rd.newSyncInfo);
const hpatch_StreamPos_t kMinRevSameIndex=kBlockType_needSync-1-kBlockCount;
TIndex_comp0 icomp0(rd.newSyncInfo->rollHashs,rd.newSyncInfo->savedRollHashByteSize);
TOldDataCache oldData(rd.oldStream,oldRollBegin,oldRollEnd,
rd.newSyncInfo->kSyncBlockSize,rd.strongChecksumPlugin,_mt);
uint8_t part[sizeof(tm_roll_uint)]={0};
const size_t savedRollHashBits=rd.newSyncInfo->savedRollHashBits;
const TBloomFilter<tm_roll_uint>& filter=*(TBloomFilter<tm_roll_uint>*)rd.filter;
tm_roll_uint digestFull_back=~oldData.hashValue(); //not same digest
while (true) {
tm_roll_uint digest=oldData.hashValue();
if (digestFull_back!=digest){
digestFull_back=digest;
digest=toSavedPartRollHash(digest,savedRollHashBits);
if (!filter.is_hit(digest))
{ if (oldData.roll()) continue; else break; }//finish
}else{
if (oldData.roll()) continue; else break; //finish
}
const uint32_t* ti_pos=&rd.sorted_newIndexs_table[digest>>rd.kTableHashShlBit];
writeRollHashBytes(part,digest,rd.newSyncInfo->savedRollHashByteSize);
TIndex_comp0::TDigest digest_value(part);
std::pair<const uint32_t*,const uint32_t*>
//range=std::equal_range(rd.sorted_newIndexs,rd.sorted_newIndexs+rd.kMatchBlockCount,digest_value,icomp0);
range=std::equal_range(rd.sorted_newIndexs+ti_pos[0],
rd.sorted_newIndexs+ti_pos[1],digest_value,icomp0);
if (range.first==range.second)
{ if (oldData.roll()) continue; else break; }//finish
bool isMatched=matchRange(rd.out_newBlockDataInOldPoss,range.first,range.second,oldData,
rd.newSyncInfo->partChecksums,rd.newSyncInfo->savedStrongChecksumBits,
rd.newSyncInfo->savedNewDataCheckChecksum,kMinRevSameIndex,_mt);
if (kIsSkipMatchedBlock&&isMatched){
if (!oldData.nextBlock())
break;//finish
}else{
if (oldData.roll()) continue; else break;
}
}
}
#if (_IS_USED_MULTITHREAD)
static void _rollMatch_mt(int threadIndex,void* workData){
TMt& mt=*(TMt*)workData;
TMtByChannel::TAutoThreadEnd __auto_thread_end(mt);
hpatch_StreamPos_t clipSize=kBestMTClipSize;
hpatch_StreamPos_t _minClipSize=(hpatch_StreamPos_t)(mt.matchDatas.newSyncInfo->kSyncBlockSize)*4;
if (clipSize<_minClipSize) clipSize=_minClipSize;
uint32_t threadNum=mt.matchDatas.threadNum;
hpatch_StreamPos_t oldSize=mt.matchDatas.oldStream->streamSize;
hpatch_StreamPos_t _maxClipSize=(oldSize+threadNum-1)/threadNum;
if (clipSize>_maxClipSize) clipSize=_maxClipSize;
size_t workCount=(size_t)((oldSize+clipSize-1)/clipSize);
assert(workCount*clipSize>=oldSize);
try{
for (size_t i=0;i<workCount;++i) {
if (!mt.getWorki(i))
continue;
hpatch_StreamPos_t oldPosBegin=i*clipSize;
hpatch_StreamPos_t oldPosEnd = oldPosBegin+clipSize;
if (oldPosEnd>oldSize) oldPosEnd=oldSize;
_rollMatch(mt.matchDatas,oldPosBegin,oldPosEnd,&mt);
}
}catch(...){
mt.on_error();
}
}
#endif
static void _matchNewDataInOld(_TMatchDatas& matchDatas,int threadNum){
const TNewDataSyncInfo* newSyncInfo=matchDatas.newSyncInfo;
const uint32_t kBlockCount=(uint32_t)TNewDataSyncInfo_blockCount(newSyncInfo);
const uint32_t kMatchBlockCount=kBlockCount-newSyncInfo->samePairCount;
hpatch_StreamPos_t* out_newBlockDataInOldPoss=matchDatas.out_newBlockDataInOldPoss;
const size_t savedRollHashByteSize=newSyncInfo->savedRollHashByteSize;
const size_t savedRollHashBits=newSyncInfo->savedRollHashBits;
TAutoMem _mem_sorted(kMatchBlockCount*(size_t)sizeof(uint32_t));
uint32_t* sorted_newIndexs=(uint32_t*)_mem_sorted.data();
TBloomFilter<tm_roll_uint> filter; filter.init(kMatchBlockCount);
{
checkv(matchDatas.oldStream->streamSize<(hpatch_StreamPos_t)(kBlockType_needSync-1-kBlockCount));
const uint8_t* partRollHash=newSyncInfo->rollHashs;
uint32_t curPair=0;
uint32_t indexi=0;
for (uint32_t i=0;i<kBlockCount;++i,partRollHash+=savedRollHashByteSize){
if ((curPair<newSyncInfo->samePairCount)&&(i==newSyncInfo->samePairList[curPair].curIndex)){
uint32_t sameIndex=newSyncInfo->samePairList[curPair].sameIndex;
while (out_newBlockDataInOldPoss[sameIndex]!=kBlockType_needSync)
sameIndex=_indexMapFrom(out_newBlockDataInOldPoss[sameIndex]);
assert(sameIndex<i);
out_newBlockDataInOldPoss[sameIndex]=_indexMapTo(i);
++curPair;
}else{
sorted_newIndexs[indexi++]=i;
filter.insert(readRollHashBytes(partRollHash,savedRollHashByteSize));
}
}
assert(indexi==kMatchBlockCount);
assert(curPair==newSyncInfo->samePairCount);
TIndex_comp01 icomp01(newSyncInfo->rollHashs,savedRollHashByteSize,
newSyncInfo->partChecksums,newSyncInfo->savedStrongChecksumByteSize);
std::sort(sorted_newIndexs,sorted_newIndexs+kMatchBlockCount,icomp01);
}
//optimize for std::equal_range
unsigned int kTableBit =getBetterCacheBlockTableBit(kMatchBlockCount);
if (kTableBit>savedRollHashBits) kTableBit=(unsigned int)savedRollHashBits;
const unsigned int kTableHashShlBit=(int)(newSyncInfo->savedRollHashBits-kTableBit);
TAutoMem _mem_table((size_t)sizeof(uint32_t)*((1<<kTableBit)+1));
uint32_t* sorted_newIndexs_table=(uint32_t*)_mem_table.data();
{
TIndex_comp0 icomp0(newSyncInfo->rollHashs,savedRollHashByteSize);
uint32_t* pos=sorted_newIndexs;
uint8_t part[sizeof(tm_roll_uint)]={0};
for (uint32_t i=0; i<((uint32_t)1<<kTableBit); ++i) {
tm_roll_uint digest=((tm_roll_uint)i)<<kTableHashShlBit;
writeRollHashBytes(part,digest,savedRollHashByteSize);
TIndex_comp0::TDigest digest_value(part);
pos=std::lower_bound(pos,sorted_newIndexs+kMatchBlockCount,digest_value,icomp0);
sorted_newIndexs_table[i]=(uint32_t)(pos-sorted_newIndexs);
}
sorted_newIndexs_table[((size_t)1<<kTableBit)]=kMatchBlockCount;
}
matchDatas.filter=&filter;
matchDatas.sorted_newIndexs=sorted_newIndexs;
matchDatas.kMatchBlockCount=kMatchBlockCount;
matchDatas.sorted_newIndexs_table=sorted_newIndexs_table;
matchDatas.kTableHashShlBit=kTableHashShlBit;
#if (_IS_USED_MULTITHREAD)
const hpatch_StreamPos_t _bestWorkCount=matchDatas.oldStream->streamSize/kBestMTClipSize;
threadNum=(_bestWorkCount<=threadNum)?(int)_bestWorkCount:threadNum;
if (threadNum>1){
matchDatas.threadNum=threadNum;
TMt mt(matchDatas);
checkv(mt.start_threads(threadNum,_rollMatch_mt,&mt,true));
mt.wait_all_thread_end();
checkv(!mt.is_on_error());
}else
#endif
{
_rollMatch(matchDatas,0,matchDatas.oldStream->streamSize);
}
{
hpatch_StreamPos_t oldSize=matchDatas.oldStream->streamSize;
for (uint32_t i=0; i<kBlockCount; ++i){
hpatch_StreamPos_t& pos=out_newBlockDataInOldPoss[i];
pos=(pos<oldSize)?pos:kBlockType_needSync;
}
}
}
void matchNewDataInOld(hpatch_StreamPos_t* out_newBlockDataInOldPoss,const TNewDataSyncInfo* newSyncInfo,
const hpatch_TStreamInput* oldStream,hpatch_TChecksum* strongChecksumPlugin,int threadNum){
uint32_t kBlockCount=(uint32_t)TNewDataSyncInfo_blockCount(newSyncInfo);
_TMatchDatas matchDatas; memset(&matchDatas,0,sizeof(matchDatas));
matchDatas.out_newBlockDataInOldPoss=out_newBlockDataInOldPoss;
matchDatas.newSyncInfo=newSyncInfo;
matchDatas.oldStream=oldStream;
matchDatas.strongChecksumPlugin=strongChecksumPlugin;
_matchNewDataInOld(matchDatas,threadNum);
}
} //namespace sync_private