本申请要求2004年7月12日提交的,名为“SYSTEMS AND METHODS FORSYNCHRONIZING COMPUTER SYSTEMS THROUGH AN INTERMEDIARYFILE SYSTEM SHARE OR DEVICE(通过中介文件系统共享或设备同步计算机系统的系统和方法)”的美国申请第(尚未获得)号(代理案卷号MSFT-4484)的优先权,后者要求2004年8月30日提交的美国临时申请第60/567,141(代理案卷号MSFT-3939/306727.01)的优先权,并且是2004年6月30日提交的,名为“SYSTEMS AND METHODS FOR PROVIDING CONFLICT HANDLING FORPEER-TO-PEER SYNCHRONIZATION OF UNITS OF INFORMATIONMANAGEABLE BY A HARDWARE/SOFTWARE INTERFACE SYSTEM(为可由硬件/软件接口系统管理的信息单元的对等同步提供冲突处理的系统和方法)”的美国站立申请第10/883,621号(代理案卷号MSFT-2854)的部分延续,该申请是2003年10月24日提交的,名为“SYSTEMS AND METHODS FOR PROVIDINGRELATIONAL AND HIERARCHICAL SYNCHRONIZATION SERVICES FORUNITS OF INFORMATION MANAGEABLE BY A HARDWARE/SOFTWAREINTERFACE SYSTEM(用于为可由硬件/软件接口系统管理的信息单元提供关系和分层同步的系统和方法)”的美国专利申请第10/692,508号(代理案卷号MSFT-2845)的部分延续,后者是2003年8月21日提交的,名为“STORAGEPLATFORM FOR ORGANIZING,SEARCHING,AND SHARING DATA(用于组织、搜索和共享数据的存储平台”的美国专利申请10/646,646(代理案卷号MSFT-2734)的部分延续,本发明也要求2003年8月21日提交的国际申请第PCT/US03/27419(代理案卷号MSFT-2778)的优先权,这些申请的公开内容通过整体引用结合于此于此。
本申请的主题涉及以下共同转让的申请,其内容全部被结合到本申请中(并且为方便起见进行了部分概括):2003年8月21日提交的、标题为“SYSTEMS ANDMETHODS FOR REPRESENTING UNITS OF INFORMATION MANAGEABLE BYA HARDWARE/SOFTWARE INTERFACE SYSTEM BUT INDEPENDENT OFPHYSICAL REPRESENTATION(用于表示可以由硬件/软件接口系统管理但独立于物理表示的信息单元的系统和方法)”的美国专利申请地10/647,058号(代理卷号MSFT-1748);2003年8月21日提交的、标题为“SYSTEMS AND METHODSFOR SEPARATING UNITS OF INFORMATION MANAGEABLE BY AHARDWARE/SOFTWARE INTERFACE SYSTEM FROM THEIR PHYSICALORGANIZATION(用于将可由硬件/软件接口系统管理的信息单元与其物理组织分离的系统和方法)”的美国专利申请第10/646,941号(代理卷号MSFT-1749);2003年8月21日提交的、标题为“SYSTEMS AND METHODS FOR THEIMPLEMENTATION OF A BASE SCHEMA FOR ORGANIZING UNITS OFINFORMATION MANAGEABLE BY A HARDWARE/SOFTWARE INTERFACESYSTEM(用于实现用于组织可由硬件/软件接口系统管理的信息单元的基本模式的系统和方法)”的美国专利申请第10/646,940号(代理卷号MSFT-1750);2003年8月21日提交的、标题为“SYSTEMS AND METHOD FOR REPRESENTINGRELATIONSHIPS BETWEEN UNITS OF INFORMATION MANAGEABLE BY AHARDWARE/SOFTWARE INTERFACE SYSTEM(用于表示可由硬件/软件接口系统管理的信息单元之间的关系的系统和方法)”的美国专利申请第10/646,645号(代理卷号MSFT-1752);2003年8月21日提交的、标题为“SYSTEMS AND METHODSFOR INTERFACING APPLICATION PROGRAMS WITH AN ITEM-BASEDSTORAGE PLATFORM(用于将应用程序与基于项目的存储平台接口的系统和方法)”的美国专利申请第10/646,575号(代理卷号MSFT-2733);2003年8月21日提交的、标题为“STORAGE PLATFORM FOR ORGANIZING,SEARCHINGAND SHARING DATA(用于组织、搜索和共享数据的存储平台)”的美国专利申请第10/646,646号(代理卷号MSFT-2734);2003年8月21日提交的、标题为“SYSTEMS AND METHODS FOR DATA MODELING IN AN ITEM-BASEDSTORAGE PLATFORM(用于基于项目的存储平台中的数据建模的系统和方法)”的美国专利申请第10/646,580号(代理卷号MSFT-2735);2003年10月24日提交的、标题为“SYSTEMS AND METHODS FOR THE IMPLEMENTATION OF ADIGITAL IMAGES SCHEMA FOR ORGANIZING UNITS OF INFORMATIONMANAGEABLE BY A HARDWARE/SOFTWARE INTERFACE SYSTEM(用于实现用于组织可由硬件/软件接口系统管理的信息单元的数字图像模式的系统和方法)”的美国专利申请第10/692,779号(代理卷号MSFT-2829);2003年10月24日提交的、标题为“SYSTEMS AND METHODS FOR PROVIDINGSYNCHRONIZATION SERVICES FOR UNITS OF INFORMATIONMANAGEABLE BY A HARDWARE/SOFTWARE INTERFACE SYSTEM(用于向可由硬件/软件接口系统管理的信息单元提供同步服务的系统和方法)”的美国专利申请第10/629,515号(代理卷号MSFT-2844);2003年10月24日提交的、标题为“SYSTEMS AND METHODS FOR PROVIDING RELATIONAL ANDHIERARCHICAL SYNCHRONIZATION SERVICES FOR UNITS OFINFORMATION MANAGEABLE BY A HARDWARE/SOFTWARE INTERFACESYSTEM(为可由硬件/软件接口系统管理的信息单元提供关系和分层同步服务的系统和方法)”的美国专利申请第10/692,508号(代理卷号MSFT-2845);以及2003年10月24日提交的、标题为“SYSTEMS AND METHODS FOR EXTENSIONSAND INHERITANCE FOR UNITS OF INFORMATION MANAGEABLE BY AHARDWARE/SOFTWARE INTERFACE SYSTEM(用于可由硬件/软件接口系统管理的信息单元的扩展和继承的系统和方法)”的美国专利申请第10/693,574号(代理卷MSFT-2847)。
详细描述
I.引言
本发明的主题用细节来描述,以满足法定的要求。然而,该描述本身不试图限制本专利的范围。相反,本发明者设想,要求保护的主题也能以其它方式实施,以结合其它当前和未来的技术包括类似于本说明描述的不同的步骤或步骤的组合。此外,虽然术语“步骤”在这里可用于意味着所采用的方法的不同元素,然而该术语不能被解释为在这里揭示的各步骤之间隐含特定的次序,除非明确地描述了各个步骤的次序。
A.示例性计算环境
本发明的许多实施例可在计算机上执行。图1和下面讨论旨在提供其中实现本发明的合适计算环境的简要描述。虽然不是必需,本发明的诸方面能以诸如由如客户工作站或服务器的计算机上执行的程序模块的计算机可执行指令的一般上下文中描述。一般而言,程序模块包括例程、程序、对象、组件、数据结构等,它们执行特定任务或实现特定抽象数据类型。此外,本发明可用其它计算机系统配置实现,包括手持设备、多处理器系统、基于微处理器的系统或可编程消费者电子设备、网络PC、小型机、大型机等。本发明还能在分布式计算环境中实现,其中任务由通过通信网络链接的远程处理设备完成。在分布式计算环境中,程序模块能位于本地或远程存储器存储设备中。
如图1所示,示例性通用计算系统包括传统的个人计算机20等,它包括处理单元21、系统存储器22和将包括系统存储器的各种系统组件耦合到处理单元21的系统总线23。系统总线23可以是若干种总线结构的任一种,包括存储总线或存储控制器、外围总线、以及使用各种总线体系结构的任一种的局部总线。系统存储器包括只读存储器(ROM)24和随机访问存储器(RAM)25。基本输入/输出系统26(BIOS)包含如在启动时帮助在个人计算机20的诸元件之间传输信息的基本例程,存储在ROM 24中。个人计算机20还可包括读写硬盘(未示出)的硬盘驱动器27、读写可移动磁盘29的磁盘驱动器28、读写如CDROM或其它光介质的可移动光盘29的光盘驱动器30。硬盘驱动器27、磁盘驱动器28和光盘驱动器30分别通过硬盘驱动器接口32、磁盘驱动器接口33和光盘驱动器接口34连接系统总线23。驱动器及其相关的计算机可读介质为个人计算机20提供计算机可读指令、数据结构、程序模块和其它数据的非易失存储。虽然这里描述的示例性环境采用硬盘、可移动磁盘29和可移动光盘31,本专业技术人员理解,在示例性操作环境中也能使用可存储能由计算机访问的数据的其它类型计算机可读介质,如盒式磁带、闪存卡、数字视频盘、Bernoulli盒式磁带、随机存取存储器(RAM)、只读存储器(ROM)等。类似地,示例环境还可包括许多类型的监视设备,如热敏和安全或火警系统,及其它信息来源。
若干程序模块能存储在硬盘、磁盘29、光盘31、ROM 24或RAM 25中,包括操作系统35、一个或多个应用程序36、其它程序模块37和程序数据38。用户能通过如键盘40和定位设备42等输入设备将命令和信息输入到个人计算机20。其它输入设备(未示出)可包括麦克风、操纵杆、游戏垫、圆盘式卫星天线、扫描仪等。这里和其它输入设备常通过耦合到系统总线的串行接口46连接到处理单元21,但也可通过其它接口连接,如并行口、游戏口或通用串行总线(USB)。监视器47或其它类型的显示设备也通过如视频适配器48的接口连接到系统总线23。除监视器47以外,个人计算机通常包括如话筒和打印机等其它外围输出设备(未示出)。图1的示例系统还包括主适配器55、小型计算机系统接口(SCSI)总线56和连接到SCSI总线的外部存储设备62。
个人计算机20可使用到如远程计算机49的一个或多个远程计算机的逻辑连接在网络环境中操作。远程计算机49可以是另一台个人计算机、服务器、路由器、网络PC、对等设备或其它公共网络节点,并通常包括以上对个人计算机20描述的许多或所有元件,虽然在图1中只示出存储器存储设备50。图1中画出的逻辑连接包括局域网(LAN)51和广域网(WAN)52。那样的网络环境常见于办公室、企业范围计算机网络、内联网和因特网。
在LAN网络环境中使用时,个人计算机20通过网络接口或适配器53连接到LAN51。在WAN网络环境中使用时,个人计算机20通常包括调制解调器54或用于通过如因特网等广域网52建立通信的其它装置。内置或外接的调制解调器54通过串行端口接口46连接系统总线23。在网络环境中,相对个人计算机20画出的程序模块或其部分可存储在远程存储器存储设备中。可以理解,示出的网络连接是示例性的,可使用在计算机之间建立通信链路的其它装置。
如图2的框图所示,计算机系统200能被粗略地分成三个组件组:硬件组件202、硬件/软件接口系统组件204、以及应用程序组件206(在这里某些上下文中也称为“用户组件”或“软件组件”)。
回到图1,在计算机系统的各种实施例中,硬件组件202可包括中央处理单元(CPU)21、存储器(ROM 24和RAM 25)、基本输入/输出系统(BIOS)26、以及各种输入/输出(I/O)设备,如键盘40、鼠标42、监视器47、和/或打印机(未示出)等。硬件组件202包括计算机系统200的基本物理基础结构。
应用程序组件206包括各种软件程序,包括但不限于编译器、数据库系统、文件处理程序、商业程序、视频游戏等。应用程序提供计算机资源用于为各种用户(机器、其它计算机系统和/或最终用户)解决问题、提供解决方案和处理数据的手段。
硬件/软件接口系统组件204包括(在某些实施例中可以仅包括)操作系统,在大多数情况后者本身包括外壳和内核。“操作系统”(OS)是启动担当在应用程序和计算机硬件之间的中介的特殊程序。硬件/软件接口系统组件204还可包括虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物、Java虚拟机(JVM)或其功能等效物、或在计算机系统中的操作系统处或操作系统外的其它软件组件。硬件/软件接口系统的目的是提供用户能在其中执行应用程序的环境。任何硬件/软件接口系统的目标是使计算机系统便于使用,以及以有效的方式利用计算机硬件。
硬件/软件接口系统一般在启动时被加载到计算机系统,并随后管理在计算机系统中所有应用程序。应用程序通过经由应用程序接口(API)请求服务来与硬件/软件接口系统交互。某些应用程序使最终用户能通过如命令语言或图形用户界面(GUI)与硬件/软件接口系统交互。
硬件/软件接口系统传统上执行应用程序的各种服务。在多个程序同时运行的多任务硬件/软件接口系统中,硬件/软件接口系统确定哪些应用程序以什么次序运行,以及在切换到另一应用程序之前以供轮流对每个应用程允许多少时间。硬件/软件接口系统还管理在多个应用程序之间内部存储器的共享,并处理来往于如硬盘、打印机和拨号端口等附加的硬件设备的输入和输出。硬件/软件接口系统还将有关操作状态和可能发生的任何错误的消息发送到每个应用程序(在某些情况下到最终用户)。硬件/软件接口系统也能下传(offload)批处理作业(如打印)的管理,使得启动的应用程序能摆脱此工作并重新开始其它处理和/或操作。在能提供并行处理的计算机上,硬件/软件接口系统还管理划分程序,使得它同时在多个处理器上运行。
硬件/软件接口系统外壳(这里简称“外壳”)是到硬件/软件接口系统的交互式最终用户界面。(外壳也称为“命令解释器”,或在一个操作系统中称为“操作系统外壳”)。外壳是可直接由应用程序和/或最终用户访问的硬件/软件接口系统的外层。与外壳相反,内核是直接与硬件组件交互的硬件/软件接口系统的最内层。
虽然可构想本发明的许多实施例尤其适用于计算机化的系统,然而在本说明中不意味着将本发明限于那些实施例。相反,这里使用的术语“计算机系统”旨在包括能存储和处理信息和/或能使用存储的信息控制设备本身的行为或执行的任何和所有设备,而不管那些设备本质上是否为电子的、机械的、逻辑的、或虚拟的。
B.传统的基于文件的存储
在当今大多数计算机系统中,“文件”是可存储信息的单元,它可包括硬件/软件接口系统和应用程序、数据集等。在所有现代硬件/软件接口系统中(Windows,Unix,Linux,MacOS,虚拟机系统等),文件是能由硬件/软件接口系统处理的基本的分立(可存储和可检索)信息单元。文件组通常被组织成“文件夹”。在MicrosoftWindows、Macintosh OS和其它硬件/软件接口系统中,文件夹是能作为单个信息单元被检索、移动和处理的文件的集合。这些文件夹进而被组织成称为“目录”(在后面详细讨论)的基于树形的分层结构排列。在如Dos、z/OS和大多数基于Unix的操作系统的其它硬件/软件接口系统中,术语“目录”和/或“文件夹”是可交替使用的,早期的Apple计算机系统(如Apple IIe)使用术语“类别”来代替目录;然而在这里使用时所有这些术语被看成是同义语并可交替使用,并旨在还包括对分层信息存储结构及其文件夹和文件组件的所有其它等价术语的引用。
传统上,目录(又名文件夹的目录)是基于树形的分层结构,其中文件被组合成文件夹,文件夹进而按包括目录树的相对节点位置排列。例如,如图2A所示,基于DOS的文件系统的基本文件夹(或“根目录”)212可包括多个文件夹214,其每一个可以还包括另外的文件夹(如特定文件夹的“子文件夹”)216,而这些的每一个又包括另外的文件夹218,直到无限。这些文件夹的每一个可具有一个或多个文件220,虽然在硬件/软件接口系统级上,文件夹中的各个文件除了它们在树形分层结构中的位置外没有什么共同点。不奇怪,将文件组织到文件分层结构的方法间接地反映了用于存储这些文件的典型存储介质(如硬盘、软盘、CD-ROM等)的物理组织。
除上述以外,每个文件夹是对其子文件夹和其目录的容器一即,每个文件夹拥有其子文件夹和文件。例如,当文件夹被硬件/软件接口系统删除时,该文件夹的子文件夹和文件也被删除(在每个子文件夹的情况下还递归地包括它自己的子文件夹和文件)。同样,每个文件一般只由一个文件夹拥有,并且虽然文件能被拷贝且副本位于不同的文件夹,文件的副本本身是不同且独立单元,它与原始文件无直接连接(如对原始文件的改变在硬件/软件接口系统级上不反映到副本文件)。因此在这方面,文件和文件夹在本质上是“物理的”,因为文件夹类似于物理容器来处理,而文件作为这些容器中不同且独立的物理元素来处理。
II.用于组织、搜索和共享数据的WINFS存储平台
本发明结合通过引用结合于此的发明针对用于组织、搜索和共享数据的存储平台。本发明的存储平台扩展和拓宽了数据平台,超越上文讨论的文件系统及数据库系统,并被设计成存储所有类型的数据,包括称为项目的新格式的数据。
A.词汇表
在这里及在权利要求书中使用的术语有下列意义:
·“项目”是能存储硬件/软件接口系统可访问的信息的单元,不象简单文件,它是具有由硬件/软件接口系统外壳展现给最终用户的所有对象共同支持的基本属性集的对象。项目还具对所有项目类型共同支持的属性和关系,包括允许引入新属性和关系的特征(在下面详细讨论)。
·“操作系统”(OS)是扮作应用程序和计算机硬件之间的中介的特殊程序。在大多数情况下,操作系统包括外壳和内核。
·“硬件/软件接口系统”是软件、或硬件及软件的组合,它起着在计算机系统的底层硬件组件和在计算机系统上执行的应用程序之间的接口的作用。硬件/软件接口系统通常包括(在某些实施例中只包括)操作系统。硬件/软件接口系统还能包括虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物,Java虚拟机(JVM)或其功能等效物、或在计算机系统的操作系统处或除操作系统外的其它软件组件。硬件/软件接口系统的目的是提供用户能执行应用程序的环境。任何硬件/软件接口系统的目标是使计算机系统便于使用,并以有效方式利用计算机硬件。
B.存储平台综述
参考图3,存储平台300包括在数据库引擎314上实现的数据存储302。在一个实施例中,数据库引擎包括带有对象关系扩展的关系型数据库引擎。在一个实施例中,关系型数据库引擎314包括Microsoft SQL Server关系型数据库引擎。数据存储302实现支持数据的组织、搜索、共享、同步和安全的数据模型304。在如模式340等模式中描述特定的数据类型,并且存储平台300提供用于采用这些模式并用于扩展这些模式的工具346,这在后面详述。
在数据存储302中实现的改变跟踪机制306提供跟踪数据存储的改变的能力。数据存储302还提供安全能力308和升级/降级能力310,均在后文详述。数据存储302还提供一组应用程序接口312,以向利用该存储平台的其它存储平台组件和应用程序(如应用程序350a,350b和350c)展现数据存储302的能力。本发明的存储平台还包括应用程序接口(API)322,使如应用程序350a,350b,和350c等应用程序能访问存储平台的所有上述功能并能访问在模式中描述的数据。应用程序能结合如OLE OB API324和Microsoft Windows Win 32 API 326等其它API来使用存储平台API 322。
本发明的存储平台300能向应用程序提供各种服务,包括便于在用户或系统之间共享数据的同步服务330。例如,同步服务330允许与具有与数据存储302相同格式的其它数据存储340的互操作,并访问具有其它格式的数据存储342。存储平台300还提供允许数据存储302与如Windows NTFS文件系统318等现有文件系统的互操作的文件系统能力。在至少某些实施例中,存储平台320还能向应用程序提供另外的能力,以允许对数据起作用并允许与其它系统的交互。这些能力可体现在如Info Agent服务334和通知服务332等附加服务328的形式中,以及体现在其它实用程序336的形式中。
在至少某些实施例中,存储平台以计算机系统的硬件/软件接口系统来实施,或形成其完整的一部分。例如而非限制,本发明的存储平台能用操作系统、虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物、或Java虚拟机(JVM)或其功能等效物来实施,或形成其完整的一部分。通过其公用的存储基础和模式化的数据,本发明的存储平台使消费者、知识工人和企业作能够更有效地进行应用程序的开发。它提供了丰富和可扩展的编程表面区域,不仅可得到内含在其数据模型中的能力,还能包括和扩展现有文件系统和数据库访问方法。
在上述描述中及在各种附图中,本发明的存储平台300可称作“WinFs”。然而使用此名字指存储平台仅是为了描述方便,并不试图作出如此限制。
C.数据模型
本发明的存储平台300的数据存储302实现一种数据模型,它支持对驻留在数据存储中的数据的组织、搜索、共享、同步和安全。在本发明的数据模型中,“项目”是存储信息的基本单元。该数据模型提供一种机制,用于声明项目和项目的扩展、用于建立在项目之间的关系、以及用于将项目组织到项目文件夹和类别中,下面将更充分描述。
该数据模型依赖于两个原语机制:类型和关系。类型是提供支配类型的实例的形式的格式的结构。格式被表达成属性的有序组。属性是给定类型的值或一组值的名字。例如,USPostalAddress(美国邮政地址)类型具有属性Street(街道)、City(城市)、Zip(邮编)、State(州),其中Street、City和State是String类型,而Zip是Int32类型。Street可以是多值(即一组值),允许地址对Street属性具有一个以上值。系统定义能在其它类型构造中使用的某些原语类型,包括String、Binary、Boolean、Int16、Int32、Int64、Single、Double、Byte、DateTime、Decimal和GUID。可使用任何原语类型(带有下面注释的某些限制)或任何构造的类型来定义类型的属性。例如,Location(位置)类型可定义具有属性Coordinate(座标)和Address(地址),其中Address属性是上述类型USPostalAddress。属性也可以是必需的或可任选的。
关系可被声明并表示两个类型的实例集之间的映射。例如,可以有在Person(个人)类型和Location类型之间声明的关系,称为LivesAt(生活在),它确定什么人生活在什么位置。关系具有名和两个端点,即源端点和目标端点。关系也可具有属性的有序集。源端点及目标端点均具有名和类型。例如,LivesAt关系具有称为类型Person的Occupant(居民)的源和称为类型Location的Dwelling(住房)的目标,且此外具有属性StartDate(起始日期)和EndDate(终止日期),表示该居民生活在该住房的时间段。注意,随时间推移,个人能生活在多个住房,且住房可有多个居民,所以放置StartDate和EndDate信息的最可能的地方是在关系本身处。
关系定义了在由作为端点类型给出的类型约束的实例之间的映射。例如LivesAt关系不能是其中Automobile(汽车)是Occupant(居民)的关系,因为Automobile不是Person。
数据模型允许定义类型间的子类型-超类型关系。也称为基本类型关系的子类型-超类系型关系以如下方式定义,若类型A是类型B的基本类型,则必须是B的每个实例也是A的实例的情况。另一种表达的方法是符合B的每个实例必须符合A。例如,若A具有String类型的属性Name(名字),而B具有Int16类型的属性Age(年龄),则得出,B的任何实例必须兼有Name和Age。类型的分层结构可被设想成带有在根上的单个超类型的树。根的分枝提供第一级子类型,该级分枝提供第二级子类型,如此等等,直到本身不再具有任何子类型的叶端(leaf-most)子类型。树不限于统一深度,但不能包含任何回路。给定的类型可具有零个或许多子类型和零个或一个超类型。给定实例可最多符合一个类型以及该类型的超类型。换言之,对树中任一级处给定的实例,该实例最多可符合该级上的一个子类型。如果一类型的实例必须也是该类型的子类型的实例,则该类型可说成是抽象。
1.项目
项目是可存储的信息的单元,不象简单的文件,它是具有由存储平台向最终用户或应用程序展现的所有对象共同支持的基本属性集的对象。项目也具有所有项目类型共同支持的属性和关系,包括如下所述允许引入新的属性和关系的特征。
项目是公用操作的对象,如拷贝、删除、移动、打开、打印、备份、恢复、复制等。项目是能被存储和检索的单元,且由存储平台处理的可存储信息的所有形式作为项目、项目的属性、或项目之间的关系存在,其每个在下面更详细讨论。
项目旨在表示显示的且容易理解的数据单元,如联系人(Contacts)、人(People)、服务(Services)、位置(Locations)、(各种类型的)文档(Documents)等。图5A是示出项目的结构的框图。该项目的不合格的名是“Location”。该项目的合格名是“Core.Location”,它表明,此项目结构被定义成Core(核心)模式中的特定类型的项目(Core模式在下面详细讨论)。
Location项目具有多个属性,包括EAddress(电子邮件地址)、MetropolitanRegion(都市地区)、Neighborhood(街坊)、和PostalAddress(邮政地址)。每个项目的特定类型属性紧跟属性名地表示,并用冒号(“:”)与属性名分开。在类型名的右边,对该属性类型允许的值的数量在方括号(“[]”)之间表示,其中冒号(“:”)右边的星号(“*”)表示未规定的和/或无限制的数量(“许多”)。冒号右边的“1”表明最多一个值。冒号左边的零(“0”)表明该属性是可任选的(可以完全没有值)。冒号左边的“1”表明必须至少有一个值(该属性是必须的)。Neighborhood和MetropolitanRegin均是“nvarchar”类型(或等效类型),它是预定义的数据类型或“简单类型”(这里用缺少大写来表示)。然而EAddress和PostalAddress分别是类型EAddress和PostalAddress的已定义类型或“复杂类型”(这里用大写标记)的属性。复杂类型是从一个或多个简单数据类型和/或从其它复杂类型导出的类型。一个项目的属性的复杂类型还构成”嵌套元素“,因为复杂类型的细节嵌套入直接项目中以定义其属性,而属于这些复杂类型的信息用具有这些属性的项目来维持(在该项目的边界内,如后面讨论)。类型的这些概念是众知的,且容易被本专业技术人员理解。
图5B是示出复杂属性类型PostalAddress和EAddress的框图。PostalAddress属性类型定义,属性类型PostalAddress的项目可期望有零个或一个City(城市)值、零个或一个Country Code(国家代码)值、零个或一个MailStop(国家代码)值、和任何数量(零到许多)PostalAddress类型等等。以此方式,定义了一项目中的特定属性的数据的形状。EAddress属性类型如所示类似地定义。虽然这里在本申请中可任选地使用,表示在Location项目中复杂类型的另一方法是用其中列出的每个复杂类型的各个属性得出该项目。图5C是示出Location项目的框图,在其中进一步描述其复杂类型。然而应该理解,在此图5C中Location项目的另一种表示恰是对图5A中示出的同一个项目。本发明的存储平台还允许子分类(subtyping),从而一个属性类能是另一个的子类型(其中一个属性类继承另一个父属性类型的属性)。
类似于但不同于属性及它们的属性类型,项目继承性地表示其自己的Item(项目)类型,它也是子分类的主题。换言之,本发明的若干实施例中的存储平台允许一个项目是另一个项目的子类型(从而一个项目继承另一个父项目的属性)。此外,对本发明的各种实施例,每个项目是“Item”项目类型的子类型,后者是在基础模式中找到的第一和基本的项目类型(基础模式也在后面详细讨论)。图6A示出一项目(在此实例中为Location项目)为在基础模式中找到的Item项目类型的子类型。在此图中,箭头表示Location项目(如所有其它项目)是Item项目类型的子类型。作为从中导出所有其它项目的基本项目的Item项目类型具有若干如ItemId的重要属性和各种时间标记,从而定义了操作系统中所有项目的标准属性。在本图中,Item项目类型的这些属性被Location所继承,并从而成为Location的属性。
表示从Item项目类型继承的Location项目中属性的另一种方法是用来自其中列出的父项目的每个属性类型的各个属性得出Location。图6B是示出Location项目的框图,其中除了其直接属性外描述其继承的类型。应注意和理解,此项目是图5A中示出的同一项目,虽然在本图中,Location用所有其属性示出,包括直接属性(在本图及图5A中示出)和继承属性(在本图中示出但未在图5A中示出)(而在图5A中,通过用箭头示出Location项目是Item项目类型的子类型来引用这些属性)。
项目是独立的对象,因而若删除一项目,也删除项目的所有直接和继承的属性。类似地,当检索一项目时,检索的是该项目及其所有直接和继承的属性(包括属于其复杂属性类型的信息)。本发明的某些实施例可使人们能在检索特定项目时请求属性的子集;然而对许多那样的实施例默认的是在检索时向项目提供所有其直接和继承的属性。此外,项目的属性也能通过添加新的属性到该项目的类型的现有属性而加以扩展。这些“扩展”其后是该项目的真实属性,且该项目类型的子类型可自动地包括扩展属性。
项目的“边界”由其属性(包括复杂属性类型、扩展等)来表示。项目的边界也表示在项目上执行的操作的限制,包括拷贝、删除、移动、创建等。例如在本发明的若干实施例中,当拷贝一项目时,在该项目边界之内的所有内容也被拷贝。对每个项目,边界包括下列:
·项目的项目类型,且若该项目是另一项目的子类型(如在所有项目从基础模式的单个项目和项目类型导出的本发明的若干实施例的情况下),是任何适用的子类型信息(即属于父项目类型的信息)。若要拷贝的原始项目是另一项目的子类型,该副本也能是该相同项目的子类型。
·项目的复杂类型属性和扩展(如果有的话)。若原始项目具有复杂类型(原来的或扩展的)的属性,副本也能具有相同的复杂类型。
·在“所有权关系”上的项目的记录,即,本项目(“拥有项目”)拥有什么其它项目(“目录项目”)的项目拥有列表。这特别关系到下面充分讨论的项目文件夹和下面说到的所有项目必须至少属于一个项目文件夹的规则。此外,关于嵌入项目(下列更充分讨论),一个嵌入项目被认为是其中嵌入如拷贝、删除等操作的项目的一部分。
2.项目标识
在全局项目空间中用ItemID唯一地标识项目。Base.Item类型定义了存储该项目身份的类型GUID的字段ItemID。一项目必须在数据存储中准确只有一个身份。
项目引用是包含定位和标识项目的信息的数据结构。在该数据模型中,定义名为ItemReference的抽象类型,从中导出所有项目引用类型。ItemReference(项目引用)类型定义了名为Resolve(解析)的虚拟方法。Resolve方法解析ItemReference并返回一项目。此方法被ItemReference的具体子类型所覆盖,后者实现给定一引用时检索项目的功能。调用Resolve方法作为存储平台API 322的一部分。
ItemIDReference(项目ID引用)是ItemReference的子类型。它定义了Locator(定位器)和ItemID字段。Locator字段命名(即标识)项目的域。它由能将Locator的值解析到项目域的定位器解析方法来处理。ItemID字段是ItemID类型。
ItemPathReference(项目路径引用)是定义Locator和Path(路径)字段的ItemReference的特殊化。Locator字段标识一项目域。它由能将Locator的值解析到项目域的定位器解析方法来处理。Path字段包含以由Locator提供的项目域为根的存储平台名字空间中的(相对)路径。
不能在集合运算中使用此类引用。引用一般必须通过路径解析过程来解析。存储平台API 322的Resolve方法提供此功能。
上面讨论的引用形式通过图11示出的引用类型分层结构表示。从这些类型继承的另外引用类型能在模式中定义。它们能在关系声明中用作目标字段的类型。
3.项目文件夹和类别
如下面将更充分讨论的,项目组能组织成称为项目文件夹(不要与文件的文件夹混淆)的特殊项目。然而不象大多数文件系统,一个项目可属于多个项目文件夹,使得当一个项目在一个项目文件夹中被访问和修订时,此修订的项目随后能直接从另一项目文件夹访问。实质上,虽然对一个项目的访问可从不同的项目文件夹发生,事实上真正访问的是同一个项目。然而,一个项目文件夹不必拥有其所有成员项目,或简单地结合其它文件夹共同拥有项目,使得一个项目文件夹的删除不必要导致项目的删除。然而在本发明的若干实施例中,一个项目必须至少属于一个项目文件夹,使得如果特定项目的唯一文件夹被删除,则对某些实施例,该项目被自动被删除,或在另外实施例中,该项目自动地成为默认项目文件夹的成员(“TrashCan(垃圾箱)”文件夹在概念上类似于在各种基于文件和文件夹的系统中使用的类似名字文件夹。)
如下面更充分讨论的,项目也可属于基于共同描述的特征的类别,特征如:(a)项目类型(或类型),(b)特定的直接或继承的属性(或属性),或(c)对应于项目属性的特定值(或值)。例如,包括个人联系人信息的特定属性的项目可自动属于联系人(Contact)类别,具有联系人信息属性的任何项目看来也自动属于此类别。同样,具有“New York City(纽约市)”值的位置属性的任何项目可自动属于纽约市类别。
类别在概念上不同于项目文件夹之处在于,项目文件夹可包括互相无关的项目(即无共同的描述的特征),而在类别中的每个项目具有对该类别描述的共同类型、属性或值(“共同性”),正是这个共同性形成对它与该类别中其它项目或那些项目之间的关系的基础。此外,虽然在特定文件夹中的项目的成员资格基于该项目的任何特定方面不是强制的,然而对某些实施例,具有在分类上与一类别相关的共同性的所有项目在硬件/软件接口系统级上可自动地成为该类别的成员。概念上,类别也能看作虚拟项目文件夹,其成员资格基于特定查询(如在数据库的上下文中)的结果,而满足此查询的条件(由类别的共同性确定)的项目应构成该类别的成员资格。
图4示出在项目、项目文件夹和类别之间的结构关系。多个项目402、404、406、408、410、412、414、418和420是各个项目文件夹422、424、426、428和430的成员。某些项目属于一个以上项目文件夹,如项目402属于项目文件夹422和424。某些项目,如项目402、404、406、408、410和412也是一个或多个类别432、434和436的成员,而其它项目,如项目44,416,418和420可以不属于任何类别(虽然这大部分不象在某些实施例中,其中具有任何属性自动暗示类别中的成员资格,因此在那样实施例中为了不是任何类别的成员,项目应完全地无特征)。与文件夹的分层结构相反,类别和项目文件夹均有更像如所示的有向图的结构。在任何情况下,项目、项目文件夹和类别都是项目(尽管是不同的项目类型)。
与文件、文件夹和目录相反,本发明的项目、项目文件夹和类别的特征在本质上不是“物理的”,因为它们不具有物理容器的概念上的等价性,因而项目可存在于一个以上那样的位置。项目存在于一个以上项目文件位置以及被组织成类别的能力提供了在硬件/软件接口级上增强和丰富程度的数据处理及存储结构能力,超越了在本领域中当前可得到的能力。
4.模式
a)基础模式
为了提供创建和使用项目的通用基础,本发明的存储平台的各实施例包括建立用于创建和组织项目及属性的概念性框架的基础(Base)模式。基础模式定义了某些特定类型的项目和属性,以及从中进一步导出子类型的这些特定基本类型的特征。使用此基础模式使程序员能在概念上将项目(及其各自的类型)与属性(及其各自的类型)加以区别。此外,基础模式列出所有项目可拥有的基本属性集,因为所有项目(及其对应的项目类型)是从基础模式的此基本项目(及其对应的项目类型)导出。
如图7所示,对于本发明的若干实施例,基础模式定义三个顶层类型:Item(项目)、Extension(扩展)和PropertyBase(属性基础)。如图所示,通过此基本“Item”项目类型的属性定义了项目类型。相反,顶层属性类型“PropertyBase”没有预定义的属性,仅是一个锚位(anchor),从中导出所有其它属性,并通过它所有导出的属性类型互相联系(共同从单个属性类型导出)。Extension类型属性定义该扩展扩展了哪个项目,并定义将一个扩展与另一个项目相区别的标识,因为一个项目可具有多个扩展。
ItemFolder(项目文件夹)是Item项目类型的子类型,除了从Item继承的属性外,它表征用于建立到其成员(如果有的话)的关系,尽管Identitykey(身份关键字)和Property(属性)均是PropertyBase的子类型。CategoryRef(目录引用)进而是IdentityKey的子类型。
b)核心模式
本发明的存储平台的各种实施例还包括为顶层项目类型结构提供概念框架的核心(Core)模式。图8A是示出核心模式中的项目的框图,而图8B是示出核心模式中属性类型的框图。在带不同扩展名(*.com、*.exe、*.bat、*.sys等)的文件和在基于文件和文件夹系统中其它准则之间作出的区分是类似于核心模式的功能。在基于项目的硬件/软件接口系统中,核心模式定义了一组核心项目类型,它们直接(按项目类型)或间接地(按项目子类型)将所有项目特征化成基于项目的硬件/软件接口系统理解并能以预定或可预计的方式直接处理的一个或多个核心模式项目类型。预定的项目类型反映了在基于项目的硬件/软件接口系统中最常用的项目,且因此通过理解这些包括核心模式的预定项目类型的基于项目的硬件/软件接口系统获取有效性级别。
在某些实施例中,核心模式是不可扩展的,即,没有另外的类型可直接从基础模式中的项目类型子分类,除非作为核心模式的一部分的特定的预定导出的项目类型。通过禁止对核心模式的扩展(即,通过禁止向核心模式添加新的项目),存储平台托管核心模式项目类型的使用,因为每个后续的项目类型必须是核心模式项目类型的子类型。此结构允许在保持具有一组预定的核心项目类型的益处的同时在定义另外项目类型时有合理程度的灵活性。
参考图8A,对本发明的各种实施例,由核心模式支持的特定项目类型可包括下列的一个或多个:
·Category(类别):此项目类型(及从中导出的子类型)的项目代表在基于项目的硬件/软件接口系统中的有效类别。
·Commodity(物品):作为值的可标识事物的项目。
·Device(设备):具有支持信息处理能力的逻辑结构的项目。
·Document(文档):具有不能由基于项目的硬件/软件接口系统解释而相反由对应于文档类型的应用程序解释的内容的项目。
·Event(事件):记录环境中某些发生事件的项目。
·Location(位置):代表物理位置(如地理位置)的项目。
·Message(消息):在两个或更多主体(下面定义)之间通信的项目。
·Principal(主体):具有除ItemId之外的至少一个肯定可验证身份(如,个人、组织、组、家庭、作者、服务等的标识)的项目。
·Statement(语句):具有关于环境的特定信息的项目,包括但不限于:政策、预订、凭证等。
类似地参考图8B,由核心模式支持的特定属性类型可包括下列的一个或多个:
·Certificate(证书)(从基础模式中的基本PropertyBase类型导出)
·PrincipalIdentityKey(主体身份关键字)(从基础模式中的IdentityKey类型导出)
·PostalAddress(邮政地址)(从基础模式中Property类型导出)
·RichText(多信息文本)(从基础模式中Property类型导出)
·EAddress(电子邮件地质)(从基础模式中Property类型导出)
·IdentitySecnrityPackage(身份安全包)(从基础模式中Relationship类型导出)
·RoleOccupancy(居民角色)(从基础模式中Relationship类型导出)
·BasicPresence(基础存在)(从基础模式中Relationship类型导出)
这些项目和属性按在图8A和图8B中列出的各自属性进一步描述。
5.关系
关系是二元关系,其中一个项目被指定为源,另一个被指定为目标。源项目和目标项目通过关系相联系。源项目一般控制关系的生命周期。即,当源项目被删除,项目之间的关系也被删除。
关系被分类成:包含(Containment)和引用(Reference)关系。包含关系控制目标项目的生命周期,而引用关系不提供任何生命周期管理语义。图12示出关系分类的方式。
包含关系又被分类成持有(Holding)和嵌入(Embedding)关系。当对一个项目的所有持有关系被移除,该项目被删除。持有关系通过引用计数机制控制目标。嵌入关系能够对复合项目建模,并能被看作排他的持有关系。一个项目能是一个或多个持有关系的目标;但一个项目只能是一个嵌入关系的目标。作为嵌入关系的目标的项目不能是任一其它持有或嵌入关系的目标。
引用关系不控制目标项目的生命周期。它们可以是摇摆不定的-目标项目可以不存在。引用关系能用于在全局项目名字空间的任何处(即,包括远程数据存储)建模对项目的引用。
获得一项目不自动取得某关系,应用程序必须明确地请求项目的关系。此外,修改关系不修改源或目标项目;类似地,添加关系不影响源/目标项目。
a)关系声明
显式的关系类型用下列元素定义;
·在Name(名字)属性中指定关系名
·下列之一的关系类型:持有、嵌入、引用。这是在Type(类型)属性中指定的。
·源和目标端点。每个端点指定所引用项目的名和类型。
·源端点字段一般是ItemID(项目ID)类型(未声明),而必须引用在与关系实例同一数据存储中的项目。
·对持有和嵌入关系,目标端点字段必须是ItemIDReference(项目ID引用)类型,且它必须引用在与关系实例相同存储中的项目。对引用关系,目标端点能是任何ItemReference(项目引用)类型,并能引用在其它存储平台数据存储中的项目。
·能可任选地声明标量或PropertyBase(属性基础)类型的一个或多个字段。这些字段能包含与该关系相关联的数据。
·关系实例被存储在全局关系表中。
·每个关系实例唯一地由组合(源ItemID、关系ID)标识。对所有源自给定项目的关系,在给定的源ItemID中关系ID是唯一的,而不管它们的类型。
源项目是关系的拥有者。而被指定为拥有者的项目控制关系的生命周期,关系本身和与它们相关的项目分开。存储平台API 322提供用于展现与项目相关联的关系的机制。
这里是一个关系声明的例子。
<Relationship Name=″Employment″BaseType=″Reference″>
<Source Name=″Employee″ItemType=″Contact.Person″/>
<Target Name=″Employer″ItemType=″Contact.Organization″
ReferenceType=″ItemIDReference″/>
<Property Name=″StartDate″Type=″the storage
platformTypes.DateTime″/>
<Property Name=″EndDate″Type=″the storage
platformTypes.DateTime″/>
<Property Name=″Office″Type=″the storage
platformTypes.DateTime″/>
</Relationship>
这是引用关系的例子。若由源引用所引用的个人项目不存在,则不能创建该关系。而且若该个人项目被删除,在个人和组织之间的关系实例也被删除。然而若组织项目被删除,关系不被删除,而它是摇摆不定的。
b)持有关系
持有关系用于基于目标项目的生命周期管理来对引用计数建模。
一个项目可以是用于对项目的零个或多个关系的源端点。不是嵌入项目的项目可以是在一个或多个持有关系中的目标项目。
目标端点引用类型必须是ItemIDReference,且它必须引用在与关系实例相同的存储中的项目。
持有关系实施目标端点的生命周期管理。持有关系实例和作为目标的项目的创建是原子操作。可以创建将同一项目作为目标的另外的持有关系实例。当具有给定项目作为目标端点的最后一个持有关系实例被删除时,该目标项目也被删除。
在关系声明中指定的端点项目的类型一般在创建该关系的实例时强制。在关系建立之后端点项目的类型不能改变。
持有关系在形成项目的名字空间中起着关键作用。它们包含“Name(名字)”属性,它定义目标项目相对于源项目的名字。对所有源自给定项目的持有关系,相对名字是唯一的。从根项目开始到给定项目的相对名字的有序类表形成该项目的全名。
持有关系形成一有向非循环图(DAG)。在创建持有关系时,系统确保不产生回路,从而确保项目的名字空间形成DAG。
虽然持有关系控制目标项目的生命周期,它不控制目标端点项目的操作的一致性。目标项目在操作上独立于通过持有关系拥有它的项目。在作为持有关系的源的项目上的拷贝、移动、备份和其它操作不影响作为同一关系的目标的项目-例如,备份文件夹项目不自动地备份该文件夹中所有项目(FolderMember(文件夹成员)关系中的目标)。
下面是持有关系的例子:
<Relationship Name=″FolderMembers″BaseType=″Holding”>
<Source Name=″Folder″ItemType=″Base.Folder″/>
<Target Name=″Item″ItemType=″Base.Item″
ReferenceType=″ItemIDReference″/>
</Relationship>
FolderMember关系使文件夹的概念成为项目的类属集合。
c)嵌入关系
嵌入关系将目标项目的生命周期的排外控制的概念模型化。它们允许合成项目的概念。
嵌入关系实例和作为目标的项目的创建是原子操作。一个项目能是零个或多个嵌入关系的源。然而一个项目能是一个且仅是一个嵌入关系的目标。作为嵌入关系的目标的项目不能是持有关系的目标。
目标端点引用类型必须是ItemIDReference,且它必须引用在与关系实例相同数据存储中的项目。
在关系声明中指定的端点项目的类型一般在创建该关系的实例时强制。在关系建立之后端点的类型不能改变。
嵌入关系控制该目标端点的操作一致性。例如,串行化项目的操作可包括串行化所有源自该项目及所有其目标的所有嵌入关系;拷贝一项目也拷贝所有它的嵌入项目。
下面是示例声明:
<Relationship Name=″ArchiveMembers″BaseType=″Embedding”>
<Source Name=″Archive″ItemType=″Zip.Archive″/>
<Target Name=″Member″ItemType=″Base.Item″
ReferenceType=″ItemIDReference″/>
<Property Name=″ZipSize″Type=″the storage
platformTypes.bigint″/>
<Property Name=″SizeReduction″Type=″the storage
platformTypes.float″/>
</Relationship>
d)引用关系
引用关系不控制它引用的项目的生命周期。尤其是,引用关系不保证目标的存在,也不保证目标的类型如关系声明中指定的那样。这意味着引用关系能是摇摆不定的。而且引用关系能引用在其它数据存储中的项目。引用关系能看作类似于网页上的链接的概念。
下面是引用关系说明的例子:
<Relationship Name=″DocumentAuthor″BaseType=″Reference″>
<Sourc ItemType=″Document″
ItemType=″Base.Document″/>
<Target ItemType=″Author″ItemType=″Base.Author″
ReferenceType=″ItemIDReference″/>
<Property Type=″Role″Type=″Core.CategoryRef″/>
<Property Type=″DisplayName″Type=″the storage
platformTypes.nvarchar(256)″/>
</Relationship>
在目标的端点允许任何引用类型。参与引用关系的项目可以是任何项目类型。
引用关系用于对项目之间的大多数非生命周期管理关系建模。因为不强制目标的存在,引用关系便于对松散耦合的关系建模。引用关系能用于在其它存储,包括在其它计算机上的存储中的目标项目。
e)规则和约束
下列附加规则和约束应用于关系:
·一个项目必须是(仅一个嵌入关系)或(一个或多个持有关系)的目标。一个例外是根项目。一个项目能是零个或多个引用关系的目标。
·作为嵌入关系目标的项目不能是持有关系的源。它能是引用关系的源。
·一个项目若是从文件升级,则不能是持有关系的源。它能是嵌入关系和引用关系的源。
·一个从文件升级的项目不能是嵌入关系的目标。
f)关系的排序
在一至少个实施例中,本发明的存储平台支持关系的排序。通过在基本关系定义中名为“Order(排序)”的属性完成排序。在Order字段中无唯一性约束。不保证带有同一“Order”属性值的关系的次序,然而保证,它们能排序在带较低“Order”值的关系之后并在带较高“Order”字段值的关系之前。
应用程序通过在在组合(SourceItem ID,RelationshipID,Order)上排序得到默认次序的关系。源自给定项目的所有关系实例被排序成单个集合,而不管在集合中关系的类型。然而这保证,给定类型(如,FolderMembers(文件夹成员))的所有关系是给定项目的关系集合的已排序子集。
用于处理关系的数据存储API 312实现一组支持关系的排序的操作。引入下列术语帮助解释那些操作:
·RelFirst是有序集合中带次序值OrdFirst的第一个关系;
·RelLast是有序集合带次序值OrdLast的最后一个关系;
·RelX是集合中带次序值OrdX的给定关系;
·RelPrev是集合中最接近于RelX的带小于OrdX的次序值OrdPrev的关系;以及
·RelNext是集合中最接近于RelX的带大于OrdX的次序值OrdNext的关系。
操作包括但不限于:
·InsertBeforeFirst(SourceItemID,Relationship)插入关系作为集合中的第一个关系。新关系的“Order”属性的值可小于OrdFirst。
·InsertAfterLast(SourceItemID,Relationship)插入关系作为集合中的最后一个关系。新关系的“Order”属性的值可大于OrdLast。
·InsertAt(SourceItemID,ord,Relationship)插入带有对“Order”属性指定的值的关系。
·InsertBefore(SourceItemID,ord,Relationship)在带有给定次序值的关系之前插入该关系。新的关系可被分配“Order”值,它在OrdPrev和ord之间,但不包括这两个值。
·InsertAfter(SourceItemID,ord,Relationship)在带有给定次序值的关系之后插入该关系。新的关系可被分配“Order”值,它在ord和OrdNext之间,但不包括这两个值。
·MoveBefore(SourceItemID,ord,Relationship)将带给定关系ID的关系移动到带指定“Order”值的关系之前。关系可被分配新的“Order”值,它在OrdPrev和ord之间,但不包括这两个值。
·MoveAfter(SourceItemID,ord,Relationship)将带给定关系ID的关系移动到带指定“Order”值的关系之后。该关系可被分配新的次序值,它在ord和OrdNext之间,但不包括这两个值。
如前提到,每个项目必须是项目文件夹的成员。按照关系,每个项目必须与一项目文件夹有一关系。在本发明的若干实施例中,某些关系由在诸项目之间存在的关系表示。
如对本发明的各实施例的实现,关系提供一有向的二元关系,它由一个项目(源)延伸到另一项目(目标)。关系由源项目(延伸它的项目)拥有,因此若源被移除则关系被移除(如在源项目被删除时关系被删除)。此外在某些情况下,关系可共享(共同拥有的)目标项目的拥有权,且那样的拥有权仅可反映在关系的IsOwned(被拥有)属性(或其等效属性)中(如图7对关系属性类型所示)。在这些实施例中,创建一新的IsOwned关系自动递增该目标上的引用计数,而删除那样的关系可递减该目标项目上的引用计数。对这些特定实施例,若项目具有大于0的引用计数,则继续存在,若项目计数达到0则自动删除。再一次,项目文件夹是具有(或能具有)与其它项目的一组关系的项目,这些其它项目包括项目文件夹的成员资格。关系的其它实际实现是可能的,并由本发明构想来实现这里描述的功能。
不管实际的实现如何,关系是从一个对象到另一对象的可选择的连接。一个项目属于一个以上项目文件夹以及一个或多个类别,而不论这些项目、文件夹和类别是公有的或私有的能力是由给予基于项目的结构中的存在(或缺乏)的意义所确定的。这些逻辑关系是分配给一组关系的意义,而不论其专门用来实现这里所述功能的物理实现如何。逻辑关系是在项目及其文件夹或类别之间建立的(或相反),因为本质上项目文件夹和类别的每一个都是特定类型的项目。因此,能象其它项目一样地对项目文件夹和类别起作用(拷贝、添加到电子邮件消息中、嵌入文档等等,而无限制),而项目文件夹和类别能象其它项目一样使用相同的机制串行化和解串行化(导入和导出)。(例如在XML中,所有项目可具有串行化的格式,且此格同等地应用于项目文件夹、类别和项目)。
代表项目及其项目文件夹之间的关系的上述关系在逻辑上能从项目延伸到项目文件夹、从项目文件夹延伸到项目、或两者。逻辑上从一项目延伸到项目文件夹的关系表明该项目文件夹对于该项目是公有的,并与该项目共享其成员资格信息;相反,缺乏从项目到项目文件夹的逻辑关系表明该项目文件夹对该项目是私有的,且不与该项目共享其成员资格信息。类似地,逻辑上从项目文件夹延伸到项目的关系表明该项目是公有的,并可与该项目文件夹共享,而缺乏从项目文件夹延伸到项目的逻辑关系表明该项目是私有的且不能共享。因此,当向其它系统导出项目文件夹时,它是“公有”的项目,它在新的环境中共享,且当项目搜索其项目文件夹寻找其它可共享的项目时,它是“公有”的项目文件夹,它向该项目提供关于属于它的可共享项目的信息。
图9是示出项目文件夹(它本身也是项目)、其成员项目、和项目文件夹及其成员项目之间互联关系的框图。项目文件夹900具有多个项目902、904和906作为其成员。项目文件夹900具有从它本身到项目902的关系912,它表明项目902是公有的,且能与项目文件夹900、其成员904和906、和任何可访问项目文件夹900的任何其它项目文件夹、类别、或项目(未示出)共享。然而从项目902到项目文件夹项目900没有关系,这表明项目文件夹900对项目902是私有的,且不与项目902共享其成员资格信息。另一方面,项目904确实具有从它本身到项目文件夹900的关系924,这表明项目文件夹900是公有的,且与项目904共享其成员资格信息。然而没有从项目文件夹900到项目904的关系,这表明项目904是私有的,且不与项目文件夹900、其另外的成员902、906、及可访问项目文件夹900的任何其它项目文件夹、类别、或项目(未示出)共享。与其到项目902和904的关系(或没有这些关系)相反,项目文件夹900具有从其本身到项目906的关系916,且项目906具有回到项目文件夹900的关系926,一起表明项目906是公有的,且能对文件夹900、其成员902和904、和可访问项目文件夹900的任何其它项目文件夹、类别、或项目(未示出)共享,且项目文件夹900是公有的,并与项目906共享其成员资格信息。
如前讨论,在项目文件夹中的项目不需要共享共同性,因为项目文件夹未被“描述”。另一方面,类别由对所有其成员项目共同的共同性描述。因此,类别的成员资格固有地限于具有所描述的共同性的项目,且在某些实施例中,满足类别的描述的所有项目自动地成为该类别的成员。因此,尽管项目文件夹允许由其成员资格来表示不重要的类型结构,类别基于定义的共同性来允许成员资格。
当然,类别描述本质上是逻辑的,因而类别可通过类型、属性和/或值的任何逻辑表示来描述。例如,对一类别的逻辑表示可以是其成员资格,以包括具有两个属性之一或两者的项目。若这些对类别描述的属性是“A”和“B”,则该类别的成员资格可包括具有属性A而没有B的项目、具有属性B而没有A的项目、及兼有属性A和B的项目。通过逻辑运算符“OR(或)”来描述属性的逻辑表示,其中由类别描述成员组是具有属性A OR B的项目。如本领域的技术人员所理解的,也能使用类似的逻辑运算符(包括但不限于单独的“AND(和)”“XOR(异或)”和“NOT(非)”或其组合)来描述类别。
尽管在项目文件夹(未描述)和类别(已描述)之间有区别,但在本发明的许多实施例中,原则上到项目的类别关系及到类别的项目关系以上面对项目文件夹和项目的同样方法揭示。
图10是示出一类别(其本身也是项目)、其成员项目、类别及其成员项目之间的互联关系的框图。类别1000具有多个项目1002、1004和1006作为成员,所有这些都共享由类别1000描述的共同的属性、值和类型1008(共同性描述1008’)的某个组合。类别1000具有从其本身到项目1002的关系,它表明项目1002是公有的,且能与类别1000、其成员1004和1006、以及可访问类别1000的任何其它类别、项目文件夹、或项目(未示出)共享。然而,没有从项目1002到类别1000的关系,这表明类别1000对项目1002是私有的,且不与项目1002共享成员资格信息。另一方面,项目1004的确具有从其本身到类别1000的关系1024,这表明类别1000是公有的,且与项目1004共享其成员资格信息。然而,不存在从类别1000延伸到项目1004的关系,这表明项目1004是私有的,且不能与类别1000、它的其它成员1002和1006、以及可访问类别1000的任何其它类别、项目文件夹、或项目(未示出)共享。与它与项目1002和1004的关系(或没有此关系)相反,类别1000具有从其本身到项目1006的关系1016,且项目1006具有回到类别1000的关系1026,这一起表明项目1006是公有的,且能与类别1000、其项目成员1002和1004、以及可访问类别1000的任何其它类别、项目文件夹、或项目(未示出)共享,且类别1000是公有的,且与项目1006共享其成员资格信息。
最后,由于类别和项目文件夹本身是项目,且项目可以互相关系,类别可关系到项目文件夹,反之亦然,且在某些另外实施例中,类别、项目文件夹和项目可分别关系到其它类别、项目文件夹和项目。然而在各种实施例中,项目文件夹结构和/或类别结构在硬件/软件接口系统级上禁止包含回路。当项目文件夹和类别结构类似于有向图时,禁止回路的实施例类似于有向非循环图(DAG),根据图论领域的数学定义,DAG是其中没有路径在同一顶点开始与终止的有向图。
6.可扩展性
如上所述,本存储平台旨在提供初始模式组340。然而,至少在某些实施例中,该存储平台还允许包括独立软件分销商(ISV)等顾客创建新的模式344(即新的项目和嵌套的元素类型)。本节讨论通过扩展在初始模式组340中定义的项目类型和嵌套的元素类型(或简称“元素”类型)着眼于创建该模式的机制。
较佳地,项目和嵌套元素类型的初始组的扩展如下约束:
·允许ISV引入新的项目类型,即子类型Base.Item;
·允许ISV引入新的嵌套元素类型,即子类型Base.NestedElement;
·允许ISV引入新的扩展,即子类型Base.NestedElement;但
·ISV不能子分类由存储平台的初始模式组340定义的任何类型(项目、嵌入元素、或扩展类型)。
由于由存储平台的初始模式组定义的项目类型或嵌入元素类型可能不精确地匹配ISV应用程序的需要,必须允许ISV定制该类型。这就考虑了扩展的概念。扩展是强类型的实例,但是(a)它们不能独立存在,以及(b)它们必须附属于项目或嵌套元素。
除了解决对模式可扩展性的需要之外,扩展还旨在解决“多分类”问题。在某些实施例中,因为存储平台可能不支持多继承性或重叠子类型,应用程序可以使用扩展作为模型化重叠类型实例(如文档既是合法文档又是安全文档)的方法。
a)项目扩展
为提供项目的可扩展性,数据模型还定义名为Base.Extension的抽象类型。这是扩展类型的分层结构的根类型。应用程序可以子分类Base.Extension,以创建特定的扩展类型。
在基础模式中如下定义Base.Extension类型:
<Type Name=″Base.Extension″IsAbstract=″True″>
<Propety Name=″ItemID″
Type=″the storage platformTypes.uniqueidentified″
Nullable=″false″
MultiValued=″false″/>
<Property Name=″ExtensionID″
Type=″the storage platformTypes.uniqueidentified″
Nullable=″false″
MultiValued=″false″/>
</Type>
ItemID字段包含与该扩展关联的项目的ItemID。带此ItemID的项目必须存在。若带给定ItemID的项目不存在,则不能创建扩展。当项目被删除,带同一ItemID的所有扩展被删除。二元组(ItemID,ExtensionID)唯一地标识了扩展实例。
扩展类型的结构类似于项目类型的结构:
·扩展类型具有字段;
·字段可以是原语或嵌套元素类型;以及
·扩展类型可被子分类。
下列限制应用于扩展类型
·扩展不能是关系的源和目标;
·扩展类型实例不能独立于项目存在;以及
·扩展类型不能用作在存储平台类型定义中的字段类型
对能与给定的项目类型关联的扩展的类型没有约束。任何扩展类型允许扩展任何项目类型。当多个扩展实例被附加到一个项目,它们在结构和行为上彼此独立。
扩展实例被分别存储并从项目访问。所有扩展类型实例可从全局扩展视图访问。能组成一有效的查询,它将返回给定类型的扩展的所有实例,而不管它们关联什么类型的项目。存储平台API提供可存储、检索和修改项目扩展的编程模型。
扩展类型可是使用存储平台的单个继承模型来子分类的类型。从一个扩展类型导出创建新的扩展类型。一个扩展的结构或行为不能覆盖或替代项目类型分层结构的结构或行为。类似于项目类型,扩展类型实例能通过与该扩展类型关联的视图直接访问。扩展的ItemID表明,它们属于哪个项目,并能用于从全局项目视图检索对应的项目对象。为操作一致性的目的,扩展被考虑成项目的一部分。拷贝/移动、备份/恢复和存储平台定义的其它常用操作可以在作为项目的一部分的扩展上操作。
考虑下述例子。在Windows类型组中定义Contact(联系人)类型。
<Type Name=″Contact″BaseType=“Base.Item”>
<Property Name=″Name″
Type=″String″
Nullable=″false″
MultiValued=″false″/>
<Property Name=″Address″
Type=″Address″
Nullable=″true″
MultiValued=″false″/>
</Type>
CRM(客户关系管理)应用程序开发者喜欢将CRM应用程序扩展附加到存储在存储平台中的联系人。应用程序开发者定义包含应用程序能处理的附加数据结构的CRM扩展。
<Type Name=″CRMExtension″BaseType=″Base.Extension″>
<Property Name=″CustomerID″
Type=″String″
Nullable=″false″
MultiValued=″false″/>
...
</Type>
HR应用程序开发者希望也将附加数据附加到联系人。此数据独立于CRM应用程序数据。应用程序开发者还可创建-扩展
<Type Name=″HRExtension″EBaseType=″Base.Extension″>
<Property Name=″EmployeeID″
Type=″String″
Nullable=″false″
MultiValued=″false″/>
...
</Type>
CRMExtension和HRExtension是能附加到联系人项目的两个独立扩展。它们能彼此独立地创建和访问。
在上述例子中,CRMExtension类型的字段和方法不能覆盖联系人分层结构的字段和方法。应注意,CRMExtension类型的实例能被附加到不同于联系人的项目类型。
在检索联系人项目时,不自动地检索它的项目扩展。给定联系人项目,可通过查询全局扩展视图以寻找带同一ItemID的扩展来访问其有关的项目扩展。
可通过CRMExtension类型视图来访问系统中所有的CRMExtension扩展,而不论它们属于什么项目。一个项目的所有项目扩展共享同一项目id。在上述例子中,联系人项目实例和附加的CRMExtension和HRExtension实例共享同一ItemID。
下面的表总结了在Item(项目)、Extension(扩展)和NestedElement(嵌套元素)类型之间的相似性和差别:
Item、ItemExtension与NestedElement
b)扩展NestedElement类型
嵌套元素类型不用与项目类型相同的机制扩展。嵌套元素的扩展用与嵌套元素类型字段相同的机制存储和访问。
数据模型定义了名为Element(元素)的嵌套元素类型的根。
<Type Name=″Element″
IsAbstract=″True″>
<Property Name=″ElementID″
Type=″the storage platformTypes.uniqueidentifier″
Nullable=″false″
MultiValued=″false″/>
</Type>
NestedElement类型从此类型继承。NestedElement元素类型另外定义-字段,它是多组元素。
<Type Name=″NestedElement″BaseType=″Base.Element″
IsAbstract=″True″>
<Property Name=″Extensions″
Type=″Base.Element″
Nullable=″false″
MultiValued=″true″/>
</Type>
NestedElement扩展在下面方面不同于项目扩展:
·嵌套元素扩展不是扩展类型。它们不属于以Base.Extension类型为根的扩展类型分层结构。
·嵌套元素扩展与该项目的其它字段一起存储,且不是全局可访问的-不能组成检索给定扩展类型的所有实例的查询。
·象存储其它嵌套元素(或项目)一样地存储这些扩展。象其它的嵌套组,NestedElement扩展被存在UDT中。它们可通过嵌套元素类型的Extension(扩展)字段来访问。
·用于访问多值属性的集合接口也用于在类型扩展组上的访问和迭代。
下面的表总结和比较Item扩展和NestedElement扩展。
Item扩展与NestedElement扩展
D.数据库引擎
如上提到,数据存储在数据库引擎上实现。在本实施例中,数据库引擎包括诸如Microsoft SQL Server引擎等实现SQL查询语言、带有对象关系扩展的关系数据库引擎。本节按照本实施例,描述数据存储实现的数据模型到关系存储的映射,在逻辑API上提供由存储平台的客户机使用的信息。然而可以理解,当采用不同的数据库引擎时可采用不同的映射。确实,除了在关系型数据库引擎上实现存储平台概念数据模型之外,也可在其它类型数据库上实现,如面向对象和XML数据库。
面向对象(OO)数据库系统为编程语言对象(如C++、Java)提供持续性和事务。“项目”的存储平台概念可很好地映射到面向对象系统中的对象,虽然嵌入的集合必须添加给对象。类似继承性和嵌套元素类型等其它存储平台类型概念也映射到面向对象类型的系统。面向对象系统通常已经支持对象身份;因此,项目身份可被映射到对象身份。项目的行为(操作)很好地映射到对象方法。然而,面向对象的系统通常缺乏组织能力并在搜索方面很差。而且,面向对象的系统不提供对非结构化和半结构化数据的支持。为支持这里描述的完全存储平台数据模型,象关系、文件夹和扩展等概念需要添加到对象数据模型。此外,需要实现如升级、同步、通知和安全性等机制。
类似于面向对象的系统,基于XSD(XML模式定义)的XML数据库支持基于单继承类型的系统。本发明的项目类型系统可映射到XSD类型模型。XSD也不提供对行为的支持。项目的XSD必须增添项目的行为。XML数据库处理单个XSD文档并缺乏组织和拓宽搜索能力。如面向对象数据库那样,为支持这里描述的数据模型,如关系和文件夹等其它概念需要被结合到该XML数据库;而且需要实现如同步、通知和安全性等机制。
关于下面小节,提供少量图示以便于一般的信息揭示:图13是示出通知机制的图示。图14是示出两个事务均将新记录插入同一B树的例子的图示。图15示出数据改变检测过程。图16示出示例性目录树。图17示出其中基于目录的文件系统的现有文件夹被移动到存储平台数据存储中。
1.使用UDT的数据存储实现
在本实施例中,在一个实施例中包括Microsoft SQL Server引擎的关系型数据库引擎314支持内建的标量类型。内建的标量类型是“原生(native)”且“简单”的。它们是原生的意义是,用户不能定义他们自己的类型;它们是简单的意义是,用户不能封装复杂的结构。用户定义的类型(下文称为UDT)通过使用户能通过定义复杂的结构化类型来扩展类型系统,提供了一种用于超过或超越原生的标量类型系统的类型可扩展性的机制。一旦由用户定义,UDT能用于可以使用内建标量类型的类型系统中的任何地方。
按本发明的一个方面,存储平台模式被映射到数据库引擎存储中的UDT类。数据存储项目被映射到从Base.Item类型导出的UDT类。类似于项目,扩展也能映射到UDT类并使用继承。根扩展类型是Base.Extension,从它导出所有扩展类型。
UDT是CLR类,它具有状态(即数据字段)和行为(即例程)。使用任何受管语言(c#、VB.NET等)定义UDT。UDT方法和操作符能在T-SQL中针对该类型的实例调用。UDT能是:行中列的类型、T-SQL中例程的参数的类型、或在T-SQL中变量的类型。
存储平台模式到UDT类的映射在高级别上完全是直接的。一般而言,存储平台模式被映射到CLR名字空间。存储平台类型被映射到CLR类。CLR类的继承镜象了存储平台类型的继承,且存储平台属性被映射到CLR类属性。
2.项目映射
为了希望项目能够被全局地搜索,并在本实施例的关系型数据中支持继承以及类型可替代性,对在数据库存储中的项目存储的一种可能的实现是在带有类型Base.Item的列的单个表中存储所有项目。使用类型可替代性,能存储所有类型的项目,且可按使用Yukon的“is of(类型)”的操作符的项目类型的子类型来过滤搜索。
然而,由于在本实施例中牵涉到与这一方法相关联的额外开销,由顶级类型将各项目划分,使得每个类型“家族”的项目存储到单独的表中。在此划分模式中,对每个直接从Base.Item继承的项目类型创建一个表。如上所述,继承下面这些的类型使用类型的可替代性存储在合适的类型家族表中。只有从Base.Item的第一级继承被专门地处理。
使用一“阴影”表存储所有项目的全局可搜索属性的副本。此表可由存储平台API的Update()方法维护,通过此方法作出所有数据的改变。不象类型家族表,此全局项目表只包含该项目的顶级标量属性,而不是全UDT项目对象。全局项目表允许通过展现ItemID和TypeID(类型ID)导航到存储在类型家族表中的项目对象。ItemID通常唯一地标识数据存储中的项目。可使用这里未予描述的元数据将TypeID映射到类型名和包含该项目的视图。由于通过其ItemID寻找项目在全局项目表的上下文及其它情况下都是常用操作,因此给定了项目的ItemId,提供GetItem()函数来检索项目对象。
为便于访问和尽可能地隐藏实现的细节,项目的所有查询可以对照在上述项目的表上构建的视图进行。具体说来,对每个项目类型针对合适类型的家族表创建视图。这些类型视图可选择相关联的类型,包括子类型的所有项目。为方便起见,除了UDT对象,视图能对包括继承字段的该类型的所有顶级域展现列。
3.扩展映射
扩展非常类似于项目,且具有某些相同要求。如支持继承性的另一根类型,扩展受到存储中许多同样的考虑和折衷比较。为此,对扩展应用类似的类型家族映射,而不是单个表方法。当然,在其它实施例中,可使用单个表方法。在本实施例中,扩展通过ItemID仅与一个项目关联,并包含在项目的上下文中唯一的ExtensionID。如同项目一样,给定包括ItemID和ExtensionID对的身份,可提供一函数用于检索扩展。类似于项目类型视图,对每个扩展类型可创建视图。
4.嵌套元素映射
嵌套元素是可嵌入到项目、扩展、关系、或其它嵌套元素以形成深嵌套结构的类型。类似于项目和扩展,嵌套元素作为UDT实现,但它们存储在项目和扩展中。因此,嵌套元素没有超越它们的项目和扩展容器的映射的存储映射。换言之,在系统中没有直接存储NestedElement类型的实例的表,且没有专门用于嵌套元素的视图。
5.对象身份
在数据模型中的每一实体,即每个项目、扩展和关系具有唯一的关键字值。一个项目由其ItemId唯一地标识。扩展由合成关键字(ItemId,ExtensionId)唯一地标识。关系由合成关键字(ItemId,RelationId)标识。ItemId,ExtensionId和RelationshipId均是GUID值。
6.SQL对象命名
在数据存储中创建的所有对象可存储在从存储平台模式名字导出的SQL模式名字中。例如,存储平台基础模式(常称“基础”)可产生在“[System.Storage]”SQL模式中的类型,如“[System.Storage].Item”。产生的名字可用限定词加前缀以消除命名的冲突。在合适处可使用惊叹号(!)作为名字的每个逻辑部分的分割符。下面表概括了在数据存储用于对象的命名习惯。与用于访问数据存储中的实例的修饰的命名习惯一起列出每个模式元素(项目、扩展、关系和视图)。
对象 |
名字修饰 |
描述 |
例子 |
主项目搜索视图 |
Master!Item |
在当前项目域中提供项目的综述 |
[System.Storage].[Master!Item] |
分类型的项目搜索视图 |
ItemType |
提供来自项目和任何父类型的所有属性数据 |
[AcmeCorp.Doc].[OfficeDoc] |
主扩展搜索视图 |
Master!Extension |
提供在当前项目域中所有扩展的综述 |
[System.Storage].[Master!Extension] |
分类型的扩展搜索视图 |
Extension!extensionType |
对扩展提供所有属性数据 |
[AcmeCorp.Doc].[Extension!SlickyNote] |
主关系视图 |
Master!Relationship |
提供在当前项目域中所有关系的综述 |
[System.Storage].[Master!Relationship] |
关系视图 |
Relationship!relationshipName |
提供所有与给定的关系相关联的数据 |
[AcmeCorp.Doc].[Relationship!AuthorsFromDocument] |
视图 |
View!viewName |
基于模式视图定义提供列/类型 |
[AcmeCorp.Doc].[View!DocumentTitles] |
7.列命名
当映射任一对象模型到存储时,由于与应用程序对象一起存储的附加信息,有可能发生命名冲突。为避免命名冲突,所有非类型的特定列(不直接映射到类型声明中的命名的属性的列)用下划线字符(_)加前缀。在本实施例中,下划线字符(_)不允许作为任何标识符属性的开始字符。此外,为统一在CLR和数据存储之间的命名,存储平台类型或模式元素的所有属性(关系等)应具有大写的第一字符。
8.搜索视图
由存储平台提供视图,用于搜索存储的内容。对每个项目和扩展类型提供SQL视图。此外,提供视图以支持关系和视图(由数据模型定义)。所有SQL视图和在存储平台中的底层表是只读的。下面将更充分描述,使用存储平台API的Update()方法可存储或改变数据。
在存储平台模式中直接定义的每个视图(由模式设计者定义,而非由存储平台自动地生成)可由命名的SQL视图[<schema-name>].[View!<view-name>]访问。例如,在模式“AcmePublisher.Books”中名为“BookSales”的视图可使用名字“[AcmePublisher.Books].[View!BookSales]来访问。因为视图的输出格式在每一视图的基础上是自定义的(由定义视图的那一方提供的任意查询确定的),列基于模式视图定义被直接映射。
存储平台数据存储中的所有SQL搜索视图使用列的下述排序习惯:
·如ItemId、ElementId、RelationshipId等的视图结果的逻辑“关键字”列
·如TypeId等关于结果类型的元数据信息。
·改变如CreateVersion(创建版本)、UpdateVersion(更新版本)等跟踪列
·类型专用的列(声明的类型的属性)
·类型专用的视图(家族视图)也包含返回对象的对象列
每个类型家族的成员可使用一系列项目视图来搜索,在数据存储中每个项目类型有一个视图。图28是示出项目搜索视图的概念的图示。
a)项目
每个项目搜索视图对特定类型或其子类型的项目的每个实例包含一行。例如,文档的视图能返回Document(文档)、LegalDocument(合法文档)和ReviewDocument(审阅文档)的实例。给定此例,能如图29那样概念化项目视图。
(1)主项目搜索视图
存储平台数据存储的每个实例定义称为主项目视图(Master Item View)的特殊项目视图。此视图提供关于数据存储中每个项目的综述信息。视图对每个项目类型属性提供一列,其中一列描述项目的类型,若干列用于提供改变跟踪和同步信息。在数据存储中使用名字“[System.Storage].[Master!Item]”来标识主项目视图。
列 |
类型 |
描述 |
ItemId |
ItemId |
该项目的存储平台身份 |
_TypeId |
TypeId |
该项目的TypeId-标识该项目的确切类型并能用于使用元数据类别来检索关于类型的信息 |
_RootItemId |
ItemId |
控制此项目的生命周期的第一个非嵌入先辈的ItemId |
<全局改变跟踪> |
... |
全局改变跟踪信息 |
<项目属性> |
n/a |
对每个项目类型属性有一列 |
(2)分类型的项目搜索视图
每个项目类型也具有搜索视图。类似于根项目视图,此视图还提供通过“_Item”列对项目对象的访问。在数据存储中使用名字[schemaName].[itemTypeName]标识每个分类型的项目搜索视图。例如[AcmeCorp.Dod].[OfficeDoc]。
列 |
类型 |
描述 |
ItemId |
ItemId |
该项目的存储平台身份 |
<类型改变跟踪> |
... |
类型改变跟踪信息 |
<父属性> |
<属性专用> |
对每个父属性有一列 |
<项目属性> |
<属性专用> |
对此类型的每个排他属性有一列 |
_Item |
项目的CLR类型 |
CLR对象一声明的项目的类型 |
9.
a)项目扩展
WinFs存储中的所有项目扩展也可使用搜索视图来访问。
(1)主扩展搜索视图
数据存储的每个实例定义一称为主扩展视图(Master Extension View)的特殊扩展视图。此视图提供关于数据存储中每个扩展的综述信息。该视图对每个扩展属性有一列,其中一列描述扩展的类型,而若干列用于提供改变跟踪和同步信息。使用名字“[System.Storage].[Master!Extension]”在数据存储中标识主扩展视图。
ItemId |
ItemId |
与此扩展关联的项目的存储平台身份 |
ExtensionId |
ExtensionId(GUID) |
此扩展实例的id |
_TypeId |
TypeId |
该扩展的TypeId-标识该扩展的确切类型,并能用于使用元数据类别来检索关于该扩展的信息 |
<全局改变跟踪> |
... |
全局改变跟踪信息 |
<扩展属性> |
<属性专用> |
对每个扩展类型属性有一列 |
10.
(1)分类型的扩展搜索视图
每个扩展类型还具有搜索视图。类似于主扩展视图,此视图还提供通过_Extension列对项目对象的访问。在数据存储中使用名字[SchemaName].[Extension!extensionTypeName]标识每个分类型的扩展搜索视图。例如[AcmeCorp.Doc].[Extension!OfficeDocExt]。
列 |
类型 |
描述 |
ItemId |
ItemId |
与此扩展关联的项目的存储平台身份 |
ExtensionId |
ExtensionId(GUID) |
此扩展实例的Id |
<类型改变跟踪> |
... |
类型改变跟踪信息 |
<父属性> |
<属性专用> |
对每个父属性有一列 |
<扩展属性> |
<属性专用> |
对每个此类型的排他属性有一列 |
_Extension |
扩展实例的CLR类型 |
CLR对象-声明的扩展的类型 |
b)嵌套的元素
所有嵌套的元素存储在项目、扩展或关系实例之中。因此,它们能通过查询合适的项目、扩展或关系搜索视图来访问。
c)关系
如上讨论,关系形成在存储平台数据存储中各项目之间链接的基本单元。
(1)主关系搜索视图
每个数据存储提供-主关系视图。此视图提供关于数据存储中所有关系实例的信息。在数据存储中使用名字“[System.Storage].[Master!Relationship]”来标识主关系视图。
列 |
类型 |
描述 |
ItemId |
ItemId |
源端点的身份(ItemId) |
RelationshipId |
RelationshipId(GUID) |
该关系实例的id |
_RelTypeId |
RelationshiPTypeId |
该关系的RelTypeId-使用元数据类别来标识该关系实例的类型 |
<全局改变跟踪> |
... |
全局改变跟踪信息 |
TargetItemReference |
ItemReference |
目标端点的身份 |
_Relationship |
Relationship |
对此实例的Relationship对象的实例 |
(2)关系实例搜索视图
每个声明的关系也有返回该特定关系的所有实例的搜索视图。类似于主关系视图,此视图对该关系数据的每个属性提供命名的列。在数据存储中使用名字[schemaName].[Relationship!relationshipName]来标识每个关系实例搜索视图。例如[AcmeCorp.Doc].[Relationship!DocumentAuthor]。
列 |
类型 |
描述 |
ItemId |
ItemId |
源端点的身份(ItemId) |
RelationshipId |
RelationshipId(GUID) |
该关系实例的id |
<类型改变跟踪> |
... |
类型改变跟踪信息 |
TargetItemReference |
ItemReference |
目标端点的身份 |
<源名> |
ItemId |
源端点身份的命名属性(ItemId的别名) |
<目标名> |
ItemReference或导出的类 |
目标端点身份的命名属性(TargetItemReference的别名和模型(cast)) |
<关系属性> |
<属性专用> |
对每个关系定义的属性有一列 |
_Relationship |
关系实例的CLR类型 |
CLR对象-声明关系的类型 |
d)
11.更新
存储平台数据存储中所有视图是只读的。为创建数据模型元素(项目、扩展或关系)的新实例,或更新现有的实例,必须使用存储平台API的ProcessOperation或ProcessUpdategram方法。ProcessOperation方法是单个存储的过程,它是由消费细化拟执行的动作的“操作”的数据存储定义的。ProcessUpdategram方法是存储的过程,它采取称为“更新元素(updategram)”的一组有序的操作,它们共同细化拟执行的一组动作。
操作格式是可扩展的,并提供在模式元素上的各种操作。某些公用操作包括:
1.项目操作:
a.CreateItem(在嵌入或持有关系的上下文中创建一新的项目)
b.UpdateItem(更新一现有的项目)
2.关系操作:
a.CreateRelationship(创建引用或持有关系的实例)
b.UpdateRelationship(更新一关系实例)
c.DeleteRelationship(移除一关系实例)
3.扩展操作
a.CreateExtension(添加一扩展到现有的项目)
b.UpdateExtension(更新一现有的扩展)
c.DeleteExtension(删除一扩展)
12.改变跟踪及墓碑
如下面更充分讨论,由数据存储提供改变跟踪和墓碑服务。本节提供在数据存储中展现的改变跟踪信息的概述
a)改变跟踪
由数据存储提供的每个搜索视图包含用于提供改变跟踪信息的列;那些列对所有项目、扩展和关系视图是公用的。由模式设计者明确地定义的存储平台模式视图不自动地提供改变跟踪信息-该信息是通过在其上构建视图本身的搜索视图来间接提供的。
对数据存储中的每个元素,可从两个地方得到改变跟踪信息:“主”元素视图和“分类型的”元素视图。例如,可从主项目视图“[System.Storage].[Master!Item]”和分类型的项目视图[AcmeCorp.Document].[Document]中得到关于AcmeCorp.Document.Document项目类型的改变跟踪信息。
(1)“主”搜索视图中的改变跟踪
主搜索视图中的改变跟踪信息提供关于元素的创建和更新版本的信息、关于哪个同步伙伴创建该元素的信息、关于哪个同步伙伴最后一次更新该元素的信息、以及来自每个伙伴的用于创建和更新的版本号。用伙伴关键字来标识同步关系中的伙伴(下面描述)。类型[System.Storge.Store].ChangeTrackingInfo的名为_ChangeTrackingInfo的单个UDT对象包含所有这些信息。在System.Storage模式中定义类型。在项目、扩展和关系的所有全局搜索视图中可得到_ChangeTrackingInfo。_ChangeTrackingInfo的类型定义是:
<Type Name=″ChangeTrackingInfo″BaseType=″Base.NestedElement″>
<FieldProperty Name=″CreationLocalTS″ Type=″SqlTypes.SqlInt64″
Nullable=″False″/>
<FieldProperty Name=″CreatingPartnerKey″ Type=″SqlTypes.SqlInt32″
Nullable=″False″/>
<FieldProperty Name=″CreatingpartnerTS″ Type=″SqlTypes.SqlInt64″
Nullable=″False″/>
<FieldProperty Name=″LastUpdateLocalTS″ Type=″SqlTypes.SqlInt64″
Nullable=″False″/>
<FieldProperty Name=″LastUpdatingPartnerKey″ Type=″SqlTypes.SqlInt32″
Nullable=″False″/>
<FieldProperty Name=″LastUpdatingPartnerTS″ Type=″SqlTypes.SqlInt64″
Nullable=″False″/>
</Type>
这些属性包含下述信息:
列 |
描述 |
_CreationLocalTS |
本地机器的创建时间标记 |
_CreatingPartnerKey |
创建此实体的伙伴的PartnerKey。若实体是本地创建的,这是本地机器的PartnerKey |
_CreatingPartnerTS |
在对应于_CreatingPartnerKey的伙伴处创建此实体的时间的时间标记 |
_LastUpdateLocalTS |
对应于本地机器的更新时间的本地时间标记 |
_LastUpdatePartnerKey |
最后一次更新此实体的伙伴的PartnerKey。若对该实体的最后一次更新在本地完成,则这是本地机器的PartnerKey。 |
_LastUpdatePartnerTS |
在对应于_LastUpdatingPartnerKey的伙伴处更新此实体的时间的时间标记。 |
(2)“分类型的”搜索视图中的改变跟踪
除了提供与全局搜索视图相同信息外,每个分类型的搜索视图提供记录在同步拓扑中每个元素的同步状态的附加信息。
列 |
类型 |
描述 |
<全局改变跟踪> |
... |
来自全局改变跟踪的信息 |
_ChangeUnitVersions |
MultiSet<改变单元版本> |
特定元素中的改变单元的版本号的描述 |
_ElementSyncMetadata |
ElementSyncMetadata |
关于只对同步运行库感兴趣的项目的附加版本无关元数据 |
_VersionSyncMetadata |
VersionSyncMetadata |
关于只对同步运行库感兴趣的版本的附加版本专用元数据 |
b)墓碑
数据存储为项目、扩展和关系提供墓碑信息。墓碑视图提供一个地方中有关活动和墓碑实体两者(项目、扩展和关系)的信息。项目和扩展墓碑视图不提对对应对象的访问,而关系墓碑视图提供对关系对象的访问(在墓碑关系的情况下关系对象为空)。
(1)项目墓碑
通过视图[System.Storage].[Tombstone!item]从系统检索项目墓碑。
列 |
类型 |
描述 |
ItemId |
ItemId |
项目的身份 |
_TypeID |
TypeId |
项目的类型 |
<项目属性> |
... |
对所有项目定义的属性 |
_RootItemId |
ItemId |
包含此项目的第一个非嵌入项目的ItemId |
_ChangeTrackingInfo |
ChangeTrackingInfo类型的CLR实例 |
此项目的改变跟踪信息 |
_IsDeleted |
BIT |
这是标志,0是活动项目,1是墓碑项目 |
_DeletionWallclock |
UTCDATETIME |
按删除项目的伙伴的UTC墙钟日期时间,若该项目是活动的,它为空 |
(2)扩展墓碑
使用视图[System.Storage].[Tombstone!Extension]从系统检索扩展墓碑。扩展改变跟踪信息类似于为项目提供的添加了ExtensionId属性的信息。
列 |
类型 |
描述 |
ItemId |
ItemId |
拥有该扩展的项目的身份 |
ExtensionId |
ExtensionId |
该扩展的ExtensionId |
_TypeID |
TypeId |
该扩展的类型 |
_ChangeTrackingInfo |
ChangeTrackingInfo类型的CLR实例 |
此扩展的改变跟踪信息 |
_IsDeleted |
BIT |
这是标志,0是活动项目,而1是墓碑扩展 |
_DeletionWallclock |
UTCDATETIME |
按删除该扩展的伙伴的UTC墙钟日期间。若该扩展是活动的,它为空 |
(3)关系墓碑
通过视图[System.Storage].[Tombstone!Relationship]从系统检索关系墓碑。关系墓碑信息类似于对扩展提供的信息。然而,在关系实例的目标ItemRef上提供附加信息。此外,还选择关系对象。
ItemId |
ItemId |
拥有该关系的项目的身份(关系的源端点的身份) |
RelationshipId |
RelationshipId |
该关系的RelationshipId |
_TypeID |
TypeId |
关系的类型 |
_ChangeTrackingInfo |
ChangeTrackingInfo类型的CLR实例 |
此关系的改变跟踪信息 |
_IsDeleted |
BIT |
这是标志,0是活动项目,而1是墓碑扩展 |
_DeletionWallclock |
UTCDATETIME |
按删除该关系的伙伴的UTC墙钟日期时间。若该关系是活动的,它为空 |
_Relationship |
关系的CLR实例 |
这是活动关系的关系对象,对墓碑的关系它为空 |
TargetItemReference |
ItemReference |
目标端点的身份 |
(4)墓碑清除
为防止墓碑信息无限制地增长,数据存储提供墓碑清除任务。此任务确定什么时候可以舍弃墓碑信息。该任务计算本地创建/更新版本的界限,并随后通过舍弃所有更早的墓碑版而截断墓碑信息。
13.助手API和函数
基础映射还提供若干助手函数。提供这些函数以帮助在该数据模型上的公用操作。
a)函数[System.Storage].GetItem
//给定ItemId返回一项目对象
Item GetItem(ItemId ItemId)
b)函数[System.Storage].GetExtension
//给定ItemId和ExtensionId返回一扩展对象
Extension GetExtension(ItemId ItemId,ExtensionId ExtensionId)
c)函数[System.Storage].GetRelationship
//给定ItemId和RelationshipId返回-关系对象
Relationship GetRelationship(ItemId ItemId,RelationshipId RelationshipId)
14.元数据
有两类在存储中表示的元数据:实例元数据(项目的类型等),和类型元数据。
a)模式元数据
模式元数据作为来自元模式的项目类型的实例存储在数据存储中。
b)实例元数据
应用程序使用实例元数据来查询项目的类型,并寻找与项目相关联的扩展。给定项目的ItemId,应用程序可查询全局项目视图,以返回该项目的类型,并使用此值来查询Meta.Type视图以返回关于该项目的声明的类型的信息。例如,
//对给定的项目实例返回元数据项目对象
SELECT m._Item AS metadataInfoObj
FROM[System.Storage].[Item]i INNER JOIN[Meta].[Type]m ON i._TypeId=m.ItemId
WHERE i.ItemId=@ItemId
E.安全性
一般而言,所有可保护的对象使用图26中所示的访问掩码格式来安排访问权限。在此格式中,低16位用于对象专用的的访问权限,接着7位用于应用于大多数对象类型的标准访问权限,高4位用于指定类属访问权限,每个对象类型将其映射到一组标准且对象专用的权限。ACCESS_SYSTEM_SECURITY位对应于访问对象的SACL的权限。
在图26的访问掩码结构中,项目专用的权限被放置在对象专用权限段(低16位)。由于在本实施例中,存储平台向管理员安全性展现两组API:Win32和存储平台API,为促进存储平台对象专用权限的设计,必须考虑文件系统对象专用的权限。
在通过引用结合于此的有关专利中充分描述了用于本发明的存储平台的安全模型。在这点上,图27(部分a、b和c)画出按安全模型的一实施例,作为从现有安全区域开拓出的新的等同地保护的安全区域。
F.通知和改变跟踪
按本发明的另一方面,存储平台提供允许应用程序跟踪数据改变的通知能力。此特征主要供保持易失状态或执行数据改变事件上的业务逻辑的应用程序使用。应用程序注册在项目、项目扩展及项目关系上的通知。在提交了数据改变通知被异步地传送。应用程序可按项目、扩展和关系类型以及操作类型来过滤通知。
按一个实施例,存储平台API 322为通知提供两类接口。第一,应用程序注册由对项目、项目扩展和项目关系的改变触发的简单数据改变事件。第二,应用程序创建“监视程序”对象来监视项目、项目扩展和项目之间关系的组。在系统失败或系统离线超过预定时间之后,可保存和重新创建监视程序对象的状态。单个通知可反映多个更新。
关于此功能的附加细节能在先前通过引用结合于此的有关专利中找到。
G.传统文件互操作性
如上提到,至少在某些实施例中,本发明的存储平台旨在被实施为计算机系统的硬件/软件接口系统的整体部分。例如,本发明的存储平台可被实施为如Microsoft Windows家族操作系统的整体部分。在这方面,存储平台API成为操作系统API的一部分,应用程序通过它与操作系统交互。因此,存储平台成为装置,应用程序通过它将信息存到操作系统上,且从而基于项目的存储平台的数据模型替代了这一操作系统的传统文件系统。例如,当在Microsoft Windows家族操作系统中实施时,存储平台可替代在该操作系统中实现的NTFS文件系统。当前,应用程序通过由Windows家族操作系统展现的Win32API来访问NTFS文件系统的服务。
然而,应认识到,完全用本发明的存储平台替代NTFS文件系统需要重新编码现有的基于Win32的应用程序,且那样的重新编码可能是不合需要的,因此本发明的存储平台提供与如NTFS等现有文件系统的某种互操作性是有益的。从而,在本发明的一个实施例中,存储平台使依赖于Win32编程模型的应用程序能同时访问存储平台的数据存储以及传统的NTFS文件系统的数据存储的内容。为此,存储平台使用作为Win32命名习惯的超集(superset)的命名习惯以便于容易的互操作性。此外,存储平台支持通过Win32 API访问存储在存储平台卷中的文件和目录。
关于此功能的另外细节能在先前通过引用结合于此的有关专利中找到。
H.存储平台API
存储平台包括API,它使应用程序能访问上面讨论的存储平台的特征和能力,并访问存储在数据存储中的项目。本节描述本发明的存储平台的存储平台API的一个实施例。关于此功能的细节能在通过引用结合于此的有关专利中找到,为方便起见在下面总结此信息的某一些。
参考图18,包含文件夹是一个项目,它包含与其它项目的持有关系,且与通常概念的文件系统文件夹等价。每个项目“包含”在至少一个包含文件夹中。
图19示出按本实施例的存储平台API的基本体系结构。存储平台API使用SQL客户机1900与本地数据存储302对话,并还使用SQL客户机1900与远程数存储(如数据存储340)对话。本地存储还可使用DQP(分布式查询处理器)或通过上述的存储平台同步服务(“Sync”)与远程数据存储340对话。存储平台API322还担当数据存储通知的桥接器API,将应用程序的下标传送到通知引擎,并如上所述将通知路由到应用程序(如应用程序350a、350b或350c)。在一个实施例中,存储平台API 322还定义受限制的“提供者”体系结构,使得它能访问MicrosoftExchange和AD中的数据。
图20示意性地表示存储平台API的各种组件。存储平台AP包括下列组件:(1)数据类2002,它代表存储平台元素和项目类型;(2)运行库架构2004,它管理对象的持久性并提供支持类2006;以及(3)工具2008,它用于从存储平台模式生成CLR类。
从给定模式得出的类的分层结构直接反应了该模式中类型的分层结构。作为例子,考虑在如图21A和图21B中所示的联系人模式中定义的项目类型。
图22示出操作中的运行库架构。运行库架构如下操作:
1.应用程序350a、350b或350c绑定到存储平台的项目。
2.架构2004创建对应于绑定项目的ItemContext对象2202,并将其返回给应用程序。
3.应用程序提交在此ItemContext(项目上下文)上的Find(寻找),以得到项目的集合;返回的集合在概念上是对象图2204(由于关系)。
4.应用程序改变、删除和插入数据。
5.应用程序通过调用Update()方法保存改变。
图23示出“FindAll(寻找所有)”操作的执行。
图24示出从存储平台模式生成存储平台API类的过程。
图25示出文件API所基于的模式。存储平台API包括处理文件对象的名字空间。该名字空间被称为System.Storage.Files。System.Storage.Files中的类的数据成员直接反映了存储在存储平台存储中的信息;此信息是从文件系统对象的“升级”或使用Win32API本机地创建。System.Storage.Files名字空间具有两个类:FileItem(文件项目)和DirectoryItem(目录项目)。这些类的成员及其方法可通过审阅图25中的模式图来预测。FileItem和DirectoryItem是从存储平台API只读的。为修改它们,必须使用System.IO中的Win32API或类。
对于API,编程接口(或简称之为接口)可以被视为用于令代码的一个或多个片断能与由代码的一个或多个其它片断提供的功能进行通信或对其进行访问的任一机制、过程、协议。或者,编程接口可以被视为能够通信地耦合至其它计算机的一个或多个机制、方法、函数调用、模块等的系统的组件的一个或多个机制、方法、函数调用、模块、对象等。上述语句中的术语“代码片断”意在包括代码的一个或多个指令或代码行,并包括,如,代码模块、对象、子例程、函数等等,无论应用的术语是什么、或代码片断是否被单独编译、或代码片断是否被提供为源码、中间码或对象代码、代码片断是否在运行时系统或进程中使用、或它们是否位于同一或不同机器上或跨多个机器分布、或由代码片断表示的功能是否完全由软件、完全由硬件或硬件和软件的组合来实现。
概念上,编程接口可以被一般地察看,如图30A或图30B所示的。图30A示出了接口“接口1”为管道,第一和第二代码片断通过该管道进行通信。图30B示出了接口包括接口对象I1和I2(可以是或不是第一和第二代码片断的部分),它们令系统的第一和第二代码片断能通过介质M进行通信。在图30B中,可以认为接口对象I1和I2为同一系统的单独接口,并且也可以认为对象I1和I2加上介质M构成了接口。尽管图30A和30B示出了双向流程以及该流程的每一侧上的接口,某些实现可仅具有一个方向上的信息流(或如下所述没有信息流),或仅具有一侧的接口对象。作为示例而非局限,诸如应用编程或程序接口(API)、入口点、方法、函数、子例程、远程过程调用和组件对象模型(COM)接口等术语包含在编程接口的定义之内。
这类编程接口的方面可包括第一代码片断向第二代码片断发送信息的方法(其中,“信息”以其最广泛的意义使用,并包括数据、命令、请求等等);第二代码片断接收信息的方法;以及该信息的结构、序列、语法、组织、模式、定时和内容。在这一点上,只要信息以接口所定义的方式传输,底层传输介质本身可以对接口的操作不重要,无论该介质是有线还是无线,或两者的组合。在某些情况下,在常规意义上,当一个代码片断仅访问由第二代码片断执行的功能时,信息可不在一个或两个方向上传输,因为信息传输可以是或者通过另一机制(如,信息被放置在与代码片断之间的信息流分离的缓存、文件等中)或者不存在。这些方面的任一个或所有可以在给定的情况下重要,如,取决于代码片断是否是松耦合或紧耦合配置的系统的一部分,并且因此该列表应当被认为是说明性的而非限制。
编程接口的这一概念对本领域的技术人员是已知的,并且可以阅读上述本发明的详细描述而清楚这一概念。然而,有其它方法来实现编程接口,并且除非明显地排除,这些方法也由所附权利要求书包含在内。这些其它方法看似比图30A和30B的视图更精密或复杂,但是它们仍执行类似的功能来完成同一整体结果。现在简要描述编程接口的某些说明性替换实现。
分解:可以通过将通信分裂成多个离散通信来间接地实现从一个代码片断到另一个的通信。这在图31A和31B中示意性地描述。如图所示,可以按照功能的可分组来描述某些接口。由此,可以分解图30A和30B的接口功能来达到相同的结果,如同可以在数学上提供24,或2乘2乘3乘2一样。因此,如图31A所示,可以细分由接口“接口1”提供的功能以将该接口的通信变换成多个接口“接口1A”、“接口1B”、“接口1C”等,而达到相同的结果。如图31B所示,由接口I1提供的函数可以被细分成多个接口I1a、I1b、I1c等,而达到相同的结果。类似地,从第一代码片断接收信息的第二代码片断的接口I2可以被分解成多个接口I2a、I2b、I2c等。当分解时,包括在第一代码片断中的接口的数量不需要匹配包括在第二代码片断中的接口的数量。在图31A或31B的任一情况下,接口“接口1”和I1的功能性精神分别与图30A和30B的保持相同。接口的分解也可遵从联合、通信和其它数学性质,使得分解较难识别。例如,命令操作可以是不重要的,并且因此由接口完成的功能可以在达到该接口之前由另一段代码或接口较好地完成,或者由系统的单独组件执行。此外,编程领域的普通技术人员可以理解有各种方式来作出不同的函数调用而达到相同的结果。
重定义:在某些情况下,可能忽略、添加或重定义编程接口的某些方面(如参数),而仍达到预期的结果。这在图32A和32B中示出。例如,假定图30A的接口“接口1”包括函数调用Square(input,precision,output)(平方),它包括三个参数,input(输入)、precision(精度)和output(输出),并且由第一代码片断向第二代码片断发布。如果中间参数precision在给定的情形下无关紧要,如图32A所示,它也可以被忽略或甚至由meaningless(无意义)(在这一情况下)参数来替换。也可以添加无关紧要的additional(另外)参数。在任一情况下,只要在输入由第二代码片断平方之后返回输出,就可以达到square(平方)的功能。Precision也有可能对计算系统的某一下游或其它部分是极有意义的参数;然而,一旦认识到precision对计算平方这一有限目的不是必需的,它可以被替换或忽略。例如,不是传递一个有效的pricision值,而是在不对结果产生不利影响的情况下传递诸如出生日期等无意义的值。类似地,如图32B所示,接口I1由接口I1′替换,它被重新定义来忽略或向接口添加参数。接口I2可类似地被重定义为接口I2′,它被重定义来忽略不必要的参数,或可在别处处理的参数。此处的要点是在某些情况下,编程接口可包括对某一目的而言所不需要的方面,诸如参数,因此可以忽略或重定义它们,或在别处处理它们用于其它目的。
内嵌代码:合并两个单独的代码模块的一些或全部功能也是可行的,使得它们之间的“接口”改变形式。例如,图30A和30B的功能可以被分别转化到图33A和33B的功能。在图33A中,图30A的先前的第一和第二代码片断被合并成包含两者的模块。在这一情况下,该代码片断仍可以彼此通信,但是该接口可以适用于更适合单个模块的形式。由此,例如,正式的调用(Call)和返回(Return)语句将不再必需,但是依照接口“接口1”的类似的处理或响应仍是有效的。类似地,如图33B所示,图30B的部分(或所有)接口I2可以内嵌地写入接口I1来形成接口I1″。如图所示,接口I2被划分成I2a和I2b,并且接口部分I2a内嵌在接口I1中书写代码来形成接口I1″。对于具体的示例,考虑图30B的接口1执行函数调用square(input,output),它由接口I2接收,在由第二代码片断处理传递到input的值(对其求平方)之后,它被使用output传递回已求平方的结果。在这一情况下,由第二代码片断执行的处理(对input求平方)可以由第一代码片断在不调用该接口的情况下执行。
脱离:可以通过将通信分裂成多个离散的通信来间接地完成从一个代码片断到另一个的通信。这在图34A和34B中示意性地描述。如图34A所示,提供了中间件的一个或多个片断(脱离接口(Divorce Interface),因为它们从原始的接口脱离的功能和/或接口函数),以转化第一接口“接口1”上的通信,使得它们符合不同的接口,在本情况下为“接口2A”、“接口2B”和“接口2C”。这可以在这样一种情况中完成,例如,依照“接口1”协议设计应用的已安装基础与如操作系统进行通信,但是然后改变该操作系统来使用不同的接口,在本情况下为接口“接口2A”、“接口2B”和“接口2C”。要点是改变了由第二代码片断使用的原始接口,使得它不再与第一代码片断所使用的接口兼容,因此使用中介来令旧接口和新接口兼容。类似地,如图34B所示,可以使用脱离接口DI1引入第三代码片断以从接口I1接收信息,并使用脱离接口DI2引入第三代码片断以向例如接口I2a和I2b发送接口功能,重新设计接口I2a和I2b以使用DI2,但是提供相同的功能性结果。类似地,DI1和DI2可共同工作以将图30B的接口I1和I2的功能转换成一新操作系统,而提供相同或类似的功能性结果。
重写:再一种可能的变化是动态地重写代码,使用别的东西来替换接口的功能,而仍达到相同的总体结果。例如,可以有一种系统,其中,向执行环境(如由.Net框架提供的环境、Java运行时环境或其它类似的运行时刻类型环境)中的及时(Just-in-Time)(JIT)编译器或解释器提供了中间语言(如Microsoft IL、JavaByteCode等)中呈现的代码片断。可以书写JIT编译器以动态地将通信从第一代码片断转化到第二代码片断,即,令它们符合第二代码片断(原始或不同的第二代码片断)所需要的不同接口。这在图35A和35B中有描述。如图35A中所看见的,这一方式类似于上述的脱离情形。它可以在这样一种情况下完成,例如,依照“接口1”协议设计应用的已安装基础操作系统进行通信,然后改变该操作系统以使用不同的接口。JIT编译器可以用于令已安装基础应用的空中通信符合操作系统的新接口。如图35B所描述的,可以应用这一动态重写接口的方法以进行动态分解,或者改变接口。
应当注意,上述通过替换实施例实现与接口相同或相似的结果的情形也可以以各种方式串行、并行或与其它干预代码组合。由此,上文呈现的替换实施例并非相互穷尽,并且可以被混合、匹配和组合以产生与图30A和30B中所呈现的一般情形相同或等效的情形。也应当注意,如同大多数编程构造,本发明可能未描述达到与接口相同或相似的功能的其它类似的方式,但是它们仍由本发明的精神和范围来表示,即,应当注意,它至少部分地是由作为接口的值的基础的接口表示的功能或由其启用的有利结果。
III.同步API
在基于项目的硬件/软件接口系统中,有若干种同步方法是可行的。
A.同步综述
对于本发明的若干实施例,并参考图3,存储平台提供同步服务330,它(I)允许存储平台的多个实例(每个有自己的数据存储302)按一组灵活的规则来同步它们的内容的各部分,以及(ii)为第三方提供基础结构以将本发明的存储平台的数据存储与实现专有协议的其它数据源同步。
存储平台到存储平台的同步在一组参与的复制品之间发生。例如参考图3,希望在多半是在不同的计算机系统上运行的存储平台的另一实例的控制下提供在存储平台300的数据存储302和另一远程数据存储338之间的同步。该组的总的成员资格不必在任何给定时间被任何给定复制品知道。
不同的复制可以独立地(即并发地)作出改变。将同步过程定义成使每个复制品知道由其它复制品作出的改变。此同步能力本质上是多主的(multi-master)(即,对等的)。
本发明的同步能力允许各复制品:
·确定另一复制品知道什么改变;
·请求关于此复制品不知道的改变的信息;
·传输关于其它复制品不知道的改变的信息;
·确定两个改变何时互相冲突;
·本地应用改变;
·传输冲突分解到其它复制品以确保会聚性;以及
·基于对冲突分解指定的政策分解冲突。
1.存储平台到存储平台的同步
本发明的存储平台的同步服务300的基本应用是同步存储平台(每个带有它自己的数据存储)的多个实例。同步服务在存储平台模式级上操作(而不是在数据库引擎314的底层表中)。因此,例如“范围(Scope)”用于定义下面讨论的同步组。
同步服务按“纯改变(net change)”的原则操作。不是记录和发送各个操作(如事务复制),同步服务而是发送这些操作的最终结果,因此常将多个操作的结果合并成单个最终结果。
同步服务通常不考虑事务边界。换言之,若在单个事务中对存储平台数据存储作出两个改变,不保证这些改变原子地应用到所有其它复制品上-可以示出一个改变而不示出其它改变。此原则的例外是,若在同一事务中对同一项目作出两个改变,则这些改变保证被原子地发送和应用到其它复制。因此,项目是同步服务的一致性单元。
a)同步(Sync)控制应用程序
任一应用程序可连接到同步服务并启动sync(同步)操作。那样的应用程序提供执行同步(见下面同步概况)所需的所有参数。那样的应用程序在这里被称为同步控制应用程序(SCA)。
在同步两个存储平台实例时,在一侧由SCA启动同步。该SCA通知本地同步服务与远程伙伴同步。在另一侧,同步服务通过由来自发起机器的同步服务发出的消息唤醒。它基于在目标机器上存在的持久配置信息(见下文的映射)作出响应。同步服务能按时间表或响应于事件运行。在这些情况下,实现时间表的同步服务成为SCA。
为启用同步,需要采取两个步骤。首先,模式设计者必须用合适的同步语义注释存储平台模式(如下文所述的指定改变单元)。其次,同步必须在具有参与同步的存储平台的实例的所有机器上正确地配置(如下所述)。
b)模式注释
同步服务的基本概念是改变单元(Change Unit)的概念。改变单元是由存储平台个别地跟踪的最小的模式片段。对每个改变单元,同步服务能确定自从最后一次同步以来它是被改变还是未被改变。
指定模式中的改变单元达到若干目的。首先,它确定了在线的同步服务如何罗嗦。当在改变单元内作出改变时,整个改变单元被发送到其它复制品,因为同步服务不知道改变单元的哪部分被改变。其次,它确定了冲突检测的粒度。当对同一改变单元作出两个并发的改变(这些术语在后继章节中详细定义),同步服务引起冲突;另一方面,若对不同改变单元作出并发改变,则无冲突发生,且改变被自动地合并。第三,它严重地影响了由系统保持的元数据的量。对每个改变单元保持许多同步服务元数据;因此,使改变单元更小会增加同步的额外开销。
定义改变单元需要找出正确的折衷。为此,同步服务允许模式设计者参与此过程。
在一个实施例中,同步服务不支持大于一个元素的改变单元。然而,它支持让模式设计者指定比一个元素更小的改变单元的能力-即将一个元素的多个属性组合到单独的改变单元中。在该实施例中,这是使用下述句法实现的:
<Type Name=″Appointment″MajorVersion=″1″MinorVersion=″0″ExtendsType=″Base.Item″
ExtendsVersion=″1″>
<Field Name=″MeetingStatus″Type=″the storage platformTypes.uniqueidentifier
Nullable=″False″/>
<Fileld Name=″OrganizerName″Type=″the storage platformTypes.nvarchar(512)″
Nullable=″False″/>
<Filed Name=″OrganizerEmail″Type=″the storage platformTypes.nvarchar(512)″
TypeMajorVersion=″1″ MultiValued=″True″/>
...
<ChangeUnit Name=″CU_Status″>
<Field Name=″MeetingStatus″/>
</ChangeUnit>
<ChangeUnit Name=″CU_Organizer″/>
<Field Name=″OrganizerName″/>
<Field Name=″OrganizerEmail″/>
</ChangeUnit>
...
</Type>
c)同步配置
希望保持它们数据的某些部分同步的一组存储平台伙伴被称为同步共同体。虽然共同体的成员希望保持同步,它们不需要以完全相同的方式表示数据;换言之,同步伙伴可转换他们正在同步的数据。
在对等情况下,让对等方对所有它们的伙伴维持转换映射是不现实的。取代地,同步服务采取定义“共同体文件夹”的方法。共同体文件夹是代表所有共同体成员正在与之同步的假设的“共享文件夹”的抽象。
此概念最好用一例子说明。若Joe希望保持他的若干计算机的My Documents(我的文档)文件夹同步,Joe定义一共同体文件夹,如称为JoeDocuments。随后在每台计算机上,Joe在假设的JoeDocuments文件夹和本地My Documents文件夹之间配置一映射。从这点出发,当Joe的计算机彼此同步时,它们借助JoeDocuments中的文档而不是它们的本地项目来交谈。以此方法,所有Joe的计算机互相理解,而不必知道其它人是谁-共同体文件夹成为同步共同体的通用语。
配置同步服务包括三个步骤:(1)定义在本地文件夹和共同体文件夹之间的映射;(2)定义确定哪个得到同步的同步概况(如与谁同步,以及哪个子集应当被发送、哪个被接收);以及(3)定义不同的同步概况应当运行的时间表,或手动运行它们。
(1)共同体文件夹-映射
共同体文件夹映射作为XML配置文件被存储在个别机器上。每个映射具有以下模式:
/mappings/communityFolder
此元素命名映射的共同体文件夹。名字遵循文件夹的句法规则。
/mappings/localFolder
此元素命名映射所转换到的本地文件夹。此名字遵循文件夹的句法规则。为了映射有效,文件夹必须已存在。此文件夹中的项目被看作对每一此映射的同步。
/mappings/transformations
此元素定义如何将项目从共同体文件夹转换到本地文件夹以及如何反向转换。若缺少或为空,不执行转换。具体说来,这意味着无ID被映射。此配置主要用于创建文件夹的高速缓存。
/mappings/transformations/mapIDs
此元素请求新生成的本地ID被赋予所有从共同体文件夹映射的项目,而不是重新使用共同体ID。同步运行库维护ID映射,以来回转换项目。
/mappings/transformations/localRoot
此元素请求共同体文件夹中的所有根项目作为指定根的子项目。
/mappings/runAs
此元素控制,在谁的授权下处理针对此映射的请求。若不存在,则假设发送者。
/mappings/runAs/sender
存在此元素表明,对此映射的消息发送者必须是人格化的,且在他的凭证下处理请求。
(2)概况
同步概况是分离同步所需的总的参数组。由SCA将其提供给同步运行库以启动同步。存储平台到存储平台的同步的同步概况包含以下信息:
·本地文件夹,用作改变的源和目标;
·与之同步的远程文件夹名-此文件夹必须通过如上定义的映射从远程伙伴发布;
·方向-同步服务支持只发送、只接收以及发送-接收同步;
·本地过滤器-选择发送什么本地信息到远程伙伴。表示成本地文件夹上的存储平台查询;
·远程过滤器-选择从远程伙伴接收什么远程信息-表示成共同体文件夹上的存储平台查询;
·转换-定义如何在项目和本地格式间转换;
·本地安全性-指定是在远程端点(人格化)的许可下应用从远程端点检索的改变,还是用户在本地启动同步;以及
·冲突分解政策-指定冲突是否应被拒绝、记入日志或自动分解-在后一种情况下,指定使用哪个冲突分解器以及它的配置参数。
同步服务提供允许简单构建同步概况的运行时CLR类。概况可被串行化成XML文件或从XML文件串行化,以便容易存储(常与时间表一起)。然而,在存储平台中没有存储所有概况的标准地方;欢迎SCA在不必永久保持的点上构建概况。注意,不需要具有本地映射来启动同步。能在概况中指定所有同步信息。然而为响应于由远程方启动的同步请求,需要映射。
(3)时间表
在一个实施例中,同步服务不提供它自己的调度基础结构。相反,它依赖于另一组件来完成此任务-在Microsoft Windows操作系统中可得到的WindowsScheduler。同步服务包括命令行实用程序,它担当SCA并基于保存在XML文件中的同步概况触发同步。该实用程序使得按时间表或者响应于如用户登录或登出等事件来配置Windows Scheduler变得非常容易。
d)冲突处理
同步服务中的冲突处理被划分成三个阶段:(1)发生在改变应用时的冲突检测-此步骤判断是否可安全地应用改变;(2)自动冲突分解并记入日志-在此步骤(发生在紧接着冲突检测之后)资讯自动冲突分解器)(或“冲突处理器”),以查看冲突是否能被分解-若不能,可任选地将冲突记入日志;以及(3)冲突检查与分解-若某些冲突已被记入日志,且发生在同步会话之外,则采取此步骤-此时,被记入日志的冲突能被分解并从日志中移除。针对冲突处理的本发明的各实施例将在后文第III节中更详细地讨论。
2.对非存储平台数据存储的同步
按本发明的存储平台的另一方面,存储平台提供ISV用于实现同步适配器的体系结构,同步适配器使存储平台能与如Microsoft Exchange、AD、Hotmail等传统系统同步。同步适配器得益于由下述同步服务提供的许多同步服务。
不管其名称如何,同步适配器不需要作为某个存储平台体系结构的插件来实现。在需要时,“同步适配器”能简单地是利用同步服务运行库接口来获得如改变枚举和应用等服务的任何应用程序。
为了使其他人能更容易地配置和运行到给定后端(backend)的同步,鼓励同步适配器的编写者展现标准同步适配器接口,它在给定上述的同步概况时运行同步。概况提供配置信息给适配器,某些适配器传送到同步运行库以控制运行库服务(如,要同步的文件夹)。
a)同步服务
同步服务向适配器编写者提供若干同步服务。在本节余下部分,方便地将存储平台在其上做同步的机器称为“客户机”,而适配器正与其对话的非存储平台后端称为“服务器”。
(1)改变枚举
基于由同步服务维持的改变跟踪数据,改变枚举允许同步适配器容易地枚举自从最后一次与该伙伴试图作出同步以来对数据存储文件夹发生的改变。
基于“锚位(anchor)”的概念来枚举改变-这是表示有关最后一次同步的信息的不透明的结构。如以前章节所述,锚位采取存储平台知识的形式。利用改变枚举服务的同步适配器落入两大类别:使用“存储的锚位”的适配器和使用“提供的锚位”的适配器。
区别基于关于最后一次同步的信息存储在哪里-在客户机上或在服务器上。适配器常常容易地存储此信息在客户机上-后端往往不能容易地存储此信息。另一方面,若多个客户机与同一后端同步,则将此信息存储在客户机上是低效且在某些情况下是不正确的-这使一个客户机不知道其它客户机已推到服务器的改变。若适配器希望使用服务器存储的锚位,则适配器需要在改变枚举时将其送回到存储平台。
为了让存储平台维护锚位(用于本地或远程存储),存储平台需要知道成功地应用在服务器上的改变。这些且只有这些改变能包括在锚位中。在改变枚举期间,同步适配器使用确认(Acknowledgement)接口,以报告哪个改变已被成功地应用。在同步结束时,使用提供的锚位的适配器必须读出新锚位(它集合所有成功应用的改变)并将其发送到它们的后端。
各适配器常常需要存储适配器专用数据以及插入到存储平台数据存储中的各项目。该数据存储的常见例子是远程ID和远程版本(时间标记)。同步服务提供用于存储此数据的机制,而改变枚举提供接收此额外数据以及要返回的改变的机制。在大多数情况下,这消除了适配器重新查询数据库的需求。
(2)改变应用
改变应用允许同步适配器将从它们的后端接收的改变应用到本地存储平台。期望适配器将改变转换到存储平台模式。图24示出从存储平台模式生成存储平台API类的过程。
改变应用的主要功能是自动检测冲突。如在存储平台到存储平台同步的情况下,冲突被定义成在互相不知道时作出的两个重叠的改变。当适配器使用改变应用时,它们必须指定对其执行冲突检测的锚位。若检测到未被适配器的知识覆盖的重叠的本地改变,则改变应用引起冲突。类似于改变枚举,适配器可使用存储的或提供的锚位。改变应用支持适配器专用元数据的有效存储。那样的数据可由适配器将其附加到要应用的改变上,且可被同步服务存储。数据可在下次改变枚举时返回。
(3)冲突分解
以下在IV中描述的冲突分解机制(包括记入日志和自动分解选项)也对同步适配器可用。在应用改变时,同步适配器能指定用于冲突分解的政策。若指定了,冲突可被传递到指定的冲突处理程序并予以分解(若可能)。冲突也能被记入日志。当试图将本地改变应用到后端时,适配器有可能检测冲突。在那样情况下,适配器仍可以将冲突传递到同步运行库,以按政策分解。此外,同步适配器可请求任何由同步服务检测的冲突发回给它们以便处理。在后端能存储或分解冲突的情况这特别方便。
b)适配器实现
虽然某些“适配器”简单地是利用运行库接口的应用程序,然而鼓励适配器实现标准的适配器接口。这些接口允许同步控制应用程序:请求适配器按给定的同步概况执行同步;取消正进行的同步;以及接收关于正进行同步的进展报告(完成百分比)。
3.安全性
同步服务努力将尽可能少的同步引入到由存储平台实现的安全模式。不是去定义对同步新的权限,而是使用现有的权限。具体地,
·能读数据存储项目的任何人可枚举对那个项目的改变;
·能写到数据存储项目的任何人可应用改变到该项目;以及
·能扩展数据存储项目的任何人可将同步元数据与该项目关联。
同步服务不维护安全授权信息。当在复制品A由用户U作出改变,且将其转发到复制品B时,该改变最初在A处(由U)作出的事实丢失了。若B将此改变转发到复制品C,则这是在B的授权而不是在A的授权下完成的。这就导致下述限制:若不信任一个复制品对一个项目作出它自己的改变,它不能转发由其它复制品作出的改变。
在启动同步服务时,由同步控制应用程序完成。同步服务人格化SCA的身份,并在该身份下完成所有操作(本地的和远程的)。作为说明,观察到用户U不能使本地同步服务从远程存储平台检索对用户U不具有读访问的项目的改变。
4.可管理性
监视复制品的分布式共同体是复杂的问题。同步服务可使用“扫描(sweep)”算法来收集和分发关于该复制品的状态的信息。扫描算法的属性确保关于所有所配置的复制品的信息最终被收集,且检测到该失败(无响应)的复制品。
在每个复制品上可得到共同体范围的监视信息。可在任意选取的复制品上运行监视工具,以检查此监视信息并作出管理决策。在受影响的复制品上必须直接作出配置改变。
B.同步API综述
在越来越多地分布式的、数字的世界中,个体和工作站常常将信息和数据存储在多种不同的设备和位置中。这就推动了数据同步服务的发展,在最小限度的用户干预的情况下,所述数据同步服务可以将所述信息保存在这些单独的、常常完全各不相同的在所有时间上都被同步了的数据存储中。
本发明的同步平台,作为此处的节II(又称,“WinFS”)中所描述的丰富的存储平台的一部分,解决了3个主要任务:
·允许应用和服务有效地同步不同“WinFS”的存储之间的数据。
·允许开发者创建用于同步“WinFS”和非“WinFS”存储之间的数据的富有成果的方法。
·为开发者提供适当的接口以便定制同步用户经历。
1.一般术语
在此,下面是与后面的讨论此处是节III.B有关的一些进一步规定的定义和关键概念:
同步复制品:大多数应用只对跟踪、枚举和同步用于WinFS存储内的项目的给定子集的改变。将参与同步操作的项目的集合称为同步复制品。复制品是用被包含在给定的WinFS包含层内的项目(通常是作为位于文件夹项目上的根)来定义的。所有同步服务都在给定的复制品的环境内实现。WinFS同步提供了规定、管理和清除复制品的机制。各个复制品具有唯一地标识给定WinFS存储内的复制品的GUID标识符。
同步伙伴:同步伙伴被规定为能够影响在WinFS项目、扩展和关系上的改变的实体。因此,各个WinFS存储可以被称为同步伙伴。当与非WinFS存储同步时,外部数据源(EDS)也被称作同步伙伴。各个伙伴具有唯一地标识它的GUID标识符。
同步共同体:同步共同体被规定为复制品的集合,采用对等同步操作的方式,同步地保存所述复制品的集合。这些复制品可以全部都是位于相同的WinFS存储、不同的WinFS存储中,或者甚至将它们清楚表示为非WinFS存储上的虚拟复制品。特别地如果共同体中只有同步操作是通过WinFS同步服务(WinFS适配器)的,则WinFS同步并不指定或委托用于所述共同体的任何专用拓扑。同步适配器(下面规定的)可以引入其自己的拓扑约束。
改变跟踪、改变单元和版本:各个WinFS存储跟踪对所有本地WinFS项目、扩展和关系的改变。在所述模式中所规定的改变单位粒度(granularity)的等级上,跟踪改变。采用作为一个顶级字段的最小粒度,任何项目、扩展和关系类型的顶级字段可以由模式设计者子划分为改变单元。为了改变跟踪的目的,每个改变单元被分配一个版本,其中版本是一对同步伙伴Id和版本号(所述版本号是伙伴专用的单调增加的数字)。按照本地发生在所述存储中的或者按照它们从其它复制品中获得的改变,更新版本。
同步知识:知识表示在任意时间给出同步复制品的状态,即它封装与给定的复制品本地知道的或者是从其它复制品中知道的所有改变有关的元数据。WinFS同步保存并且更新用于跨同步操作的同步复制品的知识。要注意的重要的事情是,知识表示允许它相对整个共同体进行解释而不是只相对于与知识被存储的特定复制品进行解释。
同步适配器:同步适配器是受管理的编码应用,它通过同步例程API访问WinFS同步服务,并且使WinFS数据与非WinFS数据存储同步。依赖于情况的需要,关于WinFS数据的哪个子集和什么WinFS数据类型进行同步,取决于适配器开发者。所述适配器负责与EDS进行通信、向和从支持模式的EDS传送WinFS模式、以及规定并管理其自己的配置和元数据。强烈鼓励适配器实现WinFS同步适配器,以便具有普通配置和控制用于由WinFS同步组所提供的适配器的底层结构的优点。对于更多的细节,请参见WinFS同步适配器API专刊[SADP]和WinFS同步控制器API[SCTRL]专刊。
对于使WinFS数据与外部的非WinFS存储同步并且不能以WinFS格式产生或保存知识的适配器,WinFS同步提供了保存远程知识的服务,所述远程知识能够被用于后来的改变枚举或应用操作。依赖于后端存储的能力,所述适配器可以希望在所述后端上或者在本地WinFS存储上存储这种远程知识。
为简单起见,同步“复制品”是一种结构,它表示“WinFS”存储中存在于单个本地位置中的一组数据,然而,非WinFS存储上的数据被称作“数据源”,并且一般要求使用适配器。
远程知识:当给定的同步复制品希望获得来自另一个复制品的改变时,它提供其自己的知识作为一种基线,根据基线,其它复制品枚举改变。类似地,当给定的复制品希望将改变发送给另一个复制品时,它提供其自己的知识作为基线,所述基线可以由远程复制品用于检测冲突。在同步改变枚举和应用期间提供的与其它复制品有关的这种知识被称为远程知识。
2.同步API主体
对于某些实施例,所述同步API分割成两部分:同步配置API和同步控制器API。同步配置API允许应用配置同步,并且指定参数用于两个复制品之间的特定同步会话。对于给定的同步会话,配置参数包括将被同步的项目的集合、同步的类型(单向或双向)、与远程数据源有关的信息、以及冲突分解策略。同步控制器API启动同步会话,取消同步,以及接收处理和与正在进行的同步有关的错误信息。还有,对于特定的实施例,其中同步需要根据预定的调度执行,这种系统可以包括调度定制调度表的机制。
本发明的多个实施例使用同步适配器以便同步“WinFS”和非“WinFS”数据源之间的信息。适配器的例子包括同步“WinFS”冲突文件夹和非WinFS邮箱之间的地址簿信息的适配器。在这些情况下,为了开发“WinFS”模式和非“WinFS”数据源模式之间的模式转换编码,适配器开发者可以使用此处所描述的“WinFS”同步核心服务API以便访问由“WinFS”同步平台所提供的服务。此外,适配器开发者提供了用于将改变与非“WinFS”数据源进行通信的协议支持。通过使用同步控制器API调用并控制同步适配器,并且使用这种API报告进度和错误。
然而,对于本发明的某些实施例,当“WinFS”数据存储与另一个“WinFS”数据存储同步时,如果“WinFS”对“WinFS”同步服务被集成在硬件/软件接口系统内,则同步适配器可以不是必需的。在任何情况下,多个这样的实施例提供了用于“WinFS”对“WinFS”以及同步适配器方法两者的一组同步服务,所述同步适配器方法包括:
·对“WinFS”项目、扩展和关系的改变的跟踪。
·用于自给定的过去的状态开始的有效递增的改变枚举的支持。
·对“WinFS”的外部改变的应用。
·在改变应用期间的冲突处理。
参见图36,示出了普通数据存储和用于同步它们的组件的3个实例。第一系统3602具有WinFS数据存储3612,所述WinFS数据存储3612包括WinFS对WinFS同步服务3622和核心同步服务3624,用于WinFS对非WinFS同步,它公开了3646用于使用的同步API 3652。类似于第一系统3602,第二系统3604具有WinFS数据存储3614,所述WinFS数据存储3614包括WinFS对WinFS同步服务3632和核心同步服务3634,用于WinFS对非WinFS同步,它公开了3646用于使用的同步API 3652。第一系统3602和第二系统3604通过其各自的WinFS对WinFS同步服务3622和3632进行同步3642。第三系统3606,不是WinFS系统,它具有用于使用WinFS同步3666将数据源保存在具有WinFS复制品的同步共同体中的应用。这种应用可以使用WinFS同步配置/控制服务3664,以便通过WinFS对WinFS同步服务3622(如果它能将自身虚拟化为WinFS数据存储),或者通过提供与同步API 3652的接口3648的同步适配器3662,直接提供与WinFS数据存储3612的接口3644。
如在此图中所示的,第一系统3602知道并且直接同步第二系统3604和第三系统3606。然而,第二系统3604和第三系统3606彼此并不知道,并且因此,并不直接彼此同步它们的改变,但是,相反,一个系统上发生的改变必须通过第一系统3602传播。
C.同步API服务
本发明的多个实施例被指向同步服务,所述同步服务包括两个基础服务:改变枚举和改变应用。
1.改变枚举
如此处较早之前讨论的,改变枚举允许同步适配器很容易地枚举改变,所述改变是,自基于由同步服务所保存的改变跟踪数据,企图与这个伙伴的同步的最后时刻开始的数据存储文件夹上已经发生的改变。就改变枚举而言,针对本发明的多个实施例:
对给定复制品中与被指定的知识实例有关的项目、扩展和关系的改变的有效枚举。
·在被指定于WinFS模式中的改变单元粒度的等级上的改变的枚举
·依据复合项目的被枚举的改变的组。复合项目包括项目、所有其扩展、与所述项目的所有保持关系、以及对应于其被嵌入的项目的所有复合项目。引用项目之间的关系的改变可以被分别枚举。
·与改变枚举有关的分类。所述分类的粒度是复合项目或者关系改变(用于引用关系)。
·在改变枚举期间对复制品中的项目的过滤的指定,例如所述复制品包括给定文件夹中的所有项目,但是对于这种特殊的改变枚举,所述应用愿意只枚举对所有联系项目的改变,其中第一名称以“A”开始(这种支持将被添加至B-里程碑)。
·用于被枚举的改变的远程知识的使用,具有将个别改变单元(或者整个项目、扩展或关系)记录为在知识上同步失败的能力,以便下一次重新枚举时具有它们。
·改进的适配器的使用,所述改进的适配器也许能够通过在改变枚举期间随着改变一起返回元数据,了解WinFS同步元数据。
2.改变应用
如此处较早所讨论的,改变应用允许同步适配器将从它们的后端接收到的改变应用到本地存储平台,因为希望所述适配器将所述改变转换成存储平台模式。就改变应用而言,本发明的多个实施例被指导:
·具有对应于WinFS改变元数据的更新的来自其它复制品(或非WinFS存储)中的递增的改变的应用。
·在改变单元粒度上的与改变应用有关的冲突检测。
·在改变应用上的个别改变单元级上成功、失败以及冲突的报告,以便应用(包括适配器和同步控制应用)可以使用要处理的那些信息、错误和状态报告,并且用于更新它们的后端状态,如果有的话。
·在改变应用期间远程知识的更新,以便防止在下一个改变枚举操作期间被提供改变的应用的“冲突”。
·改进的适配器的使用,所述改进的适配器可以随着改变一起了解并提供WinFS同步元数据。
3.示例代码
下面是用于FOO同步适配器如何可以与同步例程进行交互的编码示例(其中采用FOO作为所有适配器的专用函数的前缀):
ItemContext ctx=new ItemContext(“\.\System\UserData\dshah\My
Contacts”,true);
//从概况获得复制品项目id和远程伙伴id
//大多数适配器从同步概况获得此信息
Guid replicaItemId=FOO_GetReplicaId();
Guid remotePartnerId=FOO_Get_RemotePartnerId();
//
//使用如上所述的storedKnowledgeId查找存储中所储存的知识.
//
ReplicaKnowledge remoteKnowledge=...;
//
//初始化ReplicaSynchronizer
//
ctx.ReplicaSynchronizer=new ReplicaSynchronizer(replicaItemId,
remotePartnerId);
ctx.ReplicaSynchronizer.RemoteKnowledge=remoteKnowledge;
ChangeReader reader=ctx.ReplicaSynchronizer.GetChangeReader();
//
//枚举改变并处理它们
//
bool bChangesToRead=true;
while(bChangesToRead)
{
ChangeCollection<obj ect>changes=null;
bChangesToRead=reader.ReadChanges(10,out changes);
foreach(object change in changes)
{
//处理所枚举的对象,适配器完成其自己的模式转换以及ID
映射
//它甚至可为此目的从Ctx检索附加对象,
//并在向远程存储应用改变之后修改适配器元数据
//
ChangeStatus status=
FOOProcessAndApplyToRemoteStore(change);
//用状态更新获知的知识
reader.AcknowledgeChange(changeStatus);
}
}
remoteKnowledge=
ctx.ReplicaSynchronizer.GetUpdatedRemoteKnowledge();
reader.Close();
//
//保存更新的知识和适配器元数据(如果有的话)
//
ctx.Update();
//
//改变应用的示例,首先使用如上所述的storedKnowledgeId
//初始化远程知识
//
remoteKnowledge=...;
ctx.ReplicaSynchronizer.ConflictPolicy=conflictPolicy;
ctx.ReplicaSynchronizer.RemotePartnerId=remotePartnerId;
ctx.ReplicaSynchronizer.RemoteKnowledge=remoteKnowledge;
ctx.ReplicaSynchronizer.ChangeStatusEvent+=
FOO_OnChangeStatusEvent;
//
//从远程存储获得改变。适配器负责从存储检索其后端专用元数据。
//这可以是在复制品上的扩展
//
//
object remoteAnchor=FOO_GetRemoteAnchorFromStore();
FOO_RemoteChangeCollection remoteChanges=
FOO_GetRemoteChanges(remoteAnchor);
//
//填充改变集合
//
foreach(FOO_RemoteChange change in remoteChanges)
{
//适配器负责完成ID映射
Guid localId=FOO_MapRemoteId(change);
//可以认为正在同步个人对象
ItemSearcher searcher=Person.GetSearcher(ctx);
searcher.Filters.Add(“PersonId=@localId”);
searcher.Parameters[“PersonId”]=localId;
Person person=searcher.FindOne();
//
//适配器将远程改变转换成对个人对象的修改
//作为其一部分,适配器甚至可对远程对象的
//项目级后端专用元数据作出改变。
//
FOO_TransformRemoteToLocal(remoteChange,person);
}
ctx.Update();
//
//保存新的锚位(这可以是复制品的扩展)
//
FOO_SaveRemoteAnchor();
//
//这是自从远程知识未同步以来常规的WinFS API保存
//
remoteKnowledge=
ctx.ReplicaSynchronizer.GetUpdatedRemoteKnowledge();
ctx.Update();
ctx.Close();
//
//适配器回叫以处理应用程序状态回叫
//
void FOO_OnEntitySaved(object sender,ChangeStatusEventArgs args)
{
remoteAnchor.AcceptChange(args.ChangeStatus);
}
4.API同步的方法
在本发明的一个实施例中,通过由基于WinFS的硬件/软件接口系统所公开的同步API,可以实现WinFS存储和非WinFS存储之间的同步。
在一个实施例中,要求所有同步适配器实现同步适配器API、由API管理的公共语言运行库(CLR),以便它们可以被一致使用、启动和控制。所述适配器API提供:
·用于随着硬件/软件接口系统同步框架的寄存适配器的标准机制。
·用于适配器表示它们的性能和启动所述适配器所需的配置信息的类型的标准机制。
·用于将启动信息传递给所述适配器的标准机制。
·用于适配器将过程状态报告回调用应用的应用的机制。
·报告在同步期间发生的任何错误的机制。
·请求正在进行的同步操作的取消的机制。
根据情况的需要,存在两种可能的用于适配器的处理模型。所述适配器可以在与调用应用的应用相同的处理空间中或者全部在它本身单独的处理中执行。为了在其自己单独的处理中执行,所述适配器规定了其自己的工厂(factory)类,所述工厂类被用于例示所述适配器。所述工厂可以在与调用应用相同的处理中返回所述适配器的实例,或者在不同的Microsoft公共语言例程应用范围或处理中返回所述适配器的远程实例。默认的工厂实现被提供有在相同处理中哪个例示所述适配器。实际上,许多适配器将在与调用应用相同的处理中运行。出于以下原因中的一个或两个,通常要求有处理模型的输出:
·安全目的。所述适配器必须在某个处理或服务的过程空间中运行。
·所述适配器必须处理来自其它源的请求--例如,收入网络请求--除了处理来自调用应用的请求之外。
参见图37,本发明的一个实施例假设了一个简单的适配器,它不知道如何计算状态或者如何交换其相关元数据。在这个实施例中,就想要同步的数据源而言,首先,在步骤3702,确定自它与所述数据源最后同步开始哪些改变已经发生,通过所述复制品实现同步,并且然后所述复制品基于其当前状态信息传输自这个最后的同步开始已经发生的递增的改变,并且这种当前状态信息和递增的改变通过所述适配器传输给所述数据源。在步骤3704,所述适配器,一旦在之前步骤中接收到来自所述复制品的改变,就尽可能多地实现对数据源的改变,跟踪哪些改变成功了并且哪些失败了,并且将所述成功和失败信息传输回(所述复制品的)WinFS。在步骤3706,所述复制品(WinFS)的硬件/软件接口系统一旦从所述复制品中接收到成功和失败信息,就为所述数据源计算新的状态信息,存储这种信息以供将来由其复制品使用,并且将这种新的状态传输回所述数据源,也就是,传输给用于存储的适配器并且以后由所述适配器使用。
D.同步层次
如此处较早所讨论的,根据每一个这种被分配对应的递增的顺序的改变号(即,第一个改变是1,第二个改变是2,第三个改变是3,等等依此类推),每个复制品保存其改变的递增的并且顺序的枚举。还有,每个复制品还保存用于用于其同步共同体中的其它已知复制品(同步伙伴)的状态信息,以便跟踪它已经从这些其它复制品中接收了哪些改变。通过知道应用给来自第二个复制品的第一个复制品的最后的改变的改变号,然后第一复制品可以使用这个编号来只对大于这个最后被应用的改变的编号的那些改变进行请求、接收、或者处理。图38A-D示出了如何使用这种顺序的改变枚举方法来跟踪、枚举、以及同步改变。
在图38A中,同步伙伴A和B公共同步共同体中的复制品,并且以其父状态示出,因为还没有进行改变,所以对于各个复制品,所述父状态等于改变号0--例如对于各个复制品分别为A0和B0。(在这个实施例中,使用唯一的改变号反映初始状态。)各个复制品知道其自己的状态并且跟踪其同步伙伴的状态,在如此处所示的它的“向量”(如所示,向量列出了复制品自己的状态,第一个后面是其伙伴的每一个的最后的已知状态,基于最后的同步或者在这种情况下的启动,)中,各个复制品反映这种信息。用于复制品A的初始向量是“[A0,B0]”,并且用于复制品B的初始向量是“[B0,A0]”,并且两个复制品目前是完全同步的。
在图38B中,复制品A进行改变并且为那个改变分配唯一的递增的改变号A1(该改变号包括用于复制品本身的唯一标识“A”,以及用于在那个复制品上的改变的唯一的递增的号码“1”)。另一方面,复制品B进行2个改变,并且为那些改变分别分配唯一的递增的改变号B1和B2。在这一点上,并且在下一次同步之前,所述复制品现在没有同步,并且用于复制品A的向量现在是[A1,B0],且用于复制品B的向量是[B2,A0](再者,该向量反映了已知的最后改变。)
在图38C中,通过向复制品B发送其当前向量以便请求改变,复制品A与复制品B同步(步骤1)。一接收到复制品A的向量,复制品B就计算它需要发送给复制品A的两个改变B1和B2,并且因此继续这么做(步骤2)。复制品A接收被标识为B1和B2的复制品B的改变(也就是,改变单元),应用它们,并且将其自己的向量更新为[A1,B2](步骤3)。
在如图38D中所示的可替换实施例中,随着计算并向复制品A发送正确的改变(步骤2),复制品B还基于复制品A的向量确定已经对复制品A进行了改变而尚未对复制品B进行改变,并且因此复制品B还将其自己的向量以及用于改变的请求发送给复制品A(步骤2’)。然后,当复制品A接收到复制品B的改变时,应用它们,并且将其自己的向量为[A1,B2](在步骤3期间),它还计算其哪个改变要发送给复制品B并且同样传输它们(步骤3’)。一旦接收到这个信息,复制品B就进行所述改变并且将它的向量更新为[B2,A1](步骤4)。
关于之前所述的例子,可能在许多情况下会引发冲突。例如,A1和B2也许已经对相同的改变单元进行了改变,或者A1会对B2正在修正的相同的改变单元进行删除。虽然使用此处较早所讨论的冲突分解选项可以分解这些冲突中的一些,但是某些冲突提供了显著不同的难题,并且在此下面根据当前的例子讨论这些难题及其分解方法。
1.同步早先的“范围外”的改变
在本发明的某些实施例中,复制品的范围可以不是静态的。因此,采用在位于复制品A的范围内的项目和不在其范围内的项目之间创建新的关系的改变,复制品A可以有效地增加其范围。然而,假设用于范围外的项目的改变单元尚未被同步于复制品A和B之间(因为它已经位于用于这些复制品的同步范围之外),就用于特定项目的版本路径而言,可能会造成同步不一致。解决这个问题的方法是随着创建复制品A中范围内的项目和范围外的项目之间的关系的特定改变,对于复制品A向复制品B发送已经对范围外的项目进行了的所有改变。
2.同步父-子无序化
在本发明的某些实施例中,对于同步而言,父项目总是在子项目之间被发送(例如,如果作为孩子的项目K被嵌入在作为父亲的项目J中,则项目K不能在传输项目J之前被传输),这是一般的原理。然而,对于复制品A而言,这是可能的,在同步之间,项目J和K被改变,但是其中孩子项目K具有比孩子项目J小的分类号(基于,例如,其标识号的顺序的优先地位),并且因此一般会被首先传输。在本发明的各个实施例中,用于解决同步的问题的一种方法是,将所述改变分成两组,一组只反映对项目K进行的改变,而第二组只反映对项目J进行的改变,并且以恰当的顺序发送它们(也就是,在发送了用于父项目J的改变的组之后,发送用于子项目K的改变的组)。
3.墓碑传播
如在此较早所讨论的,出于同步的目的,墓碑被用于标记已经被删除的改变单元。然而,由于对于同步共同体中的多个向量而言同步是非同步的,所以这些墓碑可以在整个数据平台上传播。问题是,在没有说明墓碑传播的情况下,复制品A可以创建一个项目,并且在与复制品B同步期间,将那个项目发送给复制品B。然后,复制品A可以删除所述项目,并且在与复制品C同步期间,它不发送与所述项目有关的任何信息,因为没有要发送的信息(因为所述项目被删除了)。接着,当复制品B和复制品C试图同步时,复制品C可以从复制品B中接收所述项目,并且在B上持续。
对于本发明的各个实施例而言,解决这个问题的方法是,对于复制品A采用墓碑标记被删除的项目。接着,当复制品A删除所述项目时,在与复制品C同步期间,它将所述墓碑发送给复制品B。当复制品B和复制品C接着试图同步时,复制品B同样接收所述墓碑,并且所述项目现在完全从所述同步共同体中被删去了。
4.根墓碑传播
在P1中,如果项目X具有多个被嵌入项目A、B、C、D和E,那么当P1首先删除这些子项目并且其次删除同步之间的父项目X时(即,删除A、删除B、删除C、删除D、删除E和删除X,作为6个改变),引发一种有意思的情况,因为相同的最终结果可能已经发生,P1已经简单地删除了父亲X(1个改变),在这种情况下,被嵌入的项目可能也会被自动地删除。在这方面,本发明的多个实施例,一旦同步,就通过确认删除X可能事实上与6个单独的删除事件是等效的,获得功效,并且因此P1可能只向P2发送对应于X的删除的改变单元,并且允许这种删除,以便自然地传播给P2中的X的被嵌入的项目。
5.关系名称交换
如之前所讨论的,关系具有名称,并且因此对于一个复制品(P1)可以通过使用临时名称元素(X)来交换用于两个关系(R1和R2)的名称--也就是,R1的名称被复制给X,R2的名称接着被复制给R1,接着X被复制给R2,并且最后删除X。然而,因为伙伴复制品(P2)不知道临时名称元素X,所以在同步期间将会造成错误,因为确认R1具有新名称,P2试图改变这个名称,导致错误地为R1和R2使用相同的名称。对于本发明的各个实施例,解决这个问题的一种方法是,一旦接收到或者确认这种相同名称错误,就假设一种可行的名称交换情况,并且自动地创建其自己的临时名称元素(X),并且如果连续的改变的确解决了将R2重命名为X中的名称,那么它就完成了这种交换(否则,它产生所述情况作为常规冲突事件)。
6.引用关系
对于复制品P1(在WinFS系统上运行)和数据源P2(在非WinFS系统上运行)之间的同步,引发一个问题,在摇摆关系(被WinFS支持)情况中,不被非WinFS系统支持。当两个项目A和B具有在P1上的关系R,并且P1以A(P1-21)然后R(作为改变单元P1-22)然后B(作为改变单元P1-23)的顺序创建它们时,会引发这个问题。当创建R(P1-22)时,R是摇摆关系,所以当P2顺序地应用这些改变时,会导致不允许的摇摆关系错误。对于本发明的多个实施例而言,解决这个问题的方法是,改为重新排序所述改变,以便在所有其它改变从P1被发送到P2之后,可以发送所有的引用关系(例如,R),并且因此,通过首先创建项目A和B并且然后采用R将它们彼此相关,共同避免了这个问题。
E.同步-冲突处理
如在此较早所提及的,同步服务中的冲突处理被划分为3个阶段:(1)冲突检测,发生在改变应用的时候--这个步骤确定改变是否已经被安全地应用;(2)自动的冲突分解和记录--在这个步骤期间(检测到冲突之后立刻进行)考虑自动的冲突处理器以便明白所述冲突是否已经被分解--如果没有,则可以可选择地记录所述冲突;以及(3)冲突检查和分解--如果一些冲突已经被记录则进行这个步骤,并且发生在同步会话的环境之外--此时,被记录的冲突可以被分解并从所述记录中删除。
本发明的各个实施例尤其被指向对发生在对等同步系统(例如,用于在此以上所述的同步系统)中的冲突的冲突处理。准确地并且有效地处理冲突的能力最小化数据丢失,而保留了好的使用性,并且减少了在同步期间对用户干预的需要。本发明的多个实施例被指向冲突处理模式,包括以下冲突处理元素中的一个或多个:(a)冲突的模式化表示;(b)冲突的检测;(c)冲突向永久存储中的记录;(d)按照灵活的并且可配置的冲突分解策略的冲突的自动分解;(e)可包括且可扩展到过滤器并分解冲突的冲突处理器;(f)自动检测和已废弃冲突的移除;以及(g)有计划的冲突分解。还有,脱开冲突处理模式,这些冲突处理元素中的每一个本身都是本发明的有代表性的附加实施例。
1.冲突类型
通常,无论何时不能在同步操作期间同步数据(“改变应用失败”),就会引起冲突。这些失败可以是因为许多原因而造成的,尽管一般冲突可以被划分为两类:约束冲突和知识冲突。
a)基于知识的冲突
当两个复制品对同一改变单元进行独立的改变时,会造成基于知识的冲突。如果两个改变是在彼此没有知识的情况下进行的,则这两个改变被称作为是独立的--换言之,第一个的版本没有被第二个的知识覆盖,反之亦然。基于如以上所述的复制品的知识,所述同步服务自动地检测所有的这种冲突,并且处理这些冲突,在此如下面所述。一些特定类型的知识冲突包括更新-删除、删除-更新以及更新-更新冲突(其中每个名称是指依次是本地动作和远程动作;例如,更新-删除冲突是由于对同一数据的本地更新和远程删除)。
有时,将冲突认为是改变单元的版本历史中的分叉是有帮助的。如果在改变单元的生命中没有冲突发生,则其版本历史就是一个简单的链--每个改变都在之前的一个后面发生。在基于知识的冲突的情况中,两个改变并行发生,使得所述链分裂并且变成版本树。
总体上,知识冲突按照知识和版本处理的结果发生。当应用具有与被存储在数据库中的信息相冲突的版本的改变时,由WinFS同步创建知识。所述冲突需要包括冲突改变信息,以及版本信息。大多数对知识冲突的要求也是对约束冲突的要求。然而,在同步版本和知识的基础上,知识冲突可以被单独地检测。
b)基于约束的冲突
存在一些情况,在这些情况下,当一起被应用时,独立的改变妨碍了完整性约束。例如,在相同目录中创建具有相同名称的文件的两个复制品会使得这样的冲突发生,其中系统中的约束(例如,文件夹中唯一的项目名称的施加)导致了这种类型的基于约束的冲突。
一般地,基于约束的冲突包括两个独立的改变,正如用于基于知识的冲突;然而,基于约束的冲突包括不影响相同改变单元但相反影响不同改变单元的在它们之间存在约束的改变。基于约束的冲突可以从单个改变中引发,例如当两个不同类型的类型之间同步其中一个具有约束而另一个没有时。例如,如果一个系统具有最大文件名长度是八个(8个)字符长的约束,并且如果那个系统接收到来自另一个不具有这种约束的对文件的改变,其中所述改变是针对文件名使得文件名比8个字符长更长,就导致了约束冲突(从一个单个机器中的单个改变中发生)
特殊类型的约束冲突包括但并不限于:
·插入-插入冲突:当两个同步伙伴的每一个都创建具有相同逻辑标识符的对象例如具有相同名称的文件时发生。
·无父冲突:当要创建的引入对象的父亲不存在时发生。一个例子是当在文件的父文件夹之前接收一个文件时。
·未规定类型的冲突:当引入对象的模式没有被示出从而防止创建所述对象时发生。
总之,约束冲突是通过由于各种原因应用改变的错误引发的。如果采用最终导致减小的分解方法的形式,能够有针对性地被处理,或者如果它们能够被记录以用于最终通过用户交互分解,则这种错误被称为约束冲突。不能被有针对性地处理而是被报告的错误简称为改变应用错误。对于某些实施例,所有改变应用错误都被看作是错误--也就是,没有被承认的约束冲突。而对于某些实施例,由于期望在下一次接收同步时表示知识冲突,所以在发送同步期间发生的所有冲突可以被忽略。(导致没有减小的其它错误也可以被忽略。)
2.冲突检测
所述同步服务在改变应用时检测约束违规,并且自动地引发基于约束的冲突。分解基于约束的冲突通常要求自定义码采用与没有违反所述约束的方式修正所述改变,并且同步服务可以或可以不提供用于这么做的通用机制。
对于本发明的各个实施例,通过检验本地知识是否知道远程版本并且反之亦然,每个改变单元检测冲突。对于基于知识的冲突,在此有4种冲突检测情形:
1.知道远程版本的本地知识,知道本地版本的远程知识:这意味着引入的改变是已废弃的,并且因此进行被丢弃。
2.不知道远程版本的本地知识,知道本地版本的远程知识:这意味着引入的改变比本地版本更新,并且因此接受。
3.知道远程版本的本地知识,知道本地版本的远程知识。这可能只发生在如果两个版本等效的时候,并且因此没有改变被应用。
4.不知道远程版本的本地知识,不知道本地版本的远程知识。这意味着本地和远程版本相冲突,并且因此引发冲突。
3.冲突处理
冲突可能发生在发送或者接收同步期间;然而,如果在单向同步操作中两个伙伴类似(例如,在WinFS存储中两者被类似地配置),则情况是相对称的,并且通过自动分解所述同步上的冲突或者记录所述冲突以供异步分解(自动或人工),在接收端,是最容易被处理的。
当然,存在发送伙伴可能需要处理例如在WinFS对非WinFS同步中的冲突的情况。在这种情况下,在顺序的接收同步中,约束冲突可能不会传播回所述发送伙伴。还有,接收伙伴可能不具有冲突记录,或者可能需要使用发送者的冲突记录以易于管理。在这种情况下,改变可能会被一起拒绝,以便迫使发送这分解所述冲突(此处下面进行讨论)。
同步启动器配置其同步概况中的冲突分解。所述同步服务支持在单个概况中联合多个冲突处理器。因为冲突处理机制是可扩展的,所以存在多种方式联合多个冲突处理器。一种特定的方法包括指定冲突处理器的列表一个接一个地进行尝试,直到其中一个成功为止(此处如下面所述)。另一种方法包括将冲突处理器与冲突类型相关联,例如,将更新-更新基于知识的冲突指向一个冲突处理器,而将所有其它冲突指向记录。
当检测到冲突时,同步服务可以采取3个动作中的一个(由同步概况中的同步启动器选择):(1)拒绝改变;(2)自动分解冲突;或者(3)将冲突记录到冲突记录中。
a)拒绝改变
如果拒绝改变,那么如果改变没有到达所述复制品并且否定的应答被发送回启动器,则同步服务起作用。这种分解策略简单地用在没有标题的复制品(例如文件服务器)上,其中记录冲突是不可行的。相反,这种复制品向其它的复制品通过拒绝处理所述冲突。
b)自动冲突分解
自动冲突分解是按照所指定的策略分解同步上的冲突的过程。在WinFS同步操作中,可以独立地指定策略,以便发送操作和接收操作。自动冲突分解策略可以通过同步概况来指定。所引发的冲突被传递给所述概况中指定的顶级冲突处理器。这种冲突处理器可以分解所述冲突、记录它、或者将所述冲突传递给另一个冲突处理器,以便进一步随着冲突处理流水线进行处理。
图39A示出了用于本发明的多个实施例的冲突处理流水线。在此图中,当冲突发生时,冲突处理器列表(或者“列表”)3910接收冲突项目3902,并且在所述流水线的第一路径上将所述冲突传递给第一处理器3912,在这种情况下,第一处理器是过滤器。所述过滤器3912是监视定时器(watchdog),它估计所述冲突3902,并且让它传递给下一个处理器3914或者拒绝回所述列表3910,然后,列表3910将它传递回列表3912,依次,将它传递回位于所述流水线上的下一个路径的第一处理器3922。如果由第一过滤器3912将所述冲突3902传递给第二处理器3914,在这种情况下,是分解器,那么如果可能的话所述冲突被分解器3914分解,或者如果不可能,则将所述冲突拒绝回第一处理器3922。接着,所述冲突继续通过流水线进行处理,直到(a)由流水线中的处理器中的一个分解了为止,(b)通过特定的冲突处理器熟称“记录器”明确地记录到冲突记录上,所述记录器例如记录器3936(也就是,如果冲突使它传递给过滤器3934)为止,或者(c)完全被传递回流水线外部,并且默认地被发送回冲突记录(用虚线逻辑地示为记录器3944)。
图39B是示出了图39A中所示的流水线的逻辑移动的流程图。在图39B中,并且还参照图39A,在步骤3950,冲突3902进入冲突处理器列表3910上的流水线,并且在步骤3952被初始发送给过滤器3912。如果在步骤3954,冲突3902传递给此过滤器3912,那么在步骤3956所述冲突3902进行到分解器3914,在步骤3958,所述分解器3914试图分解所述冲突3902。如果成功,则在步骤3998,处理返回;否则,在步骤3960冲突进行到分解器3922,在步骤3962,分解器3922试图分解冲突3902。如果成功,在步骤3998,处理返回;否则,在步骤3964,冲突进行到列表3932,并且在步骤3966,从这里到过滤器3934,并且如果在步骤3968,冲突传递给此过滤器3934,在步骤3972,那么在步骤3970,由记录器3936将冲突记录到冲突记录(未示出)中,并且,在步骤3998,处理返回;否则在步骤3972,冲突3902被发送给过滤器3938,并且如果在步骤3974冲突3902传递给此过滤器3938,那么在步骤3976,冲突3902进行到分解器3940,在步骤3982,分解器试图分解冲突3902。如果成功,在步骤3998,处理返回;否则,在步骤3984,由分解器3936将冲突3902记录到冲突记录(未示出)中,并且在步骤3998,处理返回。
尽管在图39A和39B中没有示出,但是应当注意,连续的冲突分解器的路径也可以构造,其中,如果冲突不可能被一个分解器分解,则将冲突传递给下一个分解器,然后力图分解所述冲突,等等,依此类推。如果冲突持续未被分解恰好在路径的结尾处,那么沿着所述路径将冲突传递回列表,以便继续下一条路径。类似地,一旦用于列表的所有路径都已用尽,并且冲突仍未分解,那么列表沿着其路径传递冲突,直到它到达下一个列表,等等,依此类推。
也很重要的是注意,流水线不必以列表开始;相反,它可以以任何类型的冲突处理器诸如,例如过滤器开始。然而,无论如何,如果沿着路径将冲突传递回流水线中的第一冲突处理器,并且那个冲突处理器没有另外的路径用以尝试(可能只是用于冲突处理器列表的情况,其中所有路径都没有尝试),那么冲突传递到流水线的外部,并且自动地并且默认地被记录到冲突记录。
ConflictHandler类型是用于冲突处理器的基本类型,包括冲突处理器列表、冲突记录、以及冲突过滤器、以及其它类型的冲突处理器。此外,所述同步服务也可以提供许多默认的冲突处理器,包括但并不限于:
·本地优胜:通过选择本地存储的数据作为对引入数据的优胜者,分解冲突
·远程优胜:通过选择引入数据作为对本地存储的数据的优胜者,分解冲突;
·最后写入者优胜:基于改变单元的时间戳,挑选本地优胜者或者远程优胜者(注意,通常同步服务不依赖于时间值;这种冲突分解器对于那个规则是惟一例外);
·确定性的:以保证在所有复制品上相同的方式,挑选优胜者,但不是另外的有意义的--同步服务的一个实施例可能使用伙伴ID的字典编辑上的对照来实现这个特征。
例如,冲突处理器可以规定,对于更新-删除冲突,应当应用本地优胜者分解方法,而对于所有其它冲突,应当应用最后写入者优胜者分解方法,如下:
<conflictHandlerList
xmlns=”http://schemas.microsoft.com/winfs.2003/10/conflicts”>
<conflictFilter
xmlns=”http://schemas.microsoft.com/winfs.2003/10/conflicts”>
<conflictType>UpdateDeleteConflict</conflictType>
<conflictResolver><ResolutionType>LocalWins</ResolutionType></conflictRes
olver>
</conflictFilter>
<conflictResolver><ResolutionType>LastWriterWins</ResolutionType></confli
ctResolver>
</conflictHandlerList>
当然,如果没有指定冲突处理器,或者如果没有通过任何被指定的冲突处理器处理冲突,那么冲突就被放置在冲突记录中。对于某些实施例,冲突记录也是冲突处理器。
对于本发明的各个实施例,ISV可以实现并且建立其自己的冲突处理器。客户冲突处理器可以接受配置参数,尽管这种参数必须由同步概况的冲突分解部分中的SCA来指定。
当冲突分解器处理冲突时,它将需要执行的操作的列表(代替冲突改变)返回给所述例程。然后,所述同步服务应用这些操作,适当地调整远程知识,以便包括冲突处理器已经考虑过的信息。
可能在应用所述方法的同时检测到了另一个冲突。在这种情况下,在重新进行初始处理之前,新的冲突必须被分解或被记录。
当将冲突看作项目的版本历史中的分支时,冲突分解可以被看作接点--联合两个分支以便形成单独的点。因此,冲突分解将版本历史成为有向无回路图形(DAG)。
c)冲突日志记录
虽然被报告的冲突可以使用自动冲突分解来同步地分解,但是其它的冲突可能被记录日志以供以后有计划的分解。冲突日志记录允许冲突分解处理同步地进行--也就是,冲突不必在它们被删除的时候才能分解,而是可以被记录日志以供将来分解。例如,冲突观察器应用可以允许用户检查并且在是事实之后人工地分解被记录日志的冲突。
对于本发明的多个实施例,非常特殊的类型的冲突处理器是冲突日志记录器(或者,更简单地,“日志记录器”)。所述同步服务将冲突记录在冲突日志中作为类型ConflictRecord的项目(或者,在替换实施例中,简单地作为类型Conflict)。这些日志返回来与冲突中的项目有关(除非所述项目本身已经被删除)。对于某些实施例,各个冲突日志包含:引发冲突的引入改变;冲突的类型(例如,更新-更新、更新-删除、删除-更新、插入-插入,或者约束);以及引入改变的版本和发送它的复制品的知识。对于本发明的某些可替换实施例,每一个这种冲突项目都包含冲突改变数据和元数据、冲突的说明以及其它环境信息例如改变应用器信息、建立数据、以及远程伙伴名称。此外,以不能被用于应用所述改变的方式,存储所述改变数据。还有,对于本发明的各个实施例,从冲突中派生出的各个类型可以添加与那个类型的冲突有关的新的字段。例如,InsertInsertConflict添加引起违反唯一性约束的项目的项目ID。
对于本发明的多个实施例,要被记录日志的冲突项目还将包括目标项目的复制,作为对冲突项目的扩展,或者仅仅作为也被存储在冲突记录中、具有它和冲突项目本身之间所规定的关系、或者可替换地作为冲突项目本身的一部分(例如一组属性值对)。作为冲突日志中的冲突项目的一部分或者与冲突项目一起被存储(被保存在永久数据存储上)的这个目标项目,将反映特定的改变引发了第一位置中的冲突。图40是示出了使用示例性联系项目的这种方法的方块图。在这个例子中,联系项目4002(“目标项目”)包括名称字段4004,名称字段4004最初被设置为“John”,作为最后成功的同步的名称。这个字段4004接着本地地被本地系统改变为“Bob”。在随后的同步期间,如果将这个名称字段4004改变为“Jane”的企图引起了冲突,因为本地系统不可能查明应当应用哪个名称改变“Bob”或者“Jane”,那么本地改变(“Bob”)被保留,而随着冲突项目4002’的复制一起,冲突4006被记录在冲突日志4008中,冲突项目4002’反映了导致冲突的改变的应用(“Jane”)。以这种方式,冲突日志包括引发冲突的完整目标项目,并且这个特定的目标项目被更新,以便反映试图在导致冲突的项目上进行的改变。
为了将冲突添加到冲突日志,首先搜索日志,以便确定在相同的改变单元(多个)上是否存在其它冲突。如果在相同的改变单元上存在任何现有的冲突,则检查它们以便可以移除。如果改变知道的现有冲突被改变知道的新的冲突包含,则移除现有的冲突。另一方面,如果改变知道的新的改变被改变知道的现有被记录日志的冲突包含,则删除新的冲突,反之亦然(也就是,如果它知道的被知道的存储包含,例如当所述存储接受并且成功地应用了包含知道的冲突的改变时,冲突也被变为已废弃的)。在第三种情况下,其中两个改变知道中的任何一个包含另一个,则新的冲突被添加到所述日志,并且对应于相同的改变单元的两个冲突存在于所述日志中,直到后来被人工地或者自动地分解为止。
d)冲突检查和分解
所述同步服务提供用于应用的API,以便检查所述冲突日志,并且建议其中的所述冲突的分解方法。API允许应用枚举所有冲突或者与给定的项目有关的冲突。它还允许这些应用以3种方式中的一种方式分解被记录日志的冲突:(1)远程优胜--接受被记录日志的改变并且覆盖所述相冲突的本地改变;(2)本地优胜--忽略所述被记录日志的改变的冲突部分;以及(3)建议新的改变--其中所述应用建议一种兼并(merge),在其看法中,分解所述冲突。一旦由应用分解了冲突,所述同步服务就将它们从日志中删除。
e)复制品的减小和冲突分解的传播
在复杂的同步情形中,在多个复制品上可以删除相同的冲突。如果发生了这种情形,则许多事情都可能发生:(1)在一个复制品上可以分解所述冲突,而所述分解方法被发送给另一个;(2)在两个复制品上自动分解了所述冲突;或者(3)在两个复制品上人工地分解了所述冲突(通过冲突检查API)。
为了确保减小,所述同步服务将冲突分解方法传递给其它复制品。当分解冲突的改变到达复制品时,所述同步服务自动地找到所述日志中的通过这种更新分解了的任意冲突记录,并且删除它们。在这种情况下,一个复制品上的冲突分解方法将捆绑在所有其它复制品上。
如果对于相同的冲突,由不同的复制品选择不同的优胜者,则所述同步服务应用捆绑冲突分解方法的原理,并且自动地挑选两种分解方法中优于另一种的一种分解方法。以确定的方式,挑选出所述优胜者,以保证在所有的时候都生成相同的结果(一个实施例使用复制品ID词典编辑上的对照)。
如果对相同的冲突,不同的复制品建议不同的“新改变”,则所述同步服务将这种新的冲突看作特殊的冲突,并且使用冲突日志记录器来防止它传播到其它复制品。这种分解方法通常会引起人工的冲突分解方法。
D.同步模式和冲突处理模式的附加方面
下面是用于本发明的各个实施例的同步模式的附加(或更特殊的)方面。
·每一复制品是来自整个数据存储的数据的定义的同步子集-具有多个实例的一段数据。
·在同步模式的根上,是具有定义具有唯一ID的根文件夹(事实上,是根项目)的基础类型的复制品,ID用于同步它是其成员的共同体,并且任何过滤器和其它元素对于特定复制品都是必须或期望的。
·每一复制品的“映射”被维持在所述复制品中,并且因而,用于任何特定复制品的映射被限定在这个复制品知道的其它复制品上。虽然这种映射可以只包括整个同步共同体的子集,但是通过公共地共享的复制品,所述复制品的改变将仍被传播给整个同步共同体(尽管任何特定的复制品不知道与未知的复制品公共地共享哪些其他复制品)。
·同步模式和复制品的使用允许真正的分布式对等多标准同步共同体。还有,不存在同步共同体类型,但是同步共同体简单地作为复制品本身的共同体字段中的一个值存在。
·每一复制品具有其自己的元数据,以便跟踪递增的改变枚举并且存储同步共同体中已知的其它复制品的状态信息。
·改变单元具有其自己的元数据,包括:版本,包括伙伴关键字加上伙伴改变号;每一改变单元的项目/扩展/关系版本;与复制品已经从同步共同体中看到的/接收到的改变有关的知识;GUID和本地ID配置;以及被存储在引用关系上的用于清除的GUID。
下面是用于本发明的各个实施例的冲突处理模式的其它方面。
·由各个复制品(以及适配器/数据源地组合)各自地处理冲突分解策略--也就是,各个复制品能够基于其自己的标准和冲突分解模式分解冲突。还有,虽然数据存储的各个实例中的区别可能得出并且导致附加的未来冲突,但是对于接收到那种被更新的状态信息的其它复制品而言,如被更新状态信息中所反映的冲突的递增且连续的列表是不可见的。
·同步模式包括可以用于所有复制品的多个预定冲突处理器,以及用于用户/开发者规定的客户冲突处理器的能力。所述模式还可以包括3个特殊的“冲突处理器”:(a)冲突“过滤器”,以不同的方式分解分解不同的冲突,所述分解是基于,例如:(i)当在两个位置中改变了相同的改变单元时,如何处理,(ii)当在一个位置中改变了改变单元而在另一个中进行了删除时,如何处理;以及(iii)当在两个不同的位置中两个不同的改变单元具有相同的名称时,如何处理;(b)冲突“处理器列表”,其中列表的各个元素指定一系列动作以便轮流尝试,直到成功地分解了所述冲突为止;以及(c)“什么都没做”的记录,跟踪所述冲突,但是在没有用户干预的情况下不采取进一步的动作。
IV.通过中介同步
最初采用此处描述的新存储平台,具有包括各种个别计算机系统的同步网络的企业将具有一种混合,其中某些个别计算机系统将使用新存储平台,而其它个别计算机系统将继续使用传统存储平台。这在其中两台客户机包括新存储平台,但服务器包括传统存储平台的任何客户机-服务器结构中尤其重要。因此,在这些情况下,使用新存储平台的两台计算机系统(“客户机”)可能有必要通过使用传统平台的计算机系统(“中介”)同步。例如,某些客户机可能使用诸如漫游拥护概况(RUP)或具有客户机方高速缓存(CSC)的文件夹重定向等软件在传统漫游服务中登记。由于用于这些传统存储平台的传统漫游软件不支持用于新存储平台的漫游数据,因此用于新存储平台的新漫游服务是必需的。本发明的各实施例针对一种系统和方法,用于通过中介同步使用公用存储平台(例如,相关发明的新存储平台)的客户机,而中介不使用同一公用存储平台(例如,作为替代,使用本身不支持新存储平台的同步的传统存储平台)。
A.中介的数据结构
本发明的若干实施例针对在复制品客户机和非复制品中介之间存在和操作的“通过中介同步”(STI)适配器。对于这些实施例,STI适配器被设计成将来自复制品客户机的改变枚举的结果串行化到非复制品中介,以及将来自非复制品中介的这些改变结果反串行化到复制品客户机。
图41所示是其中两台客户机必需通过中介同步的情形的框图。图中,使用传统存储平台(例如,Win32)的中介计算机系统连接到都使用新存储平台(例如,此处描述的相关发明的实施例,为方便起见,后文称为“WinLH”,WinLH包括此处所称的WinFS文件系统,如图所示)的客户机A 4112和客户机B 4114两者。中介4102可以被认为仅仅是从客户机A 4112同步到客户机B 4114以及从客户机B 4114同步到客户机A 4112的改变的“通过”。由此,中介4102本身不为其自身的目的而与客户机A 4112或客户机B 4114同步,并且因此不直接使用它从客户机A 4112或客户机B 4114接收到的任何改变数据。为此,使用本文中先前所使用的术语,中介4102不是复制品,尽管作为复制品的客户机A 4112和客户机B都如同中介4102是复制品那样通过“通过中介同步”(STI)适配器与其交互。
客户机A 4112和客户机B 4114分别通过STI适配器4122和4124与中介4102接口,所述STI适配器被特别地定制以在客户机4112和4114的新存储平台和中介4102的特定传统平台之间接口。本发明的若于替换实施例针对对应于中介可能需要与其同步的若干传统存储平台的若干特定STI适配器。这使得客户机4112和4114仍能够如同中介4102是复制品那样逻辑上与其同步(通过STI适配器4122和4114),尽管实际上使得同步成功的是对客户机本地的STI适配器。
对于将改变枚举的结果从复制品客户机串行化到非复制品中介,每一串行化对应于被被到要写入中介的文件的三元组中的一批改变。对于某些实施例,这些文件被写入对应于特定同步共同体的特定文件夹(“共同体文件夹”),并且不同的同步共同体将具有不同的共同体文件夹。上述文件的三元组包括改变数据文件(CDF)、先决条件知识文件(PKF)、以及已获知知识文件(LKF)。CDF包含涉及在改变单元级对于WinFS项目的特定改变的信息。PKF指定了同步对等体必须已经知道什么以应用相关联的改变。另一方面,LKF指定了如果同步对等体应用相关联的改变,则它必须获知什么。为了效率起见,且类似于对等同步,STI适配器仅串行化改变单元信息(“改变的部分”及其相关联的元数据),且对于若干实施例,该数据可能仅包含(对于项目的特定改变)项目类型、项目版本号、改变单元版本以及所改变的属性的值。对于各实施例,文件的三元组使用基于串行化的消息序列的顺序命名约定写入中介中(为了后文所讨论的原因);例如,第一串行化可包含储存为中介上的1.PKF(PKF文件)、1.CDF(CDF文件)和1.LKF(LKF)文件的三个文件,第二串行化可包括2.PKF、2.CDF和2.LKF,依此类推。
B.STI适配器进程
对于本发明的若干实施例,STI适配器包括三个核心操作:发送同步、接收同步和数据压缩。
1.发送同步操作
图42所示是客户机通过STI适配器向中介发送改变数据(“发送同步”操作)的步骤的流程图。在步骤4202,STI适配器首先确认中介上是否存在对应于客户机的同步共同体的共同体文件夹。如果是,则在步骤4204,STI适配器然后扫描和反串行化中介的共同体文件夹中的LKF的所有内容,以确定对于该同步共同体的中介的本地知识(ILK)的当前状态。另一方面,如果没有共同体文件夹,则在步骤4206ILK被认为是空的,并且在中介上创建一共同体文件夹。
在步骤4208,STI适配器并发地获取中介的共同体文件夹上的“写模式”进程锁(通过中介的文件系统),以通过防止其它客户机(或其它对等体或进程)在发送同步操作过程中读取或写入共同体文件夹来保持数据的完整性。在步骤4210,STI适配器然后将ILK传递到客户机。基于IKL及其自己的客户机本地知识(CLK),在步骤4212,客户机确定是否有ILK没有传达的任何改变,如果否,则过程跳至步骤4220。另一方面,如果客户机确定存在ILK没有传达的改变,则在步骤4214,客户机准备ILK没有传达的所枚举的改变,并将它们传递到STI适配器。在步骤4216,STI适配器串行化每一批改变信息(改变数据和知识),并且在步骤4218,当顺序地递增如上所述的文件的三元组时,STI适配器然后将串行化的批量改变写入中介的共同体文件夹中。一旦所有的串行化的批量改变被写入中介中,在步骤4220,STI适配器然后释放“写模式”进程锁,以允许其它客户机(或其它对等体或进程)检查中介上更新的内容。
尽管完成了发送同步操作,应当注意,STI适配器储存了写入中介中的最后一个且最高的顺序递增的改变三元组(HCT)的身份(或参考号)以供以后参考(下文讨论)。也应当注意,没有执行冲突处理作为发送同步操作的一部分。最后,对于其中客户机仅“拉”数据(并且因此客户机不启动发送同步操作)的对等实施例,并假定中介没有用于启动它本身的功能,则STI适配器可代表中介主动启动发送同步操作。
2.接收同步操作
对于另一方向上的同步,图43所示是客户机通过STI适配器从中介接收改变数据(“接收同步”操作)的步骤的流程图。在步骤4302,STI适配器首先接收客户机本地知识(CLK),对于本发明的若干实施例,这在客户机通过STI适配器向中介发送同步请求时发生,所述同步请求内在地包括本文先前所讨论的每一对等同步模式的CLK。在步骤4304,STI适配器然后获取中介的共同体文件夹上的“读模式”进程锁(通过中介的文件系统),以通过防止其它客户机(或其它对等体或进程)在接收同步操作过程中写入(但是对于某些实施例,并非读取)共同体文件夹来保持数据的完整性。对于某些实施例,“读模式”可以被优化成锁定每一三元组而非整个目录,以达到更好的并发性。
在步骤4306,对于由STI适配器为该中介储存的HCT(例如,可以从先前讨论的发送同步操作中获得),STI适配器扫描中介上的共同体文件夹,以找出下一较高的改变三元组,该三元组(a)顺序上比HCT高,(b)对于该改变三元组,CLK(客户机本地知识)多于先决条件知识(来自PKF),以及(c)对于该改变三元组,CLK少于已获知知识(来自LKF)。(这一改变三元组此处被称为“适用改变三元组”或“ACT”)。如果在步骤4308存在这样一个改变三元组(ACT),则在步骤4310,同步适配器将该改变三元组(ACT)的内容反串行化到复制品可理解的所枚举的改变中,并且在步骤4312,将改变发送到客户机以供处理。过程然后返回到步骤4306,以处理下一个ACT,并且该过程继续,直到没有剩下的ACT,此时STI适配器在步骤4314解锁读模式,该过程结束。
3.中介文件数据压缩/压紧
对于本发明的各实施例,常规地压缩由STI适配器创建的串行化数据和知识文件是必需的;否则越来越多的改变三元组将填满中介上的所有可用空间。在这一点上,数据压缩的目标是确保数据和知识文件的增长在中介上被适当地界定。本发明的若干实施例采用的一种方法是在允许存在于共享文件系统上的改变分组的数据上设置“上限阈值”,一旦超过该阈值,要求能够进行压缩的下溢STI适配器通过压缩操作压缩共享的文件系统(共同体文件夹中的文件)。压缩操作通过以下步骤减少了储存在共享文件系统中的数据量:(a)压缩个别现有对象的改变历史,以及(b)移除已被删除(通过冲突分解明确地删除,或作为墓碑清除的结果删除)的对象的改变广播。然而,压缩仅可以由刚执行了接收同步且能够立即执行“全”发送同步(即,如同中介上没有共同体文件夹那样不带基线的全改变枚举)的客户机的STI适配器来实现。由此,压缩不能由仅与中介完成发送同步或接收同步的客户机执行。
图44所示是STI适配器(即,与可以进行发送同步和接收同步两者的客户机相关联的STI适配器)为中介上的共同体文件夹中的数据执行压缩操作(“压缩”操作)的步骤的流程图。在图中,紧接着步骤4402处STI适配器的客户机的成功接收同步操作之后,但是在释放“读模式”进程锁之前(即,紧接着图43的步骤4312之后,但在步骤4314之前),在步骤4404,STI适配器核查中介上的共同体文件夹,来看是否超过了上限阈值;如果否,则过程结束(通过接收过程通过释放锁等来完成)。然而,如果超过了上限阈值,则在步骤4406,STI适配器删除中介的共同体文件夹中所有的改变三元组文件,然后在步骤4408,STI适配器通过向客户机指示中介的知识不为空(在删除之后,情况的确如此)着手启动客户机和中介之间的全读同步操作(包括写模式进程锁定)。结果,仅对应于客户机整个状态的最小的一组三元组文件被上传到中介且存在于中介上。
对于其中“读模式”被优化成锁定每一三元组而非整个目录以达到更好的并发性的那些实施例,且对于使用标准“读模式”的本发明的其它替换事实,该过程有略微的不同,其中,STI适配器在STI适配器获得中介共同体文件夹上的“读模式”进程锁(通过中介的文件系统)(在图43的步骤4304)之前检查是否需要压缩,如果需要压缩,则使用标准(非优化)的“读模式”以通过防止其它客户机(或其它对等体或进程)在接收同步操作过程中写入(但是对于某些实施例,并非读取)共同体文件夹来保持数据的完整性。
对于某些替换实施例,中介上的数据在客户机通过从第一个现有改变三元组开始盖写现有改变三元组来上传所有改变三元组之前不被删除,一旦上传了所有的改变三元组(且重写了旧的改变三元组),则序列号高于全读同步过程中最后一个上传的改变三元组的所有剩余的改变三元组被删除。
最后,某些实施例也在完成了完整的读同步操作(包括释放读模式进程锁)之后开始压缩。对于这类实施例,该过程从获得写模式进程锁开始,然后继续执行先前提到的所有步骤。
C.STI和下级客户机支持
除上述以外,本发明的若干实施例针对先前所描述的通过中介同步技术的变体。某些实施例针对还包括也运行传统存储平台的客户机的系统,其中所述“传统客户机”也可以访问所有的数据文件。也预期某些传统客户机和其它应用程序和进程能够为其它目的而访问这些数据文件。例如,对于基于创建时间或某些其它固有文件特征同步文件的传统客户机。另一示例是直接访问任一或所有文件(例如,*.CDK文件)并复制它们的传统客户机。在许多方面,传统客户机可以在与直接与第一中介直接通信(可能使用传统同步技术)的第二中介相同的观点来考虑,并且由此,多中介同步是可能的,且如此揭示。
IV.结论
如之前所示,本发明针对用于组织、搜索以及共享数据的存储平台。本发明的存储平台扩展并且扩大了现有文件系统和数据库系统之外的数据存储的概念,并且被设计为用于所有类型的数据的存储,包括结构化的、非结构化的、或者半结构化的数据例如关系(表列)数据、XML,以及一种被称作项目的新形式的数据。通过其共同存储函数和模式化的数据,本发明的存储平台允许用于客户、知识工作者以及企业的更有效的应用开发。它提供了丰富的并且可扩展的应用编程接口,所述接口不仅可以使用其数据模型中固有的性能,而且包含并扩展了现有文件系统和数据库访问方法。可以理解,在不脱离其宽泛的发明概念的情况下,可以对以上所述的实施例进行的改变。因此,本发明并不限于所公开的特殊实施例,而是旨在由所附权利要求所规定的覆盖本发明的精神和范围内的所有改变。
如根据以上所述变得很明显的,本发明的各种系统、方法、以及方面的所有或者一部分可以以程序代码(即,指令)的形式来体现。这种程序代码可以被存储在计算机可读介质上,例如磁的、电的或者光的存储介质,在非限定情况下包括软盘、CD-ROM、CD-RW、DVD-ROM、DVD-RAM、磁带、闪速存储器、硬盘驱动器、或者其它机器可读存储介质,其中当程序代码被载入到机器例如计算机或服务器中并由机器执行时,所述机器就变成用于实施本发明的装置。本发明还可以以在一些传输介质上被传输的程序代码的形式来体现,在传输介质上例如在电线或者电缆上、通过光纤、在网络上,包括因特网或内部网,或者通过任何其它形式的传输,其中,当程序代码被接收并且被载入到机器例如计算机中并且由机器执行时,所述机器就变成用于实施本发明的装置。当在通用处理器上被实现时,所述程序代码与处理器相结合,以便提供类似于特定逻辑电路的操作的唯一装置。