一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

用于电子对象的协作编辑的系统和方法与流程

2023-01-14 17:31:37 来源:中国专利 TAG:


1.本公开涉及用于电子对象的协作编辑的系统和方法。
2.发明背景
3.实时协作编辑平台允许多个用户从不同的计算系统同时对同一电子对象进行操作。例如,googledocs允许多个用户(通过他们不同的用户系统)同时查看和编辑文档类型的对象。
4.一些实时协作编辑平台由操作变换(ot)同步协议支持,操作变换同步协议(一般而言)用于变换不同用户对对象进行的不同编辑,以保持对象一致性。
5.执行操作变换所涉及的处理可能很重要,尤其是在对象的并发用户数量和/或这些用户进行的编辑数量很大的情况下。
6.本说明书中对背景信息的引用并非承认或暗示此类信息为现有技术或本领域普通技术人员的公知常识。


技术实现要素:

7.本文描述了一种用于编辑电子对象的计算机实现的方法,电子对象由多个客户端应用程序实时编辑,该方法由第一客户端应用程序执行,并且包括:维护电子对象的本地版本;维护本地缓冲器,本地缓冲器包括一个或多个本地增量,每个本地增量描述由第一客户端应用程序的用户对电子文档的本地版本进行的一个或多个编辑;从服务器系统接收多个服务器增量,每个服务器增量与对电子对象进行的远程编辑相关;对多个服务器增量进行组成,以生成单个经组成的服务器增量;针对本地缓冲器中的一个或多个本地增量来变换单个经组成的服务器增量,以生成经变换的服务器增量;以及通过将经变换的服务器增量应用于电子文档的本地版本来编辑电子文档的本地版本。
附图说明
8.在附图中:
9.图1示出了可进行实时协作编辑的示例网络环境。
10.图2为可被配置为执行本公开的各种特征的计算机处理系统的框图。
11.图3为示例消息传送图。
12.图4为示例消息传送图。
13.图5描绘了客户端同步模块的操作。
14.图6提供了示例状态空间图。
15.图7为示例状态空间图。
16.图8描绘了服务器同步模块的操作。
17.图9提供了示例状态空间图。
18.图10提供了示例状态空间图。
19.图11为示例状态空间图。
20.图12为示例状态空间图。
21.虽然要求保护的本发明可进行各种修改和替代形式,但具体实施例在附图中以示例方式显示,并进行详细描述。然而,应该理解,附图和详细描述并不旨在将本发明限于所公开的特定形式。其目的是覆盖落入由所附权利要求限定的本发明的范围内的所有修改、等同物和替代物。
具体实施方式
22.在以下说明中,阐述了许多具体细节,以提供对所要求保护的发明的全面理解。然而,显而易见的是,所要求保护的发明可以在没有这些具体细节的情况下实施。在某些情况下,为了避免不必要的模糊,以框图形式示出公知的结构和装置。
23.概述
24.总的来说,本公开提供了允许多个用户(人或程序)同时(或基本同时)查看和编辑电子对象的技术。
25.所描述的技术可应用于各种类型的电子对象,例如,文档、演示文稿、网页、图像、设计和其他类型的对象。
26.本文所述的系统和处理为对象的协作编辑提供了托管对话模型。在这样的模型中,服务器(例如,下面描述的服务器应用110)维护可以经由客户端应用程序(例如,客户端应用程序120)协作编辑的对象的规范副本。
27.为了编辑(或简单查看)给定对象,给定用户经由其客户端应用程序与服务器建立连接,并请求访问特定对象。一旦建立了连接,用户就可以(经由他们的客户端应用程序)在他们的客户端装置上查看对象,并以无锁、非阻塞的方式执行本地编辑。这些编辑随后与服务器同步,服务器将编辑从每个客户端广播回所有其他连接的客户端。
28.根据客户端提交的编辑,服务器产生托管对象的线性操作历史。该历史被各方理解为规范的“真理之源”。
29.此外,每个客户端维护其已执行的编辑的历史。本公开描述了在客户端-服务器连接的每一端执行的同步,以针对包含来自所有其他客户端的编辑的服务器规范历史来解析客户端的本地编辑历史。
30.存在各种协作编辑平台。一个这样的平台是googlewave平台。然而,本文描述的技术在许多方面不同于诸如googlewave平台等平台。
31.例如,本文所述的协议允许客户一次发送多个提交,而不是被迫一次发送一个提交。这带来了更流畅的协作体验。
32.作为另一个示例,客户端(和服务器)可任意缓冲/排列传输中的消息,并在变换前将其压缩为单个消息,从而实现比现有技术更有效的同步。
33.作为进一步示例,本文所述的协议支持具有代理或中介的架构,允许通过单个代理机器多路复用多个客户端。
34.其他差异和优点将从公开内容中变得显而易见。
35.网络环境
36.图100描绘了可执行本文所述的各种操作和技术的网络环境100的一个示例。
37.环境100包括协作服务器系统102(简称服务器系统102),其经由一个或多个通信
网络106与协作客户端系统104通信。
38.协作服务器系统102托管协作服务器应用程序110(简称为服务器应用程序或sa 110)。sa 110由服务器系统102执行,以将其配置为向一个或多个相应的客户端应用程序(例如,如下所述的客户端应用程序120a和120b)提供服务器侧功能。sa 110包括实现本文描述的特征和功能的一个或多个应用程序、库、api或其他软件元素。例如,在ca 120是网络浏览器的情况下,sa 110将是诸如apache、iis、nginx、gws之类的网络服务器或者是替代的网络服务器。在ca 120是专用协作平台应用的情况下,sa 110将是被专门配置为与ca 120交互的应用服务器。
39.服务器系统102可托管网络服务器和应用服务器(或多个网络/应用服务器,如有需要)。
40.在本示例中,sa 110包括(或可访问)同步模块112(简称为服务器sm 112)。如下所述,服务器sm 112操作,以同步在sa 110处从各种客户端应用程序120接收的编辑,并维护sa 110用于编辑的所有对象的规范历史。
41.在所示的示例中,服务器sm 112被显示为sa 110的一部分。这可能是由于这些模块是sa 110的本地部分或者作为sa 110的扩展/插件/附加组件安装。在替代实施例中,服务器sm 112可以是在服务器系统102上(或者在运行sa 110的同一计算机处理系统上,或者在不同的计算机处理系统上)运行并与sa 110通信的独立程序。
42.服务器系统102还包括服务器数据存储器114,用于存储与其操作相关的数据。服务器数据存储器114可以是适于存储和访问数据的任何系统或系统组合。例如,服务器数据存储器114可以是由适当的数据库前端访问的数据库。
43.每个协作客户端系统104托管协作客户端应用程序120(简称为ca 120),当由协作客户端系统104执行时,该协作客户端应用程序将其被配置为提供客户端功能/与服务器系统102(替代地,更具体地,其上运行的sa 110)交互。
44.ca 120可为通用网络浏览器应用程序(如chrome、safari、internetexplorer、opera或替代的网络浏览器应用程序),其经由适当的统一对象定位器(url)访问sa 110,并经由通用万维网协议(例如,http、https、ftp)与sa 110通信。可替代地,ca 120可以是被编程为使用定义的应用编程界面(api)调用与sa 110通信的专用协作应用程序。
45.在本示例中,ca 120包括em 122(简称em 122)和客户端同步模块124(简称客户端sm 124)。一般而言,em 122向客户端系统104的用户提供可用于对对象进行改变的编辑界面(例如,通过正常的编辑操作)。em 122还促使显示基于从sa 110接收的消息对对象进行的改变(即,已经在其他ca120处对对象进行的编辑)。客户端sm 124操作,以同步由客户端系统104的用户进行的并且在sa 110处接收的编辑。
46.em 122和客户端sm 124被描述为ca 120的一部分。em 122和客户端sm 124可以是ca 120本地的,或者被安装作为ca 120的扩展/插件/附加组件。在替代实施例中,em 122和/或客户端sm 124可以是在客户端系统104上运行并与ca 120通信的独立程序。
47.给定的协作客户端系统104可具有一个以上的ca 120,例如,通用网络浏览器应用程序和专用编程客户端应用程序。
48.协作客户端系统104还包括客户端数据存储器126,用于存储与其操作相关的数据。通常,客户端数据存储器126将是客户端系统104的本地存储器(例如,如下所述的易失
性存储器208和/或非暂时性存储器210),然而,客户端系统的数据存储器可以是例如通过网络106可访问的远程数据存储器。
49.协作服务器系统102和协作客户端系统104通过一个或多个通信网络106直接或间接在彼此之间传输数据。通信网络106可以包括局域网(lan)、公共网络或网络的组合。
50.环境100描绘为单个逻辑协作服务器110。这可以是在单个计算机处理系统上运行的单个协作服务器应用程序。替代地,服务器系统102可以是集群服务器架构,其中,在一个或多个计算机处理系统上提供多个服务器实例(或节点),以满足系统需求。
51.环境100示出了两个客户端系统104a和104b,然而,典型环境100可能包括更多与协作服务器系统102通信的客户端系统104。
52.协作服务器系统102可为通过硬件和/或软件配置(或可配置)以提供服务器侧功能的任何计算机处理系统。类似地,客户端系统104可以是由硬件和/或软件配置(或可配置)以提供客户端功能的任何计算机处理系统。举例来说,合适的客户端和/或服务器系统可以包括服务器计算机系统、台式计算机、膝上型计算机、上网本计算机、平板计算装置、移动/智能电话、个人数字助理、个人媒体播放器、机顶盒、游戏控制台。
53.下文参考图2描述了计算机处理系统的一个示例。
54.计算机处理系统
55.使用一个或多个计算机处理系统实现本公开的各种实施例和特征。例如,在图1中,每个客户端系统104是计算机处理系统,服务器系统102包括一个或多个计算机处理系统。
56.图2提供了可被配置为实现本文描述的实施例和/或特征的计算机处理系统200的框图。系统200是通用计算机处理系统。应当理解,图2没有示出计算机处理系统的所有功能或物理组件。例如,没有描绘电源或电源界面,然而系统200将携带电源或被配置为连接到电源(或两者都有)。还将理解,特定类型的计算机处理系统将确定适当的硬件和架构,并且适于实现本公开的特征的替代计算机处理系统可以具有所描述的组件的额外组件、替代组件,或者比所描述的组件更少的组件。
57.计算机处理系统200包括至少一个处理单元202。处理单元202可以是单个计算机处理装置(例如,中央处理单元、图形处理单元或其他计算装置),或者可以包括多个计算机处理装置。在一些情况下,所有处理将由处理单元202执行,然而在其他情况下,处理也可以由可由系统200访问和使用(以共享或专用方式)的远程处理装置来执行。
58.通过通信总线204,处理单元202与存储指令和/或数据的一个或多个机器可读存储(存储器)装置进行数据通信,以控制处理系统200的操作。在该示例中,系统200包括系统存储器206(例如,bios)、易失性存储器208(例如,诸如一个或多个dram模块等随机存取存储器)以及非易失性存储器210(例如,一个或多个硬盘或固态驱动器)。
59.系统200还包括一个或多个界面,总体用212表示,系统200经由该界面与各种装置和/或网络接合。一般而言,其他装置可以与系统200集成在一起,或者可以是分离的。在装置与系统200分离的情况下,装置和系统200之间的连接可以经由有线或无线硬件和通信协议,并且可以是直接或间接(例如,联网)连接。
60.可通过任何适当的标准或专有硬件和连接协议与其他装置/网络进行有线连接。例如,系统200可以被配置为通过以下一个或多个与其他装置/通信网络进行有线连接:
usb;火线;esata;thunderbolt;以太网;os/2;parallel;serial;hdmi;dvi;vga;scsi;音频端口。其他有线连接也是可能的。
61.可类似地通过任何适当的标准或专有硬件和通信协议与其他装置/网络进行无线连接。例如,系统200可以被配置为使用以下一个或多个与其他装置/通信网络进行无线连接:红外线;蓝牙;wifi;近场通信(nfc);全球移动通信系统(gsm)、增强型数据gsm环境(edge)、长期演进(lte)、宽带码分多址(w-cdma)、码分多址(cdma)。其他无线连接也是可能的。
62.一般而言,视特定系统而定,与系统200连接的装置(无论通过有线或无线方式)包括:一个或多个输入装置,以允许数据输入到系统200/由系统200接收,以供处理单元202处理;以及一个或多个输出装置,以允许数据由系统200输出。下面描述了示例装置,然而,应该理解,不是所有的计算机处理系统都将包括所有提到的装置,并且可以使用那些提到的装置的额外和替代装置。
63.例如,系统200可包括或连接至一个或多个输入装置,信息/数据通过输入装置输入到系统200(由系统200接收)。这种输入装置可以包括键盘、鼠标、跟踪板、麦克风、加速度计、接近传感器、gps装置等。系统200还可以包括或连接到由系统200控制的一个或多个输出装置,以输出信息。这种输出装置可以包括诸如crt显示器、lcd显示器、led显示器、等离子显示器、触摸屏显示器、扬声器、振动模块、led/其他灯等装置。系统200还可以包括或连接到可以充当输入和输出装置的装置,例如,系统200可以从其读取数据和/或向其写入数据的存储装置(硬盘驱动器、固态驱动器、磁盘驱动器、压缩闪存卡、sd卡等)以及可以显示(输出)数据和接收触摸信号(输入)的触摸屏显示器。
64.系统200还可以连接至一个或多个通信网络(例如,互联网、局域网、广域网、个人热点等),以向联网装置传送数据和从联网装置接收数据,联网装置本身可以是其他计算机处理系统。
65.系统200可为任何合适的计算机处理系统,例如,作为非限制性示例,服务器计算机系统、台式计算机、膝上型计算机、上网本计算机、平板计算装置、移动/智能电话、个人数字助理或替代计算机处理系统。
66.通常,系统200至少包括用户输入和输出装置214和通信界面216,用于与诸如环境100的网络106等网络进行通信。
67.系统200存储或访问计算机应用程序(也称为软件或程序),即计算机可读指令和数据,当由处理单元202执行时,将系统200配置为接收、处理和输出数据。指令和数据可以存储在系统200可访问的非暂时性机器可读介质上。例如,指令和数据可以存储在非暂时性存储器210上。指令和数据可以经由传输信道中的数据信号发送到系统200或由系统200接收,由(例如)有线或无线网络连接通过界面(例如,212)实现该传输信道。
68.系统200可访问的应用程序通常包括操作系统应用程序,例如,microsoft苹果osx、苹果ios、安卓、unix或linux。
69.系统200还存储或访问应用程序,当由处理单元202执行时,这些应用程序将系统200配置为执行本文所述的各种计算机实现的处理操作。
70.例如,参考上述图1的网络环境,每个客户端系统104包括客户端应用程序120,该客户端应用程序将客户端系统104配置为执行所述客户端系统操作,服务器系统102包括服
务器应用程序110,该服务器应用程序将服务器系统102配置为执行所述服务器系统操作。
71.在某些情况下,给定计算机实现的方法的部分或全部将由系统200自身执行,而在其他情况下,可由与系统200进行数据通信的其他装置执行处理。
72.对象版本
73.在本公开中,sa 110和每个ca 120维护正在(或已经)编辑的给定对象的版本标识符。
74.客户端和服务器版本标识符(分别缩写为cv和sv)是独立的,即特定对象的给定客户端版本标识符与该对象的另一客户端版本标识符或该对象的服务器版本标识符无关。给定客户端的版本标识符允许该客户端跟踪对象自己的、本地状态,并允许服务器跟踪对象的该特定客户端的状态。服务器版本标识符用于跟踪对象的服务器版本(规范版本)。
75.本文所述的协议要求对给定的一组版本标识符(即由特定ca 120维护的版本标识符或由sa 110维护的版本标识符)进行排序,但不要求两个版本标识符之间存在任何“距离”概念。
76.举例来说,此类版本标识符的一种可能实现方式为序数,例如,单调递增的整数序列,例如,(0,1,2,...)。在某些实现方式中,客户端版本标识符采用这种形式。
77.作为另一个示例,时间戳可与序列号(在两个时间戳恰好相同的情况下使用的序列号)一起用作版本标识符,例如,(1585091071632-0,1585091874453-0,1585091874453-1,1585091875337-0,...)。在某些实现方式中,sa 110以这种形式维护服务器版本标识符。具体而言,sa 110可被配置为将诸如redis数据存储器之类的数据存储器用于对象的规范历史。在这种情况下,可以使用redis流数据类型,该类型会在向流中添加项目时自动分配这样的版本号。
78.可以使用替代的客户端和/或服务器版本标识符。
79.为了提高可读性,本文提供的示例将对客户端版本标识符使用递增整数,例如,(0,1,2,...,n),对服务器版本标识符使用递增整数对,例如,(0-0,1-1,2-1,...,n-n)(认识到在某些实现方式中,给定服务器版本标识符的第一个整数实际上将是时间戳)。
80.通信协议
81.在本公开中,ca 120和cs 110被配置为以在它们之间提供可靠、有序、双工消息流的方式进行连接。可以使用提供这种特征的任何适当的连接协议,例如,tcp连接、websocket连接或替代连接。
82.在本公开中,从给定ca 120发送至sa 110的消息将被称为客户端消息,而从sa 110发送至给定ca 120的消息将被称为服务器消息。
83.连接
84.为了开始编辑给定的共享对象,ca 120通过连接请求打开与该共享对象的连接。
85.在本实现方式中,这涉及ca 120生成连接消息,该消息包括给定对象的标识符、客户端应用程序希望连接到的对象的服务器版本标识符和对象的客户端版本标识符。例如:
86.connect(objectid,sv,cv)
87.在打开流式连接之前,客户端必须具有与服务器的规范历史中的条目相对应的(sv,state)快照。客户端可以以各种方式获得这样的快照,例如,经由某个其他通道向服务器发出专用请求(例如,http请求),或者客户端能够使用从同一对象的先前编辑会话中获
得的快照。(sv,state)不必是服务器上的当前或最近的状态;任何历史状态都足够了。
88.ca 120被配置为当客户端首次连接至给定对象时,将客户端版本标识符初始化为初始值(例如,0)。如下所述,在与对象相关的协作编辑会话期间,ca 120更新客户端版本标识符。如果ca 120与该对象断开连接,然后重新连接,则可以使用该对象的客户端版本标识符的当前值。
89.消息
90.一旦ca 120与sa 110维护的对象建立了连接(例如,根据上述连接消息),ca 120的用户可查看/编辑该对象。此外,ca 120可以从sa 110接收于其他ca 120对象相关的编辑的消息。
91.为此,本公开提供了四种类型的信息,将依次描述每种信息。
92.当ca 120a接收到本地编辑(即ca 120a的用户对对象进行的编辑)时,ca 120a生成clientsubmit消息,并将其传送至sa 110。在本实施例中,clientsubmit消息包括:客户端版本标识符(cv),其指示编辑后的对象的客户端应用程序的版本标识符;以及描述已经在本地进行的编辑的增量(d)。例如:
93.clientsubmit(cv,d)
94.当sa 110对对象进行编辑时(基于从连接至该对象的ca 120接收的编辑),sa 110生成serversubmit消息,并将其传送至连接至该对象的ca 120。在本实施例中,serversubmit消息包括:服务器版本标识符(sv),其指示编辑后的对象的服务器应用程序版本标识符;以及描述已经进行的编辑的增量(d)。例如:
95.serversubmit(sv,d)
96.一旦ca 120a接收到一条或多条serversubmit消息,通过生成clientack消息并将其传送至sa 110,确认接收到该消息。在本实施例中,clientack消息包括服务器版本标识符(sv),其指示ca 120a已经接收到包括在clientack消息中的服务器版本之前的所有serversubmit消息。例如:
97.clientack(sv)
98.一旦sa 110从给定ca 120a接收到一条或多条clientsubmit消息,通过生成serverack消息并将其传送至该ca 120a,确认接收到该消息。在本实施例中,serverack消息包括服务器版本标识符(sv)和客户端版本标识符(cv)。serverack消息中的客户端版本标识符指示sa 110已经接收到该客户端版本之前的所有clientsubmit消息。serverack消息中的服务器版本标识符指示在处理了客户端版本之前的所有clientsubmit消息之后所述对象的服务器版本。例如:
99.serverack(sv,cv)
100.可以理解,上述消息结构允许ca 120使用单个clientack消息确认多个serversubmit消息,并允许sa 110使用单个serverack消息确认来自给定ca的多个clientsubmit消息。
101.示例通信
102.转向图3和图4,为了提供通信协议的概述,提供了两个示例消息传送图,以说明上述协议的操作。接下来,提供了关于服务器sm 112和客户端sm 124在生成和处理消息时的操作的进一步细节。
120a和ca 120b)。实际上,如果需要,可以使用这样的前缀,但这不是必需的,因为sa 110为每个连接的客户端维护单独的状态数据。
119.在402和403,ca 120a和ca 120b启动与sa 110的连接。在这两种情况下,连接消息都是:connect(y,0-0,[a/b]0),表示连接的对象id是y;对象的服务器版本0-0;并且对于两个ca,其对象的本地版本标识符从[a/b]0开始。
[0120]
在404,ca 120a:接收本地编辑;生成表示编辑的增量(ad1);递增客户端版本(到a1);生成并传送客户端提交消息:clientsubmit(a1,ad1)。这表明在应用editad1之后,ca 120a处的本地版本是a1。
[0121]
在406,sa 110接收clientsubmit消息re ad1。
[0122]
在408,sa 110将增量ad1应用于对象的服务器版本。这通常涉及生成对应于在clientsubmit消息中接收的增量的服务器增量(在这种情况下是sd1)。然而,由于增量ad1是第一增量变换,所以不需要变换(或者,变换过程将在与增量ad1相同的服务器增量中结束)。应用增量会导致更新的服务器版本,在本示例中,sv=1-0,如下所述,将增量添加到对象的历史中。
[0123]
sa 110随后生成并向ca 120a传送serverack:serverack(1-0,a1)。这向ca 120a指示服务器已经接收到来自ca 120a的客户端版本a1之前的所有clientsubmit,并且在这些clientsubmit中应用增量,将对象的服务器版本带到版本1-0。
[0124]
sa 110还生成serversubmit消息并将其传送到所有其他连接的客户端,在此情况下为ca 120b:serversubmit(1-0,sd1)。这向ca120b指示在应用增量sd1之后,对象的服务器本地版本是1-0。
[0125]
在410,ca 120b接收serversubmit消息re sd1。
[0126]
在412,ca 120b将增量sd1应用于其对象的本地版本。如下所述,这可能涉及变换在serversubmit消息中接收的增量(在这种情况下是sd1)。ca 120b然后生成并传送clientack消息:clientack(1-0)。当被sa 110接收时,这指示ca 120b已经接收到服务器版本1-0之前的所有serversubmit消息。
[0127]
在414,ca 120b:接收本地编辑;生成表示编辑的增量(bd1);递增客户端版本(到b1);生成并传送客户端提交消息:clientsubmit(b1,bd1)。这表明在应用编辑bd1之后,ca 120b处的本地版本是b1。
[0128]
在416,sa 110接收clientsubmit消息re增量bd1。
[0129]
在418,sa 110将增量bd1应用于对象的服务器版本。如下所述,这涉及生成对应于在clientsubmit消息中接收的增量的服务器增量(在这种情况下是sd2)。一旦应用了增量,sa 110就更新服务器版本,在本示例中为sv=2-0。
[0130]
sa 110随后生成并向ca 120b传送serverack:serverack(2-0,b1)。这向ca 120b指示服务器已经接收到来自ca 120b的客户端版本b1之前的所有clientsubmit,并且在这些clientsubmit中应用增量,将对象的服务器版本带到版本2-0。
[0131]
sa 110还生成并向ca 120a传送serversubmit消息:serversubmit(2-0,sd2)。这向ca 120a指示在应用编辑sd2之后,对象的服务器本地版本是2-0。
[0132]
在420,ca 120a接收serversubmit消息re sd2。
[0133]
在422,ca 120a将增量sd2应用于其对象的本地版本。如下所述,这可能涉及变换
在serversubmit消息中接收的增量(在这种情况下是sd2)。ca 120a然后生成并传送clientack消息:clientack(2-0)。当被sa 110接收时,这指示ca 120a已经接收到服务器版本2-0之前的所有serversubmit消息。
[0134]
图4描绘了在ca 120b(在424)和ca 120a(在434)对相关消息/处理进行的额外本地编辑。这类似于上述消息/处理。
[0135]
对象同步
[0136]
当ca 120接收到增量(例如,在serversubmit消息中)时,必须将该增量应用于所述对象的客户端本地版本。类似地,当sa 110接收到增量(例如,在clientsubmit消息中)时,必须将该增量应用于所述对象的服务器版本。
[0137]
如下文所述,在某些情况下,ca 120或sa 110可在应用单个增量之前,将多个增量组合成单个增量(经由一个或多个组成操作)。
[0138]
为了应用给定的增量,在大多数情况下,变换操作是必要的。这是为了说明在提交消息中接收到的增量可能是由提交消息的发送者对与提交消息的接收者处的对象的当前版本不同的对象版本进行的。
[0139]
下文进一步讨论了变换操作。这一部分描述了sa 110和ca 120管理增量和版本号的方式。在本实现方式中,增量管理(和同步)由同步模块(sm)处理。
[0140]
首先,将描述客户端应用程序客户端sm 124的操作。接下来,将描述服务器应用服务器sm 112的操作。
[0141]
客户端应用程序同步
[0142]
图5提供了客户端同步模块(sm)124、客户端编辑器模块(em)122和协作服务器110之间的交互。
[0143]
在特定对象的协作编辑期间,客户端sm 124为该特定对象维护客户端增量缓冲器502。
[0144]
本公开中的本地编辑是非阻塞的。因此,当ca 120的用户对正在协作编辑的对象进行编辑时,em 122立即将该编辑应用于该对象的本地版本(即,在传送任何clientsubmit消息和/或接收任何serverack消息之前)。
[0145]
在进行本地编辑时,em 122还向客户端sm 124传送与编辑相关的数据。
[0146]
然后,客户端sm 124生成与编辑相关的本地增量。在替代实现方式中,em 122可以生成增量,并将其传送到客户端sm 124。
[0147]
然后,客户端sm 124将增量置于客户端增量缓冲器502中。在本实施例中,客户端sm 124将客户端增量缓冲器中的增量标记为未确认的(即,ca 120已经在clientsubmit消息中向sa 110传送的增量)或未决的(即,ca 120还没有向sa 110传送的增量)。
[0148]
因此,首先,对应于本地编辑的给定增量作为未决增量放置在客户端缓冲器中。
[0149]
客户端sm 124定期为缓冲器中的未决增量生成clientsubmit消息。一旦关于未决增量的clientsubmit消息被传送到sa 110,客户端sm 124就将该增量标记为未确认的增量。
[0150]
在本实施例中,客户端sm 124在生成clientsubmit消息时向增量分配客户端版本标识符。即,当clientsubmit消息中包括增量时,客户端sm 124更新当前版本标识符(例如,通过递增由客户端sm 124维护的当前客户端版本变量)并将该版本标识符与增量相关联。
[0151]
在替代实施例中,客户端sm 124可以被配置为在增量添加至客户端缓冲器502时更新客户端版本标识符并将其分配给增量(即,作为未决增量)。然而,这可能导致产生/分配不必要的版本标识符,例如,在客户端方增量缓冲器502中的未决增量如下所述组合(组成)的情况下。
[0152]
客户端sm 124可以被配置为以多种方式处理客户端缓冲器502中的未决增量(通过生成clientsubmit消息)。例如,客户端sm 124可被配置为实现用于生成clientsubmit消息的滑动窗口类型方案:即,使得在任何给定时间在缓冲器中允许最大数量的未确认增量。
[0153]
作为一个示例,如果滑动窗口(最大数量)设置为8,则客户端sm 124最多可向cs 110传送八条clientsubmit消息,而不会接收到serverack消息。一旦接收到serverack消息,客户端sm 124可以发送一个或多个另外的clientsubmit消息。
[0154]
相反,如果滑动窗口(最大数量)设置为1,则客户端sm 124可在必须等待serverack消息之前向cs 110传送单个clientsubmit消息。在某些方面,使用这种大小(1)的窗口将导致协作平台类似于现有的协作平台,现有的协作平台要求在可以发送进一步增量之前确认提交的每个增量。
[0155]
可以实现额外逻辑,以确定给定客户端sm 124的窗口尺寸(由sm 124自身和/或sa 110确定)。例如,给定的客户端sm 124可以选择抑制其发送clientsubmit消息的速率,例如,每250毫秒发送一条消息。给定的客户端sm 124还可以监控其clientsubmit消息和接收相应的serverack确认之间的等待时间,并将其发送速率调整为窗口尺寸/等待时间,以便以保持稳定的最快提交速率为目标。
[0156]
然而,一般而言,给定的客户端a的小窗口尺寸意味着其他客户端将以较慢且较大的数据块观察客户端a的编辑操作。窗口尺寸为1意味着客户端的编辑最终将被分块为不小于客户端到服务器的往返时间的单元。大窗口尺寸意味着客户端a可以以更快的速度提交更细粒度的编辑,使得其他客户端将观察到a的编辑更平滑。然而,潜在的缺点是,以更快的速度发送提交需要更多的服务器处理来跟上更高的消息吞吐量。
[0157]
当客户端sm 124从cs 110接收到serverack消息时,从客户端缓冲器502中清除所有未确认的增量,直至(包括)与serverack消息中指示的客户端版本标识符相关的增量。
[0158]
客户端sm 124还可(在任何时候)接收包含服务器增量(即,另一客户端对对象进行编辑的增量)的serversubmit消息。
[0159]
当接收到serversubmit消息时,客户端sm 124对其进行处理。
[0160]
在某些情况下,sm 124可立即处理已接收到的serversubmit消息。最初,这涉及确定是否需要变换在serversubmit消息中接收的增量。如果在客户端缓冲器502中有任何增量(未决或未确认),则将需要变换。如果没有,则不需要变换。
[0161]
如果客户端缓冲器502中有一个或多个增量,则客户端sm 124针对客户端缓冲器中的所有增量(未决和未确认)变换服务器提交消息中包含的增量。(增量变换将在下面进一步讨论)。
[0162]
然后,客户端sm 124将增量(必要时进行变换)应用于客户端的对象的当前版本(例如,当前状态)。这涉及与em 122通信,以使其显示由应用增量引起的对对象的编辑。
[0163]
一旦应用了增量,sm 124生成clientack消息,包括serversubmit消息中包含的服务器版本标识符。
[0164]
在其他情况下,一旦接收到serversubmit消息,sm 124可延迟处理该消息。在这种情况下,如果在sm 124处理原始serversubmit消息之前接收到额外的serversubmit消息,则sm 124将那些serversubmit消息中包括的增量组成在一起,以生成经组成的服务器增量。
[0165]
sm 124随后确定是否需要变换经组成的服务器增量。如上所述,如果在客户端缓冲器502中有任何增量(未决或未确认),则将需要变换。如果没有,则不需要变换。
[0166]
如果客户端缓冲器502中有一个或多个增量,则客户端sm 124针对客户端缓冲器中的所有增量(未决和未确认)变换经组成的服务器增量。客户端sm 124随后将经组成的增量(如果必要的话进行变换)应用于客户端处的对象的当前版本(例如,当前状态)。
[0167]
在以这种方式组成serversubmit消息的情况下,一旦生成和/或应用了组成增量,sm 124可生成clientack消息,包括最新serversubmit消息中包含的服务器版本标识符。
[0168]
下文提供了各种示例,以说明上述处理。
[0169]
在这些示例中,针对本地编辑生成的每个增量作为缓冲对象添加至客户端缓冲器。未决缓冲对象具有以下格式:
[0170]
{δ}
[0171]
未确认的缓冲对象具有以下格式:
[0172]
[δ,x]
[0173]
在这两种情况下,δ为增量。对于未确认的缓冲对象,x是客户端版本标识符(在本示例中是递增的整数)。
[0174]
此外,维护客户端缓冲器,作为有序数据结构,例如,列表、堆栈、队列或其他有序数据结构。因此,缓冲对象在缓冲器中的位置很重要,并表示顺序。
[0175]
虽然为提高可读性采用了上述格式,但在本实施例中,缓冲器中给定缓冲对象的相关方面为:可确定其相对于缓冲器中其他增量的顺序;可以被标识为未决或未确认的增量;对于未确认的增量,该对象允许确定与该增量相关联的客户端版本。
[0176]
客户端应用程序同步:示例1
[0177]
在该示例中,所述对象的协作编辑从客户端版本0(cv=0)和服务器版本0-0(sv=0-0)开始。
[0178]
第一本地编辑(对对象的本地版本0进行)产生如下增量缓冲:
[0179]
{δa}
[0180]
即,具有单个未决增量的缓冲器。
[0181]
然后,客户端sm 124:递增客户端版本标识符(从0到1);生成clientsubmit消息(1,δa)并将其传送到sa 110;以及修改缓冲器中的缓冲对象,以将其标记为未确认的增量,产生如下增量缓冲器:
[0182]
[δa,1]
[0183]
然后,客户端sm 124接收serverack消息,例如(1-0,1),指示sa 110已接收到cv=1之前的客户端消息。在接收到该消息时,客户端sm 124可以从缓冲器中移除缓冲对象[δa,1](在这种情况下导致空缓冲器)。
[0184]
客户端应用程序同步:示例2
[0185]
在该示例中,所述对象的协作编辑从客户端版本0(cv=0)和服务器版本0-0(sv=
0-0)开始。
[0186]
再次,第一本地编辑(对对象的本地版本0进行)产生如下增量缓冲:
[0187]
{δa}
[0188]
然后,客户端sm 124执行处理,以生成clientsubmit消息(1,δa)并将其传送至sa 110(如上文示例1所述)。这导致如下增量缓冲:
[0189]
[δa,1]
[0190]
然后进行第二本地编辑,产生如下增量缓冲:
[0191]
[δa,1]{δb}
[0192]
然后进行第三本地编辑,产生如下增量缓冲:
[0193]
[δa,1]{δb}{δc}
[0194]
在该示例中,客户端sm 124执行处理,以生成/向sa 110传送与缓冲器中的前两个未决缓冲对象相关的单独的clientsubmit消息:即clientsubmit(2,δb)和clientsubmit(3,δc)。得到的增量缓冲器为:
[0195]
[δa,1][δb,2][δc,3]
[0196]
然后,客户端sm 124可接收serverack消息,例如,(1-0,2),指示sa 110已接收到cv=2之前的客户端消息。在接收到该消息时,客户端sm 124可以从缓冲器中移除缓冲对象[δa,1]和[δb,2],从而产生客户端缓冲器:
[0197]
[δc,3]
[0198]
(相反,如果serverack消息为(1-0,3),则客户端sm 124可从缓冲器中移除所有缓冲对象,从而产生空的客户端缓冲器。)
[0199]
客户端应用程序同步:示例3
[0200]
在示例2中,单个serverack消息用于确认多个clientsubmit消息。
[0201]
作为更一般的情况,考虑具有以下状态的缓冲器:
[0202]
[δa,1][δb,2]...[δ,i][δ,j]{δx}{δy}...
[0203]
在这种情况下,(x-x,i)的serverack消息用于确认客户端缓冲器中的所有未确认的客户端缓冲对象,直到并且包括cv=i的缓冲对象,即产生以下缓冲器:
[0204]
[δ,j]{δx}{δy}...
[0205]
客户端应用程序同步:示例4
[0206]
在示例2中,生成以下增量缓冲:
[0207]
[δa,1]{δb}{δc}
[0208]
在这种情况下,客户端sm 124可通过对其增量执行组成操作(如下所述,组合(δb,δc)),将两个未决缓冲对象组合成单个缓冲对象,而不是针对前两个未决缓冲对象生成/传送单独的clientsubmit消息。客户端sm 124随后生成具有组成增量(在这种情况下表示为δbc)的新的未决缓冲对象,并替换现在已经与新的缓冲对象组合的缓冲对象,从而产生增量缓冲器:
[0209]
[δa,1]{δbc}
[0210]
客户端sa124可在新的缓冲对象上生成/传送clientsubmit消息,即:clientsubmit(2,δbc),从而产生客户端缓冲器:
[0211]
[δa,1][δbc,2]
[0212]
然后,客户端sm 124可接收serverack消息,例如,(1-0,2),指示sa 110已接收到cv=2之前的客户端消息。在接收到该消息时,客户端sm 124可以移除缓冲对象[δa,1]&[δbc,2],从而产生空的客户端缓冲器。
[0213]
更一般地,客户端sm 124可以被配置为将任意数量的相邻待处理缓冲对象(或相邻本地增量)组合成单个增量,并将该单个增量包括在单个clientsubmit消息中。为此可以采用各种方法。
[0214]
例如,客户端sm 124可在将本地增量添加到缓冲器时将其组成在一起。例如,当客户端缓冲器没有待决增量时生成的本地增量被添加到缓冲器中,作为待决增量。当客户端缓冲器具有未决增量时生成的本地增量与该未决增量组成,然后将经组成的增量作为未决增量添加到客户端缓冲器(替换现有的未决增量)。当采用这种方法时,客户端缓冲器将在任何给定时间保持单个未决增量。
[0215]
替代地,客户端sm 124可在临时列表(或其他数据结构)中存储新的本地增量,然后通过将临时列表中的所有增量组成单个增量,然后生成包括该单个增量的单个clientsubmit消息,来定期清除临时列表。在某些情况下,这种方法在生成clientsubmit消息时保持然后批量组成本地增量,提供了比在新的本地增量到达时连续执行组成操作更有效的处理。
[0216]
客户端应用程序同步:示例5
[0217]
在该示例中,对象的协作编辑从客户端版本0(cv=0)和服务器版本0-0(sv=0-0)开始。
[0218]
在该示例中,生成了两个本地编辑,并针对这些编辑中的第一个发送clientsubmit消息。这将如下产生缓冲器
[0219]
[δcl,1]{δc2}
[0220]
然后,客户端sm 124接收serversubmit消息:serversubmit(1-0,δs1)。
[0221]
为了处理serversubmit消息,客户端sm 124确定客户端缓冲器中存在增量。因此,客户端sm 124针对客户端缓冲器中的所有增量(在这种情况下为δc1&δc2)来变换serversubmit消息中的增量(在这种情况下为δs1)。
[0222]
图6提供了表示所述三种编辑的示例状态空间图600。
[0223]
在本公开所用的状态空间图中(例如,图6、图7、图9和图10):实线方框表示实际对象状态(即,通过应用增量生成的对象状态);连接两个对象状态的实线箭头表示已经应用于一个对象状态(箭头开始时的状态)以生成另一个对象状态(箭头结束时的状态)的增量;虚线框表示潜在的对象状态(即可以通过应用增量生成的对象状态);连接两个对象状态的虚线箭头表示可以应用于一个对象状态(箭头开始时的状态)以生成另一个对象状态(箭头结束时的状态)的增量。
[0224]
状态空间600的状态602表示对象的起始状态(sv=0-0,cv=0)。此时,对象的客户端和服务器版本是同步的(即sv0-0=cv0)。
[0225]
从状态602,ca 120本地应用增量δc1,将对象的客户端状态转换到状态604(cv=1)。从状态604,ca 120本地应用增量δc2,将对象的客户端状态转换到状态606(cv=2)。
[0226]
同时,sa 110应用增量δs1(从另一客户端接收),将对象的服务器状态转换到状态608(sv=1-0)。
[0227]
如状态空间图620中所示,为了应用增量δs1,客户端应用程序客户端sm 124首先需要针对本地增量进行变换。
[0228]
为此,客户端sm 124可以例如:对(δc1,δs1)执行变换操作,以生成(δc1’,δs1’);然后对(δc2,δs1’)进行变换操作,以生成(δc2’,δs1”)。
[0229]
然后,客户端sm 124可将增量δs1”应用于对象的本地版本(即状态606)。
[0230]
然后,客户端sm 124生成/传送clientack消息,指示其为当前服务器版本(例如,clientack(1-0))。
[0231]
此时,如果未进行其他编辑,一旦服务器sa 110接收/变换/应用了客户端的本地编辑δc1和δc2,对象的客户端和服务器版本将同步。
[0232]
客户端应用程序同步:示例6
[0233]
在上述示例5中,当缓冲器处于以下状态时,客户端的客户端sm 124接收到serversubmit消息(serversubmit(1-0,δs1))。
[0234]
[δc1,1]{δc2}
[0235]
在示例5中,通过执行两个变换操作来处理serversubmit消息,以(最终)生成δs1”,然后将其应用于对象的客户端版本。
[0236]
然而,如下文所述,本公开提供了满足变换/组成交换特性的组成和变换函数。为了说明这一点,代替执行如以上示例5中所述的两个变换操作,变换/组成交换特性将允许客户端sm 124:对两个本地客户端增量(例如,组成(δc1,δc2))执行组成,以生成单个增量δc(1,2));针对服务器增量变换该单个增量(例如,变换(δc(1,2),δs1)=(δc(1,2)’,δs1)”);然后将经变换的服务器增量(δs1”)应用于对象的当前本地状态。
[0237]
图7的状态空间图700提供了一个示例。
[0238]
一旦客户端sm 124变换并应用服务器增量,客户端sm 124生成/传送clientack消息,指示其为当前服务器版本(例如,clientack(1-0))。
[0239]
此时,如果未进行其他编辑,一旦服务器sa 110接收/变换/应用了客户端的本地编辑δc1和δc2,对象的客户端和服务器版本将同步。
[0240]
虽然该特定示例用于说明变换/组成交换特性,但在处理服务器提交消息中接收的服务器增量的过程中,客户端sm 124不太可能被配置为从客户端增量缓冲器中组成多个客户端增量。即使这样做了,客户端sm 124也需要在客户端增量缓冲器中保留各个增量,至少是为了确认和客户端重新连接的目的(下面将进一步讨论)。
[0241]
更实际地,变换/组成交换特性允许通过组成服务器增量序列,针对客户端增量变换由组成产生的增量以生成变换的增量,然后将变换的服务器增量应用于对象的当前本地(客户端)状态,针对任何长度的服务器增量序列(在serversubmit消息中接收)变换客户端增量(未确认或未决)。
[0242]
例如,考虑具有以下状态的客户端sm 124缓冲器:
[0243]
[δc1,1]
[0244]
以及接收三个serversubmit消息序列:
[0245]
serversubmit(1-0,δs1)
[0246]
serversubmit(2-0,δs2)
[0247]
serversubmit(3-0,δs3)
[0248]
在这种情况下,客户端sm 124可通过以下方式在serversubmit消息中应用服务器增量:
[0249]
对所有服务器增量执行组成,例如:
[0250]
组成(δs1,(组成(δs2,δs3)))=组成服务器增量δs(1,2,3)
[0251]
针对经组成的服务器增量变换客户端增量,例如:
[0252]
变换(δc1,δs(1,2,3))=(δc1

,δs(1,2,3)

)
[0253]
将经变换的经组成服务器增量(δs(1,2,3)

)应用于客户端的当前对象状态。
[0254]
在该示例中,给定ca 120的服务器增量累积、组成在一起,然后以与上述类似的方式针对客户端增量进行变换。
[0255]
更一般地,当客户端具有n条未确认的clientsubmit消息,并且接收m条serversubmit消息时,面临图11所示的情况。在这种情况下,不进行n
×
m次变换,而是变换/组成交换特性允许客户端将来自serversubmit消息的m个增量组成为一个增量,然后仅进行n次变换(类似于图6的场景620)。这样做会导致客户端执行n m个工作单元,而不是nxm个工作单元。
[0256]
这种情况在服务器侧处理中是对称的。例如,服务器可以将接收到的n个clientsubmit消息的增量组合成单个增量,然后进行m次变换,m条未确认的serversubmit消息的每个增量具有一次变换。
[0257]
服务器应用程序同步
[0258]
服务器应用程序同步在许多方面类似于上述客户端应用程序同步。然而,也有不同之处。
[0259]
对于服务器应用程序同步,消息处理在某种意义上与客户端应用程序同步相反。例如,服务器sm 112以类似于客户端sm 124处理服务器提交消息的方式来处理clientsubmit消息。
[0260]
当然,另一个区别是sa 110可从许多客户端接收clientsubmit/clientack消息(与从单个服务器接收serversubmit/serverack消息的ca 120相反)。
[0261]
为了解决这一问题,如图8所示,服务器sm 112为连接至对象的每个客户端提供同步器802,每个同步器802为其客户端维护服务器侧增量缓冲器。在所示的示例中,两个客户端120a和120b连接到这些对象。因此,服务器sm 112提供:用于客户端120a的同步器802a和服务器侧客户端缓冲器804a以及用于客户端120b的同步器802b和服务器侧客户端缓冲器804b。
[0262]
当sa 110接收到传入消息(例如,clientsubmit或clientack消息)时,服务器首先识别始发ca 120:即,消息源自的连接ca 120。例如,可以通过参考与ca 120/sa 110连接相关联的通信协议数据和/或与客户端发起消息相关联的其他元数据来确定该发起客户端。发起客户端用于确定哪个同步器802将处理输入消息。
[0263]
在clientack消息的情况下,相关同步器802以类似于客户端sm 124处理serverack消息的方式处理消息(如上所述)。例如,通过删除客户端的服务器侧缓冲器中的对象,直到/包括与clientack消息中包含的服务器版本相关的对象。
[0264]
在clientsubmit消息的情况下,相关同步器802以类似于客户端sm 124处理serversubmit消息的方式处理消息(如上所述)。例如,同步器802确定clientsubmit消息中
的增量是否需要变换(如果在相关服务器侧客户端缓冲器804中存在任何未决或未确认的增量,将会是这种情况),并且如果需要,则进行变换。此外,同步器促使增量保存在规范对象历史806中(在对象历史项目中,如下面进一步描述的)。
[0265]
规范对象历史
[0266]
如上所述,sa 110维护sa 110管理的每个对象的规范对象历史。用于维护给定对象的规范对象历史的各种机制是可能的。
[0267]
一般而言,对象历史可以被实现为具有各种特性,包括仅被附加以及可被所有连接的客户端观察到。
[0268]
对象历史还支持锁定:如果接收到并发操作,则只有一个操作能够成功。在某些实现方式中,可以实现乐观锁定。在这种情况下,如果提交失败,则所述客户端可以使用对象历史与服务器版本重新同步。在替代实现方式中,可以提供悲观锁定机制。
[0269]
在一种实现方式中,redis流可用于维护给定对象的规范历史。
[0270]
在本实施例中,规范对象历史由服务器sm 112维护(例如,历史806)。在替代实现方式中,对象历史可以由与服务器sm 112通信的单独模块/应用程序来维护。
[0271]
如下所述,同步器802被配置为添加与客户端增量(即,在clientsubmit消息中接收的增量)相对应的对象历史项目,这些客户端增量被处理为对象历史。在本实施例中,每个对象历史项目包括增量(即项目涉及的增量)和服务器版本标识符(指示应用增量后的服务器版本)。对象历史项目还可以包括客户端标识符(指示增量源自的特定ca(或用户帐户))和客户端版本标识符(取自导致生成对象历史项目的clientsubmit消息)。例如:
[0272]
[sv,δ,client_id,cv]
[0273]
在某些实现方式中,在对象历史项目中包含客户端标识符和客户端版本标识符是可选的。例如,这允许服务器系统102注入并非源自任何连接的ca120的编辑(即,增量),并且因此导致没有客户端id或客户端版本标识符的对象历史项目。
[0274]
每个同步器802还被配置为访问对象历史,并随着时间的推移,依次处理添加到其中的所有项目。
[0275]
当同步器处理对象历史的项目时,首先确定该项目的client_id是否指示该项目涉及源自同步器自身客户端或不同客户端的增量。例如,如果所述对象历史项目具有客户端id 120a,并且同步器802与客户端120a相关联,则该项目与同步器自己的客户端相关联。
[0276]
如果项目与同步器自身的客户端相关联,则同步器802基于项目生成serverack消息,并将serverack消息传送至其客户端。然后,处理对象历史项目,同步器可以处理下一个对象历史项目。
[0277]
如果该项目与另一个客户端相关联(经由替代的client_id确定)或不与客户端相关联(在这种情况下,由于缺少client_id而确定),则项目中的增量并非源自同步器的客户端。在这种情况下,同步器802基于该项目生成serversubmit消息。serversubmit消息包括项目的增量和服务器版本标识符。然后,处理对象历史项目,同步器可以处理下一个对象历史项目。
[0278]
一旦所有同步器802均已处理完对象历史806中的所有项目(且所有客户端均已处理了由此产生的serversubmit消息),对象被同步:即,对象在sa 110处的状态和对象在所有连接的ca120处的本地状态相同。
[0279]
在ca 120从sa 110断开的情况下,ca 120可以重新连接。
[0280]
为此,ca 120生成并传送连接消息,其客户端版本标识符值在其缓冲器中任何未确认客户端提交的客户端版本值之前。
[0281]
然后,ca 120针对其缓冲器中的每个未确认增量重新发送clientsubmit消息。在为给定的未确认增量重新发送clientsubmit消息时,ca 120使用与最初为该增量生成/传送到服务器的clientsubmit消息中使用的相同的客户端版本标识符。然而,如果在此期间进行了变换,则增量可能会有所不同。
[0282]
为了便于以这种方式重新连接,clientsubmit消息由服务器同步模块112中的客户端同步器802进行幂等处理。这使得客户端可以安全地重新发送任何clientsubmit消息,而无需ssm 112两次应用任何增量。
[0283]
为此,ssm 112以与跟踪每个客户端的最新客户端版本的规范对象历史(例如,redis数据存储器)相同的持久性维护客户端状态表。如果对象由x标识,则客户端状态可以如下记录:
[0284]
clientstate(x,client_id,客户端版本标识符)
[0285]
客户端同步器为向对象历史记录添加增量而执行的每个事务也确保其客户端版本与clientstate表中的客户端的最新客户端版本相匹配,并(以事务方式)将其更新为添加至对象历史记录的条目的客户端版本。该事务可以乐观地或悲观地执行(尽管在使用redis数据存储器的情况下,该事务是乐观的,因为redis支持这样的事务)。
[0286]
当客户端同步器802通过执行该事务来处理clientsubmit(cv,d),以向对象历史添加条目时,检查客户端状态条目的客户端id。如果客户端同步器802确定clientsubmit消息的cv不大于clientstate表中最后记录的客户端版本,则可以简单地忽略该clientsubmit消息(在这种情况下,clientsubmit消息被解释为已经被重新提交的消息)。
[0287]
在一些实现方式中,客户端同步器802被配置为执行额外步骤,以验证已接收到这种clientsubmit消息。这涉及在规范对象历史中找到先前接收的clientsubmit消息(即,与正在处理的消息具有相同客户端版本标识符的消息),并检查增量是否“相同”(在任何必要的变换之后)。
[0288]
存储在对象历史806中的数据允许任何ca 120将其对象的本地版本与服务器版本重新同步,例如,在ca 120与sa 110断开、消息出错或出现其他问题的情况下。
[0289]
如下描述每种消息类型的服务器侧处理示例。
[0290]
服务器应用程序同步:clientsubmit消息
[0291]
在接收到clientsubmit消息时,服务器sm 112首先确定消息来自哪个ca 120,因此确定哪个同步器802将对其进行处理。在本示例中,clientsubmit消息来自ca 120a,因此,该消息(或来自其的相关数据)被传送到同步器802a。
[0292]
同步器802a随后确定clientsubmit消息中的增量是否需要变换。如果在客户端120a的服务器侧缓冲器804a中没有增量,则不需要变换该增量。否则,增量确实需要变换,并且同步器802a进行这种变换(例如,如上面的客户端应用程序同步:示例5或客户端应用程序同步:示例6中所述)。
[0293]
同步器802a随后为增量创建对象历史项目,并将该项目保存至对象历史806。对象历史项目包括客户端120a的标识符、客户端版本标识符、经变换的增量和服务器版本标识
符(在当前情况下,由工具(redis)生成,当对象项被添加到其中时,该工具用于维护对象历史)。例如:
[0294]
[12345-1,δx,120a,a1]
[0295]
以与上述客户端sm 124的操作类似的方式,客户端同步器802a可延迟处理已接收的clientsubmit消息,而不是立即尝试变换客户端提交消息中的增量并将其添加至对象历史806。在这种情况下,如果在同步器802a处理原始clientsubmit消息之前接收到额外的clientsubmit消息,则同步器802a将那些clientsubmit消息中包括的增量组成在一起,以生成经组成的客户端增量。同步器802a然后在将产生的(单个)增量添加到对象历史项目中的对象历史806之前,针对服务器侧客户端缓冲器804a中的任何增量(未决的或未确认的)和对象历史806中的任何相关增量来变换经组成的客户端增量。在这种情况下,对象历史项的客户端版本被设置为其增量已经组成在一起的clientsubmit消息的最新客户端版本标识符。
[0296]
在将clientsubmit消息的增量(必要时进行变换)添加至对象历史之前,同步器802a确保服务器侧增量缓冲器804a已赶上最新历史(根据存储在对象历史806中的对象历史项目,其中一些可能尚未由同步器802a处理)。
[0297]
为此,进行两次变换过程。在第一次变换过程中,clientsubmit的增量被变换成超过当时在同步器的服务器侧增量缓冲器804a中的增量(这可能在持久性上落后于提交的对象历史)。这一传送发生在具有对象历史806的任何事务之外,因此可以由可能试图向对象历史提交增量的任何同步器并行执行。一旦来自clientsubmit消息的增量相对于服务器侧增量缓冲器804a是最新的(即,已经针对其中的增量进行了变换),则执行第二次变换过程。在第二次变换过程中,启动对象历史事务。在这一点上,发现对象历史806中的任何额外条目,并且如果必要的话,针对这种额外条目的增量进一步变换clientsubmit的增量。由上面讨论的变换/组成交换特性提供以这种方式处理来自客户端提交消息的增量的能力,即针对服务器侧增量缓冲器804a中的增量变换clientsubmit增量的第一变换过程以及针对任何相关对象历史项目中的增量进一步变换增量(如果必要)的第二变换过程。
[0298]
客户端同步器802a可以被配置为执行单次遍历。然而,在许多情况下,这种方法效率较低,因为会使事务打开的时间更长。如果实现单次遍历方法,单次遍历将涉及打开事务,查询尚未在服务器侧缓冲器802a中显示的任何额外历史项目,然后针对所有服务器侧缓冲器增量和所有额外历史项目的组成来变换clientsubmit。在这种情况下,当提交事务时,将丢弃作为事务的一部分读取的任何额外历史项目。此时不将其添加到服务器侧缓冲器804a中。相反,经由正常填充该缓冲器的订阅,在适当的时候出现在服务器侧缓冲器804a中。
[0299]
然后,clientsubmit消息的处理完成。
[0300]
服务器应用程序同步:serverack消息
[0301]
在适当的时候,当同步器804a处理对象历史806中的项目时,将遇到该项目(即,[12345-1,δx,120a,a1])。
[0302]
处理项目时,同步器802a首先分析项目中的客户端标识符,以确定项目是否源自其自身的客户端。在这种情况下,客户端标识符120a是与同步器804a相关联的客户端。
[0303]
在确定这一点时,同步器804a生成serverack消息,该消息包括项目的服务器版本
标识符和相关客户端版本标识符(从对象历史项目中获得)。
[0304]
同步器804a随后向其客户端应用程序ca 120a发送serverack消息。
[0305]
对来自对象历史806的项目的处理完成。
[0306]
服务器应用程序同步:serversubmit消息
[0307]
同步器802b也处理来自对象历史806的项目,并在适当的时候遇到上述示例项目:
[0308]
[12345-1,δx,120a]
[0309]
处理该项目时,同步器802b首先分析项目中的客户端标识符,以确定项目是否源自其自身的客户端。在这种情况下,客户端标识符120a不是与同步器804b相关联的客户端。
[0310]
因此,同步器802b创建缓冲对象,并将缓冲对象添加至服务器侧增量缓冲器802b。缓冲对象基于该项目,并且以类似于客户端sm 124在进行本地客户端编辑时创建缓冲对象的方式来创建。然而,服务器同步器802b的缓冲对象包括服务器版本标识符。例如,处理上述项目如下生成缓冲对象(最初是未决的):
[0311]
{δx,120a}
[0312]
然后,同步器806以类似于客户端sm 124处理客户端缓冲器的方式处理服务器侧缓冲器中的项目。例如,同步器802可以将给定客户端的服务器侧增量缓冲器804中的多个未决缓冲对象一起组成单个(组合的)缓冲对象。(参见上面的客户端应用程序同步:示例4。)
[0313]
在适当的时候,同步器802b将基于上述缓冲对象生成serversubmit消息,并将其传送至客户端120b。这样做,同步器802b更新缓冲对象,以反映该对象现在是未确认的缓冲对象:
[0314]
[δx,120a]
[0315]
此外,与客户端sm 124一样,同步器802可以被配置为定义缓冲器中未确认缓冲对象的最大数量。同步器802可以被配置为动态地为其特定客户端设置最大数量。这样做,同步器802有效地抑制了到其客户端的serversubmit消息。例如,如果同步器802a确定其客户端120a花费太长时间来确认serversubmit消息,则可以减小窗口尺寸(即,允许的未确认serversubmit消息的最大数量)者甚至断开其客户端。同时,如果同步器802b确定其客户端120b正在快速响应于serversubmit消息,则可以增加窗口尺寸。
[0316]
服务器应用程序同步:clientack消息
[0317]
在操作期间,服务器sa112将接收clientack消息(每个消息包括服务器版本标识符)。
[0318]
当接收到clientack消息时,服务器sa112首先确定消息的始发ca 120,并相应地确定相关同步器802。
[0319]
同步器802随后清除客户端的服务器侧增量缓冲器804,直至(包括)与clientack消息中指示的服务器版本相关的缓冲对象。
[0320]
上述通信协议(以及本文所述的操作变换处理)允许合并消息序列。换言之,给定的ca 120(或sa 110)可以发送多个提交消息,而不必等待任何确认。此后,ca 120可以用单个clientack消息来确认几个serversubmit消息,并且sa 110可以用单个serverack消息来确认来自给定ca的几个clientsubmit消息。
[0321]
通过提供平台,客户端或服务器应用程序可一次发送多个提交,而不是被迫一次
发送一个,可提供“更平滑”或“不太抖动”的用户体验。为了说明这一点,考虑由ca 120显示的编辑的以下两个示例(示例的每一行指示状态改变/新编辑):
[0322][0323][0324]
可以看出,在版本1中,用户最初会看到小编辑,然后是延迟,然后是大的成簇编辑,然后是延迟,然后是另一个大的成簇编辑。“t”和“the quick b”之间的延迟表示客户端到服务器的往返时间。
[0325]
在版本2中,用户将看到一系列小的编辑。如果窗口尺寸(如前所述)足够大,则其他客户端看到的这些编辑的间隔不需要受创作客户端到服务器的往返时间的限制。
[0326]
此外,允许一次进行多个提交,允许提交消息在传输中任意缓冲/排队(由sa 110或ca 120,或甚至代理)。连续缓冲/排队的消息可以在变换前合并成一条消息,从而比要求确认每个单独提交的协议更有效地实现同步。这也允许一种架构,其中,多个客户端应用程序120可以通过单个代理机器被多路复用。单个代理机器可以被配置为对其接收的消息施加其自己的流控制。例如,这种代理可以被配置为通过延迟、缓冲和组成相邻的提交或确认消息来实施最大吞吐量或最小等待时间。
[0327]
电子对象、增量和增量操作
[0328]
在某些实施例中,实体的状态及其随时间的演变由所称的域来描述。在某些方面,本公开的域类似于范畴理论类别。
[0329]
本公开的域描述了实体的可能状态空间,为此,可视为类似于数据类型(例如,布尔值或数字列表)。然而,与数据类型不同,域还描述了域的实体如何从一种状态演化到另一种状态。从一种状态到另一种状态的演化步骤被称为增量。因此,域描述了可编辑实体的静态方面(即状态)和可编辑实体的动态方面(即增量)。
[0330]
在以下描述中,使用haskell typeclass语法呈现域。
[0331]
形式上,域由表示状态s的数据类型和表示增量d的数据类型参数化。在本实现方式中,每个域在其状态数据类型和增量数据类型上定义五个函数:恒等、应用、取消应用、组成和变换。在haskelltypeclass语法中,“s”是state数据类型,“d”是delta数据类型,这些函数可以如下表示:
[0332][0333]
除了这些函数(在严格的haskell方法中),还需要函数依赖|s->d,d->s。
[0334]
恒等函数将状态作为输入,并生成增量(将被称为恒等增量)。恒等增量的本质是将恒等增量应用于输入状态(使用下面描述的应用函数),返回相同的状态。
[0335]
应用函数将状态和增量作为输入,并生成状态,即通过将输入增量应用于输入状态而产生的状态。
[0336]
取消应用函数与应用函数相反。相应地,取消应用函数也将状态和增量作为输入,并输出状态,在这种情况下,该状态是对输入状态取消应用(或撤消)输入增量的结果。
[0337]
组成函数将两个连续增量作为输入,并生成单个增量,即两个输入增量的组成。
[0338]
变换函数将一对发散增量作为输入,并生成一对收敛增量,即运算变换。
[0339]
上述域函数的特征在于以下关系:
[0340][0341]
域函数关系
[0342]
变换/组成交换
[0343]
为了提供更高效的协作编辑,发明人认识到,设计/提供满足将被称为变换/组成交换特性的组成和变换函数是有利的。
[0344]
变换/组成交换特性在执行一系列变换操作后执行组成操作与执行一系列组成操作后执行单个变换操作之间建立了等价关系。换言之,先变换后组成相当于先组成后变换(即组成和变换是可交换的)。
[0345]
当域满足变换/组成交换特性时,协议可利用该特性有效地在客户端和服务器之间同步数据。上面描述了这种协议的一个示例,然而替代协议也是可能的。
[0346]
同步示例:单个服务器增量,连续客户端增量
[0347]
将参考图9的状态空间图900、920和940提供示例。
[0348]
本示例始于在特定对象状态902下同步的客户端应用程序(例如ca 120a)和sa 110。从同步状态902开始,ca 120a应用一系列增量:δc1然后δc2,这分别将对象的客户端本地版本转换到状态904和906(假设δc1和δc2被依次应用并且没有组合成随后应用的单个增量)。同时,服务器110从另一客户端应用程序(例如,ca 120b)接收增量(δs1),并将该增量应用于对象的服务器版本,这将对象的服务器版本转换到状态908。
[0349]
结果:在sa 110要处理增量δc1和δc2时,已经处理了增量δs1;在cs120a要处理增量δs1时,已经处理了增量δc1和δc2。
[0350]
如状态空间图920所示,为了处理增量δs1,常规方法是ca 120a和/或sa 110执行以下操作变换:
[0351]
变换1:(δc1,δs1)=>(δc1’
,δs1’
)
[0352]
变换2:(δc2,δs1’
)=>(δc2’
,δs
1”)
[0353]
在客户侧,ca 120a可将增量δs
1”应用于状态906,以生成状态912。在这种情况下,ca 120a执行的操作如下:
[0354]
函数注释变换(δc1,δs1)生成(δc1’
,δs1’
)变换(δc2,δs1’
)生成(δc2’
,δs
1”)应用906δs
1”从状态906转换到状态912
[0355]
在服务器侧,sa 110可将增量δc1’
应用于状态908,以生成状态910,并将增量δc2’
应用于状态910,以生成状态912。在这种情况下由sa 110执行的操作如下:
[0356]
函数注释变换(δc1,δs1)生成(δc1’
,δs1’
)变换生成(δc2’
,δs
1”)应用908δc1’
从状态908转换到状态910应用910 δc2’
从状态910转换到状态912
[0357]
替代地,sa 110可对δc1’
和δc2'执行组成操作,并将所得增量应用于中间状态908,而不是依次应用δc1’
和δc2’
。在这种情况下,服务器执行的操作如下:
[0358]
函数注释变换(δc1,δs1)生成经变换的增量(δc1’
,δs1’
)变换(δc2,δs1’
)生成经变换的增量(δc2’
,δs
1”)组成δc1’
δc2’
生成单个增量(δ(c1’
,δc2'))应用908δ(c1’
,δc2’
)从状态908转换到状态912
[0359]
通常,支持变换和组成操作的算法具有与其输入大小成线性关系的复杂性。即变换(δc,δs)为o(c s),组成(δc1,δc2)为o(ci c2)。因此,对于长度为n的客户端增量序列,这种同步方法导致总体复杂度为o(n(s c))。
[0360]
然而,通过提供满足变换/组成交换特性的组成和变换函数,该示例中的客户端同步可通过单个变换步骤实现。这要求变换和组成函数促使状态空间920中描述的和上面描述的更新路径等价于状态空间940中描述的更新路径,即使得下面两个操作序列等价:
[0361]
操作序列1操作序列2
变换(δc1,δs1)=(δc1’
,δs1’
)组成(δc1,δc2)=δ(c1,c2)变换(δc2,δs1’
)=(δc2’
,δs
1”)变换(δ(c1,c2),δs1)=(δ(c1,c2)’,δs
1”)应用906δs
1”=912应用906δs
1”=912
[0362]
这允许计算效率更高的同步。具体地,对于长度为n的客户端增量序列,改进的过程具有o(s nc)的复杂度(与先前过程的o(ns nc)的复杂度相比)。
[0363]
虽然该示例描述了针对单个服务器增量变换的两个客户端增量的序列,但是相同的原理适用于需要针对单个服务器增量变换的任意数量的客户端增量的序列。
[0364]
同步示例:连续服务器增量,单个客户端增量
[0365]
上文关于图9所述的示例涉及单个服务器更新和多个连续客户端更新。同样的原则也适用于单个客户端更新和多个服务器更新的情况。通过图10的状态空间图1000、1020以及1040描述这种情况。
[0366]
在图10的示例中,sa 110应用两个δs1和δs2,而特定ca 120(例如,ca 120a)应用单个增量δc1。
[0367]
为了重新同步对象,sa 110的常规方法是执行以下操作变换:
[0368]
变换1:(δs1,δc1)=>(δs1’
,δc1’
)
[0369]
变换2:(δs2,δc1’
)=>(δs2’
,δc
1”)
[0370]
sa 110然后可将增量δc
1”应用于状态1006,以生成状态1012(如状态空间图1020所示)。在这种情况下由sa 110执行的操作如下:
[0371]
函数注释变换(δs1,δc1)生成(δs1’
,δc1’
)变换(δs2,δc1’
)生成(δs2',δc
1”)应用1006δc
1”从状态1006转换到状态1012
[0372]
然而,根据本公开,这种情况下的服务器同步可如下通过单一变换步骤实现:
[0373]
函数注释组成(δs1,δs2)生成δ(s1,s2)变换(δ(s1,s2),δc1)生成(δ(s1,s2)’,δc
1”)应用1006δc
1”从状态1006转换到状态1012
[0374]
如上所述,虽然该示例描述了针对单个客户端增量进行变换的两个服务器增量的序列,但是相同的原理适用于需要针对单个客户端增量进行变换的任意数量的服务器增量的序列。
[0375]
当针对服务器增量序列解析客户端增量序列时,本公开提供的效率更显著。对于长度为n的客户端增量序列和长度为m的服务器增量序列,传统的同步方法是o(mn(s c))。相反,本文描述的变换/组成交换特性提供了复杂度o(ms nc)。
[0376]
更具体而言,利用变换/组成交换特性,通过将在缺少变换/组成交换特性的情况下的二次运算转变为线性运算,降低了基于运算变换(ot)的同步协议的成本。
[0377]
参考图11和图12的状态空间图,对本公开进行了进一步说明。图11和图12示出了状态空间图,其中,客户端进行三次本地编辑(δc1到δc3),同时服务器进行三次服务器编辑(δs1到δs3)。
[0378]
图11描绘了在缺少变换/组成交换特性的情况下所需的变换。在这种情况下,为了
同步,客户端可以:
[0379]
变换(δc1,δs1)=(δc1’
,δs1’
)
[0380]
变换(δc2,δs1’
)=(δc2’
,δs
1”)
[0381]
变换(δc3,δs
1”)=(δc3’
,δs1”’
)
[0382]
应用(状态1108,δs1”’
)=state 1120
[0383]
变换(δc1’
,δs2)=(δc
1”,δs2’
)
[0384]
变换(δc2’
,δs2’
)=(δc
2”,δs
2”)
[0385]
变换(δc3’
,δs
2”)=(δc
3”,δs2”’
)
[0386]
应用(状态1120,δs2”’
)=state 1122
[0387]
变换(δc
1”,δs3)=(δc1”’
,δs3’
)
[0388]
变换(δc
2”,δs3')=(δc2”’
,δs
3”)
[0389]
变换(δc
3”,δs
3”)=(δc3”’
,δs3”’
)
[0390]
应用(状态1122,δs
3”')=状态1124
[0391]
服务器需要进行一组类似的操作。
[0392]
相比之下,图12描绘了存在变换/组成交换特性时可使用的变换。
[0393]
在这种情况下,客户端可以:
[0394]
组成(δc1,(组成(δc2,δc3))=δc
123
[0395]
组成(δs1,(组成(δs2,δs3))=δs
123
[0396]
变换(δc
123
,δs
123
)=(δc
123’,δs
123’)
[0397]
应用(状态1108,δs
123’)=状态1124
[0398]
服务器执行类似的操作,然后:
[0399]
应用(状态1114,δc
123’)=状态1124
[0400]
示例域
[0401]
本部分提供了被设计用于满足上述变换/组成交换特性的示例域。
[0402]
所描述的域可用作构件域;也就是说,可以以各种方式组合,以表达各种专用数据模式。使用这些域表达的任何模式继承了上述同步效率。
[0403]
为了清楚和简洁,对于每个域,示例算法实现方式以haskell语法呈现。
[0404]
原始域
[0405]
单元域
[0406]
单元域是退化域。具有单一状态以及该状态的单一演变方式:什么都不做。
[0407]
在haskell中,可以如下表示单元域:
[0408][0409]
这样的单元域可用于测试对象。
[0410]
常量域
[0411]
常量域是状态任意的域,但仅允许恒等增量。即,值没有办法从一种状态发展到另一种状态。
[0412]
在haskell中,可以如下表示常量域:
[0413][0414]
常量域用于描述不能改变的值。在协作数据模型中,一些元素可以被赋予不可变的标识符。例如,在文档编辑器中,每一页都可能被赋予一个uuid。页面的uuid不应该改变。将一个页面的标识符表示为一个常量域,允许在这个域样式中表示其值(uuid)及其不变性(没有增量来改变其)。
[0415]
计数器域
[0416]
计数器域表示仅按增量演变的数。计数器的状态可以表示为int。计数器的增量(即增量)也可以表示为int。
[0417]
在haskell中,可以如下表示计数器域:
[0418][0419]
与单元域一样,计数器域可用于测试对象。
[0420]
高阶域
[0421]
高阶域从其他域生成,例如,当高阶数据类型从现有数据类型生成新数据类型时。
[0422]
配对和产品域
[0423]
配对域和产品域是高阶域(从某种意义上说,是从现有域产生的新域,与高阶数据类型从现有数据类型产生新数据类型的方式相同)。
[0424]
配对域采用两个域a和b,并产生表示实体对的域:一个来自域a,一个来自域b。配对由原始域的增量对的增量演变而成:一个增量来自域a,一个增量来自域b。配对实体的状态和增量均使用配对类型(_,_)表示。
[0425]
在haskell中,可以如下表示配对域:
[0426][0427]
产品域是对组件域的任意集合的配对域的概括。
[0428]
例如,域a、b、c和d的乘积表示实体元组:一个来自域a,一个来自域b,一个来自域c,一个来自域d。可通过将域函数(identity,apply,unapply,...)以与配对相同的方式分布在所有组件上,从配对域中概括出乘积域。
[0429]
举例来说,当以java或javascript等语言表示时,产品域的“元组”可表示为地图对象(字典)。
[0430]
例如,在协作演示应用的环境中,内容域可能被定义为以下各项的乘积:以“标题”为关键词的box《string》域;以及以“页面”为关键词的列表《页面》域(下面描述框和列表域)。
[0431]
任一和求和域
[0432]
任一域采用两个域a和b,并产生表示实体中的分离“任一”的域:一个来自域a,一
个来自域b。“任一”由来自原始域a的增量或来自原始域b的增量演变而成。使用任一类型表示任一实体的状态和增量。
[0433]
在haskell中,可以如下表示任一域:
[0434][0435]
求和域是任一域向任意数量的域的归纳。例如,域a、b、c和d的和表示实体的并集:一个来自域a,一个来自域b,一个来自域c,或者一个来自域d。求和域可以从任一域中归纳。
[0436]
举例来说,在协作设计应用的背景下,设计元素可能为少量元素“类型”中的一种,例如,“图像”元素、“形状”元素或“文本”元素。对于给定的imageelement、shapeelement和textelement域,这可以表示为被定义为以下域的求和域的元素域:标记为“图像”的imageelement域;以及标记为“形状”的shapeelement域;以及标记为“文本”的textelement域。
[0437]
当以这种方式建模时,元素域中的对象可以是那些特定元素类型中的一种,但不能从一种类型演变成另一种类型:在其使用期间保持其类型。
[0438]
框域
[0439]
框域通过在其状态上添加生命周期语义,将任何现有域转变为另一个域。框实体可以通过以下任一方式演变:来自其原始域的更新;或者被来自原始域的任何状态替换(重新实例化)。
[0440]
在haskell中,可以如下表示框域:
[0441][0442]
例如,在协作设计应用的环境中,页面可能具有“背景”特性,其模式由图像的产品域、裁剪框和透明度值描述。这种表示将允许同时并且独立地编辑该页面背景的不同方面,例如,裁剪框和透明度。将该模式表示为该产品域的框(而不是直接表示产品域)扩展了可能的编辑集,不仅包括对该背景的特定方面(例如,透明度的变化)的单独编辑(作为更新),还包括用具体指定的编辑自动替换整个背景的编辑(作为替换)。这体现了修改现有页面背景的用户操作与用全新的页面背景替换页面背景的用户操作之间的区别。
[0443]
mlist域
[0444]
mlist域是另一个高阶域。获取现有域,并从原始域中生成单调增长的实体列表。列表实体可以通过在任何位置插入来自原始域的新实体以及通过用来自原始域的增量更新其任何现有实体来演变。
[0445]
在haskell中,可以如下表示mlist域:
[0446][0447]
例如,在协作设计应用的背景下,页面可能具有设计元素列表。设计元素的集合可以由mlist《element》描述,用于描述单个元素的模式的某个元素域。
[0448]
然而,在实践中,不直接使用mlist域。相反,用于列表域的上下文中(如下所述)。
[0449]
idict域
[0450]
idict域获取域a和a的状态s,并产生新域(idictas)。域的每个状态都是a状态的字符串关键词字典,所有其他关键词都映射到s。
[0451]
例如,给定计数器域,(idict计数器0)域:
[0452]-具有表示字典的状态{

foo

:1,

bar

:2},其中:
[0453]
关键词“foo”映射到计数器状态1;
[0454]
关键词“bar”映射到计数器状态2;以及
[0455]
所有其他可能的关键词(例如,“baz”、“quux”等)映射到计数器状态0。
[0456]-具有表示字典增量的增量{

foo

: 1,

bar

:2},其中:
[0457]
关键词“foo”的状态将增加 1(根据计数器增量 1)
[0458]
关键词“bar”的状态将增加 2(根据计数器增量 2)
[0459]
所有其他关键词的状态(例如,“baz”、“quux”等)将增加 0(根据计数器恒等增量 0)
[0460]
idict恒等函数(恒等s)生成空字典。
[0461]
idict应用函数(applysd)产生具有来自s和d的关键词的新字典。每个新关键词k映射到由来自组件域的(applys[k]d[k])产生的状态,进行过滤,以省略其值等于字典默认状态的条目。
[0462]
idict取消应用函数(unapplysd)产生具有来自s和d的关键词的新字典。每个新关键词k映射到由来自组件域的(unapplys[k]d[k])产生的状态,进行过滤,以省略其值等于字典默认状态的条目。
[0463]
idict组成函数(composede)产生具有来自d和e的关键词的新字典。每个新关键词k映射到由来自组件域的(composed[k]e[k])产生的增量,进行过滤,以省略其值等于来自组件域的单元增量的条目。
[0464]
idict变换函数(变换sc)产生具有来自s和c的关键词的新字典(c’和s’)。将(c’[k],s’[k])设置为由来自组件域的(transform s[k]c[k])产生的增量,进行过滤,以省略其值等于来自组件域的单元增量的条目。
[0465]
为了进一步说明idict域,以下为(idict计数器0)域中的示例:
[0466]
identity{}=true
[0467]
apply{

foo

:1,

bar

:2}{

foo

: 1,

bar

:-2,

baz

: 1}={

foo

:2,

baz

:1}
[0468]
unapply{

foo

:2,

baz

:1}{

foo

: 1,

bar

:-2,

baz

: 1}={

foo

:1,

bar

:2}
[0469]
compose{

foo

: 1,

bar”: 2}{

foo

: 1,

bar

:-2,

baz

: 1}={

foo

: 2,

baz

: 1}
[0470]
transform({

foo

: 1,

bar

: 2},{

foo

: 1,

baz

: 3})=({

foo

: 1,

baz

: 3},{

foo

: 1,

bar

: 2})
[0471]
额外域
[0472]
上述定义的域足以包含操作变换算法的工作集。
[0473]
然而,可提供额外域。
[0474]
举例来说,以下额外域在功能上等同于上述域的组合,但具有提供操作简单性和效率的直接实现方式。
[0475]
选项域
[0476]
选项域获取一个域,并用可选性对其进行修饰。在功能上,选项域可以使用上述任一和单元域来表示。具体地,给定域a,a的可选域等价于无(单元)或a:
[0477]
选项a=任一单元a
[0478]
列表域
[0479]
上述mlist域的单调方面(其中,仅不断增长)可使其在某些应用中成为不方便的数据模型。列表域提供了也可以从中删除项目的列表。
[0480]
给定域a,a实体的一般列表被定义为a实体的可选空框的单调增长列表:
[0481]
list a=mlist(box(option a))
[0482]
可以理解,基本列表状态仍是单调的,但可通过过滤出其空项目将其视为常规列表:
[0483][0484]
从具有包含更新的增量的列表中“删除”状态为s的元素:
[0485]
update(box.replace(just s)nothing)
[0486]
该更新将列表演变为在被删除的实体的位置具有单元/无的列表。
[0487]
明文域
[0488]
明文域定义了可编辑文本的字符串,其中,可在字符串的任何位置插入或删除字符。在功能上,这相当于常量字符列表(如上所述):
[0489]
明文=列表(constchar)
[0490]
dict域
[0491]
以类似于列表域是mlist域的替代版本的方式,dict域是idict域的替代版本,其中,通过将条目包裹在框中使条目可选:
[0492]
dict a=idict(box(option a))
[0493]“插入”具有关键词k和值s的条目被理解为应用op:
[0494]
update k(box.replace nothing(just s))
[0495]
类似地,“删除”具有关键词k和值s的条目被理解为应用op:
[0496]
update k(box.replace(just s)nothing)
[0497]
mstream域
[0498]
mstream域类似于mlist域,但是具有不同的增量,这些增量通过克隆(和修改)列表条目来描述增长,而不是插入具有特定状态的新列表条目。
[0499]
mstream域采用域a,并产生来自a的单调增长的实体流的域,与来自a的表示无限前缀和无限后缀的状态配对,称为“背景状态”。例如,(mstreamcounter0)域是背景状态为0的计数器流。在该域中,状态:
[0500]
[4,2,8]
[0501]
对应于嵌入在0s的背景中的有限列表[4,2,8]:
[0502][0503]
mstream域的增量与mlist域的增量相同,除了(插入s)op被(复制d)op代替。
[0504]
data mstreamop s d=copy d|update d
[0505]
type mstreamstate s=[s]
[0506]
type mstreamdelta s d=[mstreamop s d]
[0507]
与mlist一样,(updated)op的含义是用增量d更新列表单元格。(copyd)op的含义是插入新单元格,作为前一单元格的副本,由增量d修改。
[0508]
attributestream域
[0509]
与列表和dict域一样,attributestream域是其他域的组合。
[0510]
具体而言,attributestream域表示mstream域的特定实例,作为“属性字典”流:
[0511]
attributestream=stream(idict(box(optional(const string)))unit)
[0512]
换言之,attributestream域中的状态是字典流(即列表),每个字典是字符串关键词到字符串值的映射。例如:
[0513]
[{

font-size



10



font-weight



bold

},
[0514]
{

font-size



10



colour



red

},
[0515]
{

colour



red

}]
[0516]
为便于描述,上述公开内容假设协作会话中的任何用户可对给定对象执行任何可用动作(即,读取/查看、写入/编辑、创建、删除)。然而,给定用户和/或给定实体可用的动作可以被权限修改。例如,可以创建允许给定用户查看但不编辑给定对象的权限。
[0517]
图中所示和上文所述的处理以特定顺序定义操作,以解释各种特征。在一些情况下,所描述和/或示出的操作能够以不同于所示出/描述的顺序来执行,一个或多个操作可以组合成单个操作,单个操作可以分成多个单独的操作,和/或由一个或多个所描述/示出的操作实现的功能可以由一个或多个替代操作来实现。此外,给定流程图操作的功能/处理可能由不同的系统或应用来执行。
[0518]
除非另有说明,术语“include”和“comprise”(及其变体,例如,“including”、“includes”、“comprising”、“comprises”、“comprised”等)是包含性的,不排除其他特征、部件、整体、步骤或元素。
[0519]
除非上下文要求,术语“第一”、“第二”等用于区分各种元素和特征,而没有顺序意义。例如,在不脱离各种描述的示例的范围的情况下,第一消息可以被称为第二消息,并且类似地,第二消息可以被
[0520]
应当理解,本说明书中公开和定义的实施例延伸至文本或附图中提及或明显可见的两个或多个单独特征的替代组合。所有这些不同的组合构成了本公开的替代实施例。
[0521]
本说明书参考各种具体细节描述了各种实施例,具体细节可能因实现方式而异。权利要求中没有明确陈述的限制、元素、性质、特征、优点或特性不应被认为是必需的或必要的特征。因此,说明书和附图被认为是说明性的,而不是限制性的。
再多了解一些

本文用于创业者技术爱好者查询,仅供学习研究,如用于商业用途,请联系技术所有人。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献