https://blog.csdn.net/qazw9600/article/details/10811161

说明

  • 解析基于算法库bsdiff-4.3.tar.gz。
  • 算法文件组成是两个C文件:bsdiff.c(根据老版本和新版本生成补丁文件)和bspatch.c(根据老版本和补丁文件生成新版本)。
  • 个人还未完全理解BSDiff算法,主要是后缀数组的实现未理解,暂时将后缀数组实现函数qsufsort和split当做黑盒,记录说明下其它操作。

解析

  1. 生成后缀数组
Line 230: qsufsort(I,V,old,oldsize);
  1. 循环处理新文件数据,找到代码操作导致二进制数据相差字节多于8bytes的偏移点
while(scan<newsize) {for(scsc=scan+=len;scan<newsize;scan++) {len=search(I,old,oldsize,new+scan,newsize-scan,0,oldsize,&pos);for(;scsc<scan+len;scsc++)if((scsc+lastoffset<oldsize) &&(old[scsc+lastoffset] == new[scsc]))oldscore++;if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break;if((scan+lastoffset<oldsize) &&(old[scan+lastoffset] == new[scan]))oldscore--;};....
}

2.1 新版本文件和老版本文件都从数据开头开始,通过二分法,在整个后缀数组I中找到与新版本数据匹配最长的长度len和数组编号pos。

len=search(I,old,oldsize,new+scan,newsize-scan,0,oldsize,&pos);* search和matchlen函数略。

2.2 计算出当前偏移的old数据与new数据相同的字节个数,再与len比较。

 for(;scsc<scan+len;scsc++)if((scsc+lastoffset<oldsize) &&(old[scsc+lastoffset] == new[scsc]))oldscore++;if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break;

2.2.1 如果相差小于8则继续for循环。

2.2.2 如果相差大于8则退出for循环,下面则对这一段数据进行处理。

老版本程序:
printf("hello");
....
新版本程序:
printf("world");
....
  1. 对上一个位置到新位置之间的数据进行处理
while(scan<newsize) {....if((len!=oldscore) || (scan==newsize)) {s=0;Sf=0;lenf=0;for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {if(old[lastpos+i]==new[lastscan+i]) s++;i++;if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };};
,lenb=0;if(scan<newsize) {s=0;Sb=0;for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {if(old[pos-i]==new[scan-i]) s++;if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };};};if(lastscan+lenf>scan-lenb) {overlap=(lastscan+lenf)-(scan-lenb);s=0;Ss=0;lens=0;for(i=0;i<overlap;i++) {if(new[lastscan+lenf-overlap+i]==old[lastpos+lenf-overlap+i]) s++; if(new[scan-lenb+i]==     old[pos-lenb+i]) s--;   if(s>Ss) { Ss=s; lens=i+1; }; };lenf+=lens-overlap; lenb-=lens;};for(i=0;i<lenf;i++)db[dblen+i]=new[lastscan+i]-old[lastpos+i];for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)eb[eblen+i]=new[lastscan+lenf+i];dblen+=lenf;eblen+=(scan-lenb)-(lastscan+lenf);offtout(lenf,buf);BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK)errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);offtout((scan-lenb)-(lastscan+lenf),buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8);if (bz2err != BZ_OK)errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);offtout((pos-lenb)-(lastpos+lenf),buf);  BZ2_bzWrite(&bz2err, pfbz2, buf, 8);if (bz2err != BZ_OK)errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);lastscan=scan-lenb; lastpos=pos-lenb; lastoffset=pos-scan;};
};

3.1 计算diff string的长度

s=0;Sf=0;lenf=0;
for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {if(old[lastpos+i]==new[lastscan+i]) s++;i++;if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
};
if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
* Sf*2-lenf 和 s*2-i 都是等式: a*2 - b。
* Sf*2-lenf可以理解为 上一组s和i,s*2-i计算出的值。
* s*2 - i, i和s的增长步长都为1,也就是i走两步,s走一步就可以维持s*2 - i结果不变,
如果结果要增加,也就是s增加的频率要>50%,即后续增加的数据超过50%的数据需要是相等的。

3.2 获取与下一段数据近似相同数据的长度

lenb=0;
if(scan<newsize) {//printf("lastscan:%d, pos:%d\n", lastscan, pos);s=0;Sb=0;for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {if(old[pos-i]==new[scan-i]) s++;if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };};
};

3.3 上面两段数据可能重叠,处理重叠

if(lastscan+lenf>scan-lenb) {overlap=(lastscan+lenf)-(scan-lenb);s=0;Ss=0;lens=0;for(i=0;i<overlap;i++) {if(new[lastscan+lenf-overlap+i]==old[lastpos+lenf-overlap+i]) s++; if(new[scan-lenb+i]==     old[pos-lenb+i]) s--;   if(s>Ss) { Ss=s; lens=i+1; };};lenf+=lens-overlap; lenb-=lens;
};

3.4 将diff string和extra string保存到内存中,再将长度数据使用bzip压缩写入文件

for(i=0;i<lenf;i++)db[dblen+i]=new[lastscan+i]-old[lastpos+i]; //diff string
for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)eb[eblen+i]=new[lastscan+lenf+i]; //extra stringdblen+=lenf;
eblen+=(scan-lenb)-(lastscan+lenf);//长度数据压缩写入文件
offtout(lenf,buf);
BZ2_bzWrite(&bz2err, pfbz2, buf, 8); //保存的是diff string 的长度
if (bz2err != BZ_OK)errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);offtout((scan-lenb)-(lastscan+lenf),buf); //保存的是extern string 的长度
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
if (bz2err != BZ_OK)errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);offtout((pos-lenb)-(lastpos+lenf),buf);  //保存的是old程序中的新偏移pos相对于上一个偏移lastpos的相差
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
if (bz2err != BZ_OK)errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);//保存偏移
lastscan=scan-lenb;
lastpos=pos-lenb;
lastoffset=pos-scan;
  1. 循环结束后将内存中的diff string和extra string压缩写入文件。

说明

Bsdiff差分算法讲解相关推荐

  1. bsdiff差分算法

    bsdiff的基本原理 bsdiff是由Conlin Percival开源的一个优秀的差分算法,而且是跨平台的.在Android系统中所使用的imgdiff本质上就是bsdiff. bsdiff的依据 ...

  2. Xdelta3 bsdiff Courgette三种差分算法比较

    今天介绍常用的三种差分算法,分别是Xdelta3 bsdiff Courgette. Xdelta3 官网地址: http://xdelta.org 源码地址:https://github.com/j ...

  3. Myers差分算法详解

    一.简介 上一章节讲述了使用DiffUtil工具类计算两个集合的差异.具体核心代码是calculateDiff方法.即 计算差异 的方法. DiffUtil+AsyncListDiffer工具类原理讲 ...

  4. 边界填充算法讲解_边界填充算法

    边界填充算法讲解 Boundary fill is the algorithm used frequently in computer graphics to fill a desired color ...

  5. 干货回顾丨机器学习笔记-----AP(affinity propagat)算法讲解及matlab实现

    在统计和数据挖掘中,亲和传播(AP)是基于数据点之间"消息传递"概念的聚类算法.与诸如k-means或k-medoids的聚类算法不同,亲和传播不需要在运行算法之前确定或估计聚类的 ...

  6. Learning to Rank 中Listwise关于ListNet算法讲解及实现

     [学习排序] Learning to Rank 中Listwise关于ListNet算法讲解及实现             版权声明:本文为博主原创文章,转载请注明CSDN博客源地址!共同学习, ...

  7. TF-IDF算法讲解

    什么是 TF-IDF 算法? TF(全称TermFrequency),中文含义词频,简单理解就是关键词出现在网页当中的频次. IDF(全称InverseDocumentFrequency),中文含义逆 ...

  8. Java的算法讲解以及案例!

    算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,java算法就是采用Java语言来实现解决某一问题的清晰指令. 算法的特征: 输入性:有零个或多个外部量作为算法的输入 输出性:算法产生 ...

  9. 单目标多目标 灰狼算法算法讲解

    灰狼算法单目标&多目标算法讲解 引言 元启发式算法 概念 优势 特征 分类 1. 灰狼算法思想 参考文献 源代码下载 灰狼社会等级及捕猎过程 2. 单目标灰狼算法 包围猎物 追逐猎物 搜捕猎物 ...

最新文章

  1. 汇编程序设计与计算机体系结构软件工程师教程笔记:处理器、寄存器简介
  2. 每个设计师需知的40个设计素材站
  3. springmvc原理详解(手写springmvc)
  4. Spring框架之权限管理
  5. Java工作笔记-使用Maven创建多模块项目
  6. HDOJ 1285 确定比赛名次(拓扑排序)
  7. 微信小程序之 3d轮播(swiper来实现)
  8. 如何查看selenium的版本号
  9. android 音乐播放器----歌词在线下载
  10. Linux telnet命令
  11. Continue(Java)
  12. 实验4 数据库的连接查询
  13. C语言关键字详解(五)带你全面了解 volatile 关键字
  14. 论文笔记:DeepReID: Deep Filter Pairing Neural Network for Person Re-Identification
  15. Android Clipping
  16. 搜狗拼音输入法传统版 6.7i(0747) 去广告优化版
  17. iPhone11启动全线降价;瑞幸自曝22亿造假,股价暴跌75%;会议软件 Zoom 陷信任危机 | EA周报...
  18. starting to launch local task to process map join maximum memory =1029701632 的原因
  19. 比较两个字符串是否相等,strcmp wcscmp stricmp wcsicmp
  20. linux - 安装 telnet-server

热门文章

  1. 关于COM的Reg-Free(免注册)技术简介及实例讲解。
  2. Remote branch Develop not found in upstream origin
  3. 线段树线段树的创建线段树的查询单节点更新区间更新
  4. CentOS7编译安装libc++和libc++abi
  5. Linux设备中的并发控制
  6. 1296: [SCOI2009]粉刷匠
  7. 通过PHP自带的$_SERVER判断 手机访问网站自动跳转到手机版
  8. 绑定到异步的ObservableCollection
  9. ubuntu16.04安装FastDFS-5.08
  10. 打不开文件F:\vmware -副本\Ubuntu 16.vmdk:该虚拟机的磁盘已经由虚拟机或者快照使用