专利名称:用于自动修改数据库存取方法的系统和方法
技术领域:
本发明一般涉及采用面向目标的计算机程序来处理数据库中存储的数据的系统和方法,特别涉及自动修改存取数据库中数据的目标分类方法的系统和方法,以便插入用于从数据库中检索数据、并且在适当的时间将修改后的新数据存储到数据库中的指令。
面向目标的DBMS(数据库管理系统)提供对程序设计语言目标的持续存储,并且它们支持对程序设计语言中实际上是任何数据结构的存储。相反,常规记录结构的DBMS需要嵌入的数据库语言(例如SQL)语句或过程调用,用于在数据库和程序设计语言表示之间来回复制数据,并且它们只支持对记录的存储。某些新的产品允许传统的面向记录的数据库被自动地映像到程序设计语言目标上,从而使程序员可以将其同样看作是面向目标的DBMS。对与目标相关的映像和面向目标的DBMS来说,本发明都是一项创新的应用技术。为方便起见,我们将用后者来代表二者。
面向目标的数据库的一个引人注目的方面,是用于操纵该数据库的计算机程序相比于传统的数据库存取程序而言更易于理解。面向目标的数据库的一个更重要的优点是“静态数据类型实施”可以适用于存取该数据库的计算机程序。这意味这种程序的编译程序可以保证存储在一个特定数据库区段的所有数据与为该区段定义的数据类型相匹配。因此,一个试图将整数放到雇员姓名区段中的程序会被面向目标的系统中的编译程序拒绝。
遗憾的是,编写面向目标的程序来存取存储在DBMS(数据库管理系统)中的磁盘或其它辅助存储器中的数据,起初一看似乎很容易,其实是很困难的。编写将存取目标区段翻译为数据库询问程序的目标分类方法是比较直接的,而编写代码来持续确定什么时候需要从数据库读出数据和什么时候需要将数据写入数据库则要复杂一些,原因在于采用了目标参考(即目标中对其它目标的引用)用的方式。例如,不要因疏忽而在存储器中产生代表相同数据库目标的两个目标,这一点是很重要的。
为了本说明书描述方便起见,“存储器”和“主存储器”用于指随机存取存储器或计算机系统的主存储器,“辅存储器”和“持久存储器”指相对于主存储器而言将数据保留更持久或更长时间的磁盘存储器或其它存储形式。
本发明的一个目的是使程序员在编写面向目标的数据库应用程序时,就象他们在简单地处理主存储器中的数据库目标一样,而不必关心从/向实际的持续存储数据库读出/写入数据的机理。
更详细地说,本发明的一个目的是提供一个系统和方法,用于“后处理”被编译的面向目标的数据库程序,以便自动插入在将数据库中的数据复制到存储器中的目标之时所需要的额外代码,并且在适当的时候将修改后的新数据从存储器中的目标复制到数据库中。程序员可以以这种方式编写面向目标的数据库程序,其中代表持久存储的数据的目标可以被处理,对初始源代码程序来说,与存储非持续数据的目标没有不同之处。
总之,本发明是用于将存取主存储器中存储的目标的编译程序自动转换为存取并更新持续存储的目标的程序的系统和方法。初始计算机程序包括用于存取并更新在至少第一目标类中的目标的原始指令。该原始指令存取并更新计算机主存储器中的目标。本发明的系统和方法通过向原始指令加入目标装入指令和目标存储指令,来自动修改初始计算机程序,以产生修改后的计算机程序。
在执行修改后的计算机程序时,当一个持续存储的目标第一次被存取时,目标装入指令将该持续存储的目标的一个备份装入计算机主存储器的一个相应目标中。目标存储指令在出现预定事件(如完成一事项)时将计算机主存中包含新的或修改后的数据的目标复制到相应的持续存储目标中。
本发明的系统和方法进一步修改初始计算机程序来产生修改的计算机程序,做法是在原始的指令中加入无效目标标记指令(dirty object markinginstruction),该指令在执行修改的计算机程序时对计算机主存中哪些目标包含新的和/或更新的数据予以跟踪。目标存储指令只复制计算机主存中包含新的和/或更新的数据的那些目标。
下面结合附图对本发明进行详细的描述,由此可以清楚了解本发明的其它目的和特性。
其中
图1是采用数据库程序的一个计算机系统的概念性方框图,所述数据库程序采用本发明最佳实施例的方法作了修改;
图2是本发明方法的最佳实施例的概念性方框图;图3是包含本发明最佳实施例的一个计算机系统的方框图;图4是在本发明最佳实施例中采用的数据库目标分类的方框图;图5是在本发明最佳实施例中采用的方法的流程图;图6A和6B是在本发明的另一实施例中使用的零指示字例外处理程序的流程图。
在本文中,“数据库使用程序”指对持续存储在数据库或在持续存储文件中存储的数据进行存取的任何程序。
在最佳实施例中,数据库使用程序的作者在写程序时就好象被用到的所有程序被存储在主存中一样。因此,数据库使用程序的源代码不包含确定何时目标要从持续存储数据库中复制到主存中、跟踪记录主存中哪些目标包含在进行当前事项时将最终需要被写回到数据库中的新的或修改的数据、以及将带有新的或修改的数据的目标写回到数据库时需要的所有程序代码。因此,与包含在数据库和主存之间来传送信息所需要的所有代码的一个源代码程序相比,该源代码程序更便于读出和修改。
在最佳实施例中,数据库使用程序的源代码是用Java程序设计语言编写的,该语言是由太阳微系统公司(Sun Microsystem Inc.)销售的一种“机器平台独立”的程序设计语言。该数据库使用程序的源代码200(见图2和图3)采用传统的Java编译程序202编译成java字节码程序204,从而产生通常包含一些目标类别的字节码文件。
Java字节码程序是与构成一个虚拟机的字节码程序解释程序176一起执行的。Java字节码程序的设计使得任何计算机只要安装了Java字节码程序的解释程序,无论该计算机的操作系统和计算机硬件平台如何,Java字节码程序都可以在该计算机上执行。
然而,数据库使用程序的初始编译字节码程序版本并不是一个真正的功能程序,因为它在编写时基于这样一个错误的假设,即所使用的全部数据库是存储在主存中的,而实际上该数据库是存储在持续存储器中的。根据本发明,用修正编译程序中的目标类别的一个“后处理器”程序206来对数据库使用程序的初始编译字节码程序版本进行修改。该后处理器206对目标类别的目标数据结构进行修正,这些目标类将被用于存储持续存储目标的主存备份,以启动对管理目标指示字并且跟踪记录将需要被存储在持续存储数据库中的“无效(dirty)”目标所需要的额外信息的存储。后处理器也修正编译程序中的目标分类方法,做法是增加额外的指令,来确定目标应该在什么时候从持续存储的数据库中复制到主存、复制数据库的目标到主存、跟踪记录主存中的哪些目标包含在进行当前事项时最终需要被写入到数据库中的新的或修正的数据、以及将带有新的或修正的数据的目标写入到数据库。
参考图1,图中示出了与数据库使用程序的操作有关的主数据结构。为了解释方便起见,假定采用本发明的计算机系统100包括主存102,它通常由高速随机存取存储器构成,和持久数据存储器104(也称为辅存储器),它通常是磁盘存储器或即使在设备断电时也能保持存储在其中的信息的其它存储装置。
持久数据存储器104存储一个数据库106,在这种情况下下它被假定为存储多个目标108的一个面向目标的数据库。所有或大多数被存储的目标108包括对数据库中其它目标的指示字。另外,数据库106通常是管理对数据库中存储的数据的所有存取活动的数据库管理系统(DBMS)的一部分,对数据库的存取通常需要采用很好定义的命令(如包括在各种SQL版本中的命令)来进行。为了便于讨论,假定DBMS110和数据库106没有被本发明所改变。
在最佳实施例中,运行期系统112控制程序的执行,该程序则将数据存储在主存102中。在本申请中为了方便起见,将由运行系统112执行的程序假定为面向目标的程序,因此也就倾向于在主存中以目标114的形式存储数据。存储在主存102中的某些目标,如目标114-3,被称为“过渡”目标,因为他们从没存储在持久存储器104过,因此其存在时间不会长于产生它们的过程。其它目标,如目标114-1和114-2被称为“持久”目标,原因是当产生它们的事项成功地终止时,或者(A)这些目标的一个备份被存储在持久存储器104中,或者(B)构造这些目标使其存储在持久存储器104中。
应该理解,本发明适用于任何系统,其中目标数据在满足一组目标存储条件(即出现任何一个第一组限定事件)时被存储在持久存储介质中,并且目标数据在满足一组目标检索条件(即出现任何一个第二组限定事件)时从持久存储介质中检索出来。
如图1所示,在最佳实施例中,持久目标包括一个对持久数据描述符122的指示字120。在最佳实施例中,持久数据描述符122包括A)持久存储器中目标的全目标识别符(OID)124或地址;B)当目标被包括在一列“无效”目标中时所使用的一列指示字126;C)在目标中对另一目标的每个参考130的全目标识别符(OID)128或地址。为了减小存储器的存储量,只有持久目标才包括一个持久数据描述符122。
为了清楚起见,应注意在最佳实施例中,当一个目标从DBMS110(即从持久存储器104)复制到主存102中时,在被复制目标中的所有目标参考都是64位或更大的目标地址,这里将其称为DBMS目标识别符(OID)。这些OID被存储在持久数据描述符122中,并且在主存目标备份114中的目标参考字段130被替代为(A)一个零指示值,如果被参考的目标不在主存102中,或(B)指示被参考目标的备份的主存目标指示字的值,如果被参考的目标在主存中。在另一个实施例中,OID可能包括与从数据库复制的目标有关的唯一的主关键值(key value)。
在最佳实施例中,持久目标的每个目标类也支持瞬态目标。该瞬态目标与相同目标类的持久目标具有相同的数据结构,但是有一个零持久数据描述符指示字120。对相同目标类中的瞬态和持久目标都支持的一个原因是,即使瞬态目标中的数据从不需要被存储在持久存储器104中,但对目标以及与持久目标同类的中间或瞬态“工作”目标进行临时复制,以便在各种计算中使用来说,常常要便利得多。
在本发明的应用中,某些目标类别只用于持久目标,在实现本发明时,这些目标类定义可以予以修改,以清除持久数据描述符指示字120,而包括持久数据描述符122本身来作为主目标定义的一部分。
在最佳实施例中采用另外两个数据结构,来跟踪存储在主存中的目标114。首先,在主存中存储一个散列表140,并用于将DBMS OID映射为主存目标指示值。每当从DBMS复制一个目标到主存时,将一个相应的项目加到指示目标的OID以及其主存目标指示字的散列表中。
当在散列表140中查找任何目标的全DBMS OID时,如果在散列表中没有发现相应的项目,那么目标就还没有被复制到主存中。另一方面,如果在散列表中找到了相应的项目,那么在该项目中的目标指示字就指示主存中的目标。
第二,一个表标题142指示需要复制到持久存储器中的相连的目标表。这些目标被称为“无效”目标,因为它们是超高速缓冲存储器(被称之为“无效”超高速缓冲行)中被同样修正的数据,在发生一定事件时,它们需要被写回到主存中。相连的表列是由表标题142中的一个指示字加上无效目标的持久数据描述符122中的一系列指示字126构成的。如果无效目标表是空的,那么表标题142包括一个零指示字。当无效目标非空时,表标题142指示要被加到无效目标表中的最后一个目标,后者又指示要被加到无效目标表中的倒数第二个目标,以此类推。无效目标表中的最后一项是要被加到无效目标表中的第一项,它在其下一个指示字字段126中有一个零指示字。
当一个“新目标”需要被加到无效目标表中时,执行步骤依次为(A)将表标题142中的目标指示字复制到新目标的下一个无效目标指示字字段126中;(B)存储一个新目标指示字到表标题142中。
在最佳实施例中作的另一组假定是数据库目标被用在有限事务处理范畴中,并且每个事务处理有一个作了很好定义的开端,这通常由一个“起始事务处理”指令来定义;以及一个作了很好定义的结尾,当事务处理的结果要被持久地存储在数据库中时,该结尾通常由“执行事务处理”来定义,当事务处理结果要被丢弃时,该结尾由“异常终止事务处理”来定义。此外,在执行每次事务处理时,假定运行期系统112必须请求对所有复制到主存中的数据库目标的读锁定,并且必须进一步请求对所有其内容由运行期系统112执行的程序所修改的数据库目标的写锁定。
更为特别的是,编程员准备数据库使用程序的源代码时必须在源代码中包括等同于Invoke Database.Start Transaction(调用数据库.启动事务处理)的一个语句,以便在每个事务处理的开始调用数据库目标类的“启动事务处理”方法。与此类似,编程员必须在源代码中包括等同于Invoke Database.End Transaction(调用数据库.结束事务处理)的一个语句,以便在每次成功地完成事务处理后调用数据库目标类的“结束事务处理”方法,并且在源代码中必须包括等同于Invoke Database.Abort Trarsaction(调用数据库.异常终止事务处理)的一个语句,以便在每次未成功完成事务处理的开始时调用数据库目标类的“异常终止事务处理”方法。
“启动事务处理”、“结束事务处理”和“异常终止事务处理”方法将在下面参考图4作更详细的描述。
由于运行期系统操作的“经过很好定义的事务处理”上下文语境,在结束每次事务处理时,存储在主存中的目标组通常将被无效,最好是通过使其PDD中的每个目标的OID为零来实现。另外,清除散列表140中的内容,并将一个零指示字存储在无效表标题142中,从而使得主存中的目标准备进行无用单元收集,除非正执行的程序产生了指示这些目标中的任意一个的额外指示字。然而,由于所有这种目标应该被认为是无效和不可利用的,因此,当结束一项事务处理后,一个适当编写的程序不应该留存指示主存中任何目标的指定字。
注意到存储在主存中的所有或大部分瞬态目标都将由主存中存储的持久目标直接或间接作为参考。通过使主存中的所有持久目标无效并使所有这类持久目标不能得到,主存中的瞬态目标通常也会变得不能得到,从而等待无用单元收集。
在另一个实施例中,如在不用无用单元收集来消除无用目标的系统中,主存中的目标可以明确地被删除和重新分配。
计算机系统结构参看图2,在一个最佳实施例中,包含本发明的一个最佳实施例的计算机系统100通常或者是一台独立计算机、或者是网络化计算机系统中的一台客户计算机150或服务计算机152。为了讨论便利起见,我们假设本发明的最佳实施例由客户计算机150实现。该客户计算机150包括一个中央处理单元(CPU)160、一个用户接口162、和一个经由通信网络166与其它计算机通信的通信接口164。
存储器102/104包括主存102和持久存储器104两者,用于存储·一个操作系统170;·一个Intemet通信管理器程序172;·一个Java字节码程序检验程序174,用于检验一个特定程序是否满足某些预定的完整性条件;·一个Java字节码程序的翻译程序176,用于执行应用程序;·一个类别装入程序178,它将目标类别装入到用户的地址空间,并且采用字节码程序检验程序来检验与每个装入的目标类相关的方法的完整性;·至少一个类别贮存室180,用于局部存储由计算机102的用户使用和/或可使用的目标类182、184、186;·至少一个目标贮存室190,用于存储目标192、194,它们是在目标贮存室182中存储的目标类的目标例子;一个目标散列表140,用于记录跟踪主存中存储的与DBMS数据库110/106中存储的目标相关的目标;·一个无效目标表标题142。
在存储器102/104中还存储了·一个源代码数据库使用程序200;·一个Java程序的编译程序202;·一个由编译程序202从源代码程序200中产生的初始编译后的程序204;·最佳实施例的后处理器程序206;·由后处理器程序206产生的一个修正后的程序208。
然而,应该理解,在执行修正后的程序208时,源代码200、编译程序202、初始编译后的程序204和后处理器程序202通常不存储在主存中。
在最佳实施例中,操作系统170是一个面向目标的多任务操作系统,它支持在每个定义的地址空间中执行的多个线索。该操作系统进一步采用无用单元收集过程来恢复与释放的数据结构相关的存储空间。无用单元收集过程周期性地自动被执行,并且当可用于分配的存储器数目低于阈值水平时,还在额外的时间被自动调用。
参考图3,最佳实施例的系统和方法接收一个初始源代码、Java语言的数据库使用程序200。这个初始源代码程序由常规的Java编译程序202进行编译,以产生一个Java字节码程序204。然而,Java字节码程序不是一个真正的功能性程序,因为它的代码是基于错误的假定,即假定所使用的全部数据库被存储在主存中,而实际上由程序使用的数据库是存储在持久存储器中的。
数据库使用程序204的初始编译字节码程序版本接下来由一个“后处理程序”206进行修改,该后处理程序206修正编译的程序中的目标类,从而产生修正后的Java字节码程序208。后处理程序206对将要用于存储持久存储目标的主存备份的目标类的目标数据结构进行修正,以便存储用于管理目标指示字和用于记录跟踪需要存储在持久存储数据库中的“无效”目标所需要的额外信息。后处理程序206也修正编译的程序中的目标分类方法,做法是加入额外的信息来确定目标何时从持久存储的数据库中复制到主存中、将目标从数据库复制到主存中、记录跟踪主存中哪些目标包含在完成当前事务处理后最终需要被写入到数据库中的新的或修正的数据,并且将带有新的或修正后的数据的目标写回到数据库中。
修正后的程序208包括对一个或多个预定目标类182的方法的方法调用,下面将对此作详细的描述。然而,在由修正的程序所采用的预定目标类中的方法通常是需要与用于持久目标的持久数据描述符结构122(见图1)一起工作、并且用于处理数据到/从数据库106中的移动的方法。
产生的修正后的字节码程序208的完整性由字节码程序检验程序174进行检验,然后由字节码程序解释程序176予以执行。
参看图4,在最佳实施例中有一个预定的目标类,称为数据库目标类,它包括与持久目标一起工作和处理数据向/从数据库106中移动时需要的所有方法。该数据库目标类包括两个变量1)无效目标表标题142和2)目标散列表140。包括在数据库目标类中的方法为·一个查询(Query)方法220,用于请求满足用户或程序指定条件的一个或多个数据库目标,并且在主存中产生这些目标的备份;·一个装入数据(Load Data)方法222,它将特定数据库目标中的数据装入主存中的一个目标,并且导致为主存中的那个目标产生一个持久数据描述符;该装入数据方法还请求并获得对相关DBMS目标的读锁定,并且对装入主存中的每个目标加一个项目到散列表;·一个标记目标(Mark Obiect)为无效方法224,它将主存中的一个特定目标加到无效目标表;该标记目标方法也请求并获得对相关DBMS目标的写锁定;·一个散列功能方法226,它由数据库查询方法220和装入数据方法222用来查找散列表140中的一个目标ID以及确定将新的项目存储到散列表140中的位置;·一个起动事务处理(Start Transaction)方法228,它用于在事务处理的开端起动目标散列表140和无效目标表标题142,但只限于在事务处理开始时它们还没被启动的情况;·一个结束事务处理(End Transaction)方法230,它在成功结束(即完成)一项事务处理后被调用,并且首先用于将无效目标表中的所有目标复制到数据库106,然后重新启动目标散列表140和无效目标表标题142;
·一个异常终止事务处理方法232,它在没有成功地结束事务处理(即异常终止)时被调用,并且被用于重新启动目标散列表140和无效目标表标题142;用于启动散列表和无效目标表的方法234,它由起始、结束和异常终止事务处理方法228、230和232调用,来启动或重新启动目标散列表140和无效目标表标题142,从而使先前存储在主存中的所有持久目标都不可用。
本发明的查询、起始事务处理、结束事务处理和异常终止事务处理方法由编程员在编写数据库程序时调用。数据库目标类的装入数据、标记无效和散列功能方法仅仅在由后处理程序206产生的修正的程序中的指令来使用。
当查询方法220被调用并且导致从数据库返回一个或多个目标时,对所有被请求的目标自动请求一个读锁定。此外,由数据库查询方法220返回的所有目标在主存中被表示为持久目标,每个目标具有一个持久数据描述符122。
起始事务处理方法228(A)在散列表140和无效表指示字142没被清除时对其予以清除,(B)发送一个“起始事务处理”命令到DBMS,以便适当地对DBMS的内部状态初始化。
结束事务处理方法230工作如下当事务处理成功地结束时,无效目标中的所有目标都需要被复制到持久存储器。然而,在无效目标被复制到DBMS之前,由被复制到DBMS中的无效目标中的目标指示字所参考的所有瞬态目标必须被转换为持久目标,并且被加入到要被复制到DBMS中的无效目标表中。这是避免在DBMS目标中存在没被分辨的指示字所必要的。在最佳实施例中,用于将无效目标表中的所有目标复制到持久存储器中的结束事务处理方法执行两遍通过无效目标表。第一遍被用于(A)直接或间接地通过其它瞬态目标将由目标所参考的所有瞬态目标放置在无效目标表列中、(B)得到所有这些目标的数据库OID、(C)将所有这些被引用的瞬态目标转换为持久目标、(D)将对这些目标的参考加到散列表和无效目标表。
然后,在第二遍中,无效目标表中的每个目标被复制到DBMS,在发送目标到DBMS之前,用其相应的DBMS OID取代每个目标中的本地目标引用。然后发送一个“进行事务处理”命令到DBMS,它导致先前在DBMS目标上获得的所有读锁定被释放,并且所有DBMS目标转变为持久存储。
表1是“数据库.结束事务处理”方法的伪代码表示。
表1“数据库.结束事务处理”方法的伪代码表示/*第一遍*/对无效目标表中的每个目标{对由无效目标所参考的每个瞬态目标{请示DBMS指定一个唯一的OID到这个瞬态目标在参考无效目标的PDD中存储瞬态目标的指定OID为瞬态目标产生一个PDD,以将其转换为持久目标填充目标的PDD将这个目标加到当前正在处理的无效目标的位置之下的一个位置处的无效目标表中}对在无效目标的PDD中没有相应的OID的无效目标中的每个非零目标指示字{从它的PDD中取得被参考目标的OID将参考目标的OID存储在参考无效目标的PDD中}}/*第二遍*/将无效目标表中的所有目标存储到DBMS中,在传送目标到DBMS之前用它们相应的DBMS OID替代每个目标中的局部目标参考发送一个“执行事务处理”命令到DBMS,它使先前在DBMS目标上获得的所有读锁定被释放,并且所有DBMS目标改变为被持久存储。
异常终止事务处理方法232(A)清除散列表140和无效表指示字142,(B)发送一个“异常终止事务处理”命令到DBMS,以便复位DBMS的内部状态。
后处理程序参看图4和图5,数据库目标类的数据结构和方法由后处理程序插入一个被编译的数据库使用程序中的代码来使用。在最佳实施例中后处理一个被编译的数据库使用程序的过程如下通过修正被编译的数据库使用程序中的目标类定义以及对程序的第一条指令设置一个指示字来开始后处理程序(步骤250)。
可能被用于存储从数据库或其它持久存储器中复制的数据的被编译数据库使用程序的所有目标类被修正,以便包括对持久数据描述符的一个指示字。在本发明的某些实施例中,后处理程序将接收其目标可以被用来存储持久数据的所有目标类的一个表列,在这种情况下,只有那些目标类被检查和修正,以便包括一个持久数据描述符。在其它实施例中,假定在被初始编译的数据库使用程序中所有目标类被潜在地用来存储持久数据,从而所有目标类都被检查和修正,以便包括持久数据描述符指示字。
接下来,检查被初始编译的数据库使用程序的每个语句或指令(步骤254、258),来确定该语句是否是需要特殊处理的几个指令类型中的一个。在下面的描述中,加到被编译的数据库使用程序中的指令将被写成伪代码形式。用于这个文件中的伪代码采用通用的计算机语言惯例。尽管这里使用的伪代码仅仅是为本说明书所发明的,但其设计很容易被本领域的计算机编程员理解。为引用一个目标的目标指示字字段的“Get Field”指令而插入的代码如果当前指令(即由后处理程序指示字指示的一个指令)是用于从一个目标读出一个目标指示字字段的一条指令(在Java字节码语言中被称为“getfield(获得字段)”指令)(步骤254),那么示于表2中的指令就被加到程序中(步骤256)。为方便引用,表2中被加入的指令被加以编号。
表2在“读目标指示字字段”指令之后加入的代码/*在后处理之后,被编译的代码看起来是这样的*/Push ptr/*将参考目标的指示字推到堆栈*/
Getfield F/*在存储信息的地方得到被参考目标的目标指示字。
Getfield指令将被参考目标的一个指示字留在堆栈的顶部*/(如果由上述指令检索的目标指示字为零,那么后处理程序在此将代码插入到程序中,来作特殊的处理)/*被编译程序中的下一条指令实际上可以是任何指令,例如*/Getfield G/*从被参考目标的字段G得到信息*//*在上述Getfield F指令之后,插入到程序中的代码如下*/01 如果在堆栈上端的目标指示字(即由“Getfield F”指令得到的一个)不是零02 {Goto Sl}03 如果参考目标没有持久数据描述符{04 发出一个零指示字例外(可能导致程序终止执行)}05 从参考目标的持久数据描述符得到该目标的数据库目标识别符(OID)06 如果OID是零{/*当数据库目标包括一个零指示字时,例如在一个表列或树的叶节点处,OID是零。*/07 goto Sl}08 Ptr=散列表(OID)09 如果Ptr不是零(即散列表有一个OID项目){10 将Ptr复制到参考目标的适当字段中}11 否则{12 Ptr=数据库装入数据(Database.Load Data)(OID)/*该数据库装入数据方法执行下述步骤12a 从数据库为OID取目标12b 产生并起动相关目标类的一个新的目标例子12c 为新目标产生一个持久数据描述符12d 将取得目标的内容复制到新的目标,除非取出目标的OID被复制到新目标的持久数据描述符中12e 在散列表中为新目标产生新记录12f Ptr=新目标的指示字*/}13 将Ptr推到堆栈14 S1/*被编译程序的下一条指令紧随S1标号*/对增加的指令的解释如下。在该解释中,“参考目标”是包含对在此称之为“被参考目标”的另一个目标的一个指示字的目标。此外,应该理解表1和表2中的插入“指令”是伪指令,并且加入的实际指令的数量和格式将随使用的程序设计语言而变化。
增加的指令01直接检测被参考目标的目标指示字是否为零。如果目标指示字不是零,那么执行到标号S1的一个转移(指令02),恢复原始程序代码的执行。因此,当在主存中已经存在一个被参考的目标时,只执行一条增加的指令即非零指示字测试决定的一个条件转移指令。
如果被参考目标的目标指示字是零(指令01),那么使用剩余的指令(03至14)。指令03核查参考目标是否有一个持久数据描述符。如果不是,这可能是一个致命的错误,因为程序试图访问可能不存在的一个目标,并且指令04发出一个零指示字例外,它导致例外处理程序接管对程序的控制。
假定参考目标确有一个持久的数据描述符,指令04将不予执行,而是执行指令05,从参考目标的持久数据描述符得到被参考目标的目标识别符(OID)。
指令06确定OID是否为零。如果是,这表示程序极有可能在执行一个树或表遍历,并且已经到达叶节点。指令07在该点通过执行向S1标号的转移直接将控制传送回原始程序的下一条指令,在堆栈上留下一个零指示字。
接下来,假定已经找到一个非零OID,指令08访问散列表以请求与OID相关的目标指示字(如果有的话)。指令09检查散列表是否返回了一个非零目标指示字。如果是,这意味着被参考的目标已经在主存中了。在这种情况下,指令10将目标指示字复制到参考目标的适当字段中,指令18将目标指示字推向堆栈,然后控制在标号S1处返回到原始程序指令。
指令12只在指令09确定被参考目标不在主存中时才被执行。指令12调用数据库装入目标方法,该方法a)从数据库取得被参考的目标,b)产生并启动适当目标类的一个新事例,c)为该新目标产生一个持久数据描述符,d)将所取的目标的内容复制到新目标中,并且将任意OID(即对数据库中其它目标的参考)从已获取的目标复制到新目标的持久数据描述符中,以及e)在新目标的散列表中产生一个新的记录。指令14将新目标的目标指示字推进堆栈。然后控制返回到原始程序指令。
总之,增加的代码确定被参考的目标是否已在主存中,如果不是,它从数据库取出该目标,并将已取目标中的信息存储在主存的一个新目标中。这个代码只有在下面所述的程序位置上被加到原始编译程序中,即在该处(A)采用对已在主存中的一个目标的零目标指示字或(B)采用对还没被复制到主存中的一个目标的零目标指示字,程序就可以设法读出信息。
为“存放字段(Put Field)”指令所插入的代码如果当前指令(即由后处理程序指示字指示的那一个)是用于将信息存储到一个目标(在Java字节码语言中被称之为“存放字段”指令)中的一条指令(步骤258),那么表3所示的指令被加到程序中(步骤260)。为了便于引用,表3中增加的指令被编了号。
表3加到“在目标中存储信息”指令中的代码/*假定源代码为“E.G=V”,其中E是一个目标指示字,G指示一个字段E,V是被存储的值*//*在后处理之后,被编译的代码看上去是这样的*/Push E/*将指示一个目标的指示字推进堆栈*//*或者这可能是将一个目标指示字留在堆栈上的任何其它指令*/(下面参见正好在“Push V”指令之前由后处理程序插入到程序中以便标记目标为无效(如果还没被标记为无效的话)、并执行对更新目标指示字字段的指令的特殊处理的代码>Push V/*V是将要存储在目标中的数目、指示字或其它值*/Putfield G/*将信息存储到目标的字段G中*//*在Push V指令之前插入程序中的代码是*/31 在堆栈的顶部推进目标指示字的另一个备份32 PDD1=对目标的持久数据描述符的指示字33 如果PDD1是零{/*目标是一个平常的瞬态目标,因此这不可能被标记为无效*/34 Goto S2}35 LL=PDD 1.Link List/*LL是在PDDptr持久数据描述符中的已连接的表指示字的值*/36 如果LL不是零{/*目标已经被标记为无效*/37 Goto S2}/* 将目标标记为无效,并请求写锁定*/38 调用Database Mark Dirty(数据库标记无效)/*调用数据库方法*//* 该Mark Dirty方法也从该数据库请求一个Write Lock(写锁定)*/40 S2/* 只有当被写入的字段是一个目标指示字字段时下面的代码才被插入此时推进堆栈的值V是一目标指示字*/41 将V推进堆栈42 如果V是非零{43 PDD2=V.PDD/*对目标的持久数据描述符的指示字*/44 如果PDD2是零
{/*V目标是一个平常的瞬态目标,因此它没有OID要被插入到参考目标中*/45 Goto S3}46 OID1=V目标的OID47 将OID1存储在参考目标的持久数据描述符中的适当字段(即由PDD1指示的那一个)}48 S3/*将V推进的指令在原始已编译程序中S3标号之后,或者如果S2和S3标号之间的代码没被插入的话,则在S2标号之后*/对表2中加入的指令的解释如下指令S1和S2从一个目标(有时被称为参考目标)得到持久数据描述符指示字的一个备份。指令S3检查该指示字是否为零。如果指示字为零,这意味着参考目标是一个瞬态目标,不能被标记为无效,在这种情况下已插入代码的指令S4执行到标号S2的一个转移。
接下来,指令S5在参考目标的持久数据描述符中得到连接的表指示字,并且指令S6检查它是否为零。一个非零连接表指示字指示该目标先前已经被标记为无效,在这种情况下,被插入代码的指令S7执行到标号S2的一个转移。
如果参考目标有一个持久数据描述符,并且先前还没有标记为无效,那么指令S8调用数据库目标类的Mark Dirty(标记无效)方法,以便将目标标记为无效。Mark Dirty方法包括从数据库请求写锁定的指令。
只有在向其写入一个值的字段是一个目标指示字字段时,指令41至48才被加到原始编译程序中。指令41和42确定要被存储在参考目标中的值V是否为零目标指示字。如果要存储的值V是一个零目标指示字,那么控制被传送到标号S3之后的指令(即在原始编译程序中的“Push V”指令),因为没有OID要被存储在参考目标的持久数据描述符中。
如果要被存储的值V不是一个零目标指示字,指令43和44就确定由值V指示的目标是否有一个持久数据描述符。如果没有,那么没有OID要被存储在参考目标(即目标E)的PDD中,并且控制被传送到标号S3之后的指令。否则,由指令46得到相应于值V的OID,并且由指令47存储在被参考目标的持久数据描述符的适当字段中。
示于图5中的程序的步骤262和252在原始编译程序的每条指令被处理后才执行,并使指示字前进到下一条程序指令(如果有的话),并且确定后处理程序何时完成。
应该注意的是,由后处理程序产生的修正程序在最佳实施例中是一个有效的Java字节码程序。所以,在适当的时候,由后处理程序产生的修正程序可以被进一步编译为计算机平台的本机代码,该本机代码在该计算机平台上被执行。
在另一个实施例中,在大多数情况下,通过使用一个聪明的“零目标指示字”例外处理程序,可以避免在用于从一个目标中读出一个目标指示字字段的每条getfield(获得字段)指令之后插入如表1中所示的代码。每当运行期系统试图执行一条指令,例如一条getfield(获得字段)或putfield(放入字段)指令),该指令要求一个有效目标指示字被存储在操作数堆栈中,但该堆栈上的值是一个零目标指示字的值,这时就发生零目标指示字例外。
在这个实施例中,在图5的后处理程序的步骤250,后处理程序将一个零指示字例外处理程序加到正在处理的已编译数据库应用程序中,并且还修正程序的例外处理程序表,以便引用被插入的零指示字例外处理程序作为参考。修正步骤256,以便只有在零指示字例外处理程序在识别从中得到一个零目标指示字字段的参考目标可能有困难时,才将表1中所示的指令插在程序中(步骤268)。也就是说,如果使用一条目标指示字的第一条指令在程序中被移到远离从第一目标检索该目标指示字的指令的地方,那么例外处理程序可能不能识别那个第一目标。例如,考虑一个程序具有以下指令序列P1=从目标01的字段F2读出的目标指示字(许多插入指令,可能包括转移指令和读各种目标字段的其它指令>
将P1推到堆栈getfield F3在上面的例子中,如果“getfield F3”指令引起一个零指示字例外,例外处理程序可能不能确定在堆栈上的该零目标指示字是从目标01得到的。在这种情况下,后处理程序仍然在用于读出目标01的目标指示字字段的指令之后插入图1所示的代码。
在这个实施例中,当从一个目标读出一个非零目标指示字时,在绝大多数情况下在运行期不会出现额外量,而在第一个最佳实施例中,对每个这种getfield指令必须至少执行一条另外的指令(导致程序转移的一条非零检测指令)。
如上所述,每当被修正的数据库使用程序在程序执行过程中试图引用采用一个零指示字的目标时,零指示字例外处理程序就被调用。该修正的数据库使用程序(A)当它第一次试图执行一个“getfield”或“putfield”操作,以便访问还没有从数据库放入主存中的一个目标中的信息时,或者(B)当它采用一个在先前没有用来引用主存中的一个目标的一个目标中的目标指示字时,才应试图引用带有零指示字的一个目标作为参考。零指示字例外处理程序将在下面参考图6进行描述。
参看图6,零指示字例外处理程序执行以下步骤A)确定哪个目标(参考目标)包含引起零指示字例外的零目标指示字(280);B)如果参考目标没有一个持久数据描述符(281),那么再断言零指示字例外(282),以便导致下一个较高水平的例外处理程序(如果有的话)被调用;C)如果参考目标确实有一个持久数据描述符(281),那么从那个目标的持久数据描述符中得到相应的数据库目标ID(283);D)查找散列表中的目标ID看该目标的一个备份是否已经存储在主存中(284)了;E)如果该目标已经存储在主存(286,Y)了,那么用指向目标(从散列表中复制的)的主存目标指示字的复制件取代零指示字,将该目标指示字推进程序操作数堆栈,然后将控制返回到数据库使用程序,以使它重新执行导致零指示字例外的指令(288);F)如果目标还不在主存中(286,N),那么调用Database.Load Object(数据库装入目标)方法(289);以及G)接下来将控制返回到数据库使用程序,以使其重新执行导致零指示字例外的指令(299)。
数据库装入目标方法在调用时执行以下步骤H)请求并获得由目标ID参考的目标的一个备份;还请求并得到对DBMS目标的读锁定(290);I)相应于从DBMS接收的目标产生该目标类的一个新的目标实例,并且为该目标产生一个持久数据描述符(292);J)将DBMS目标的内容复制到新目标中,除非在新目标中的所有目标识别符被存储在新目标的持久数据描述符中并且主存中的目标识别符用零目标指示字替代(294);K)向散列表加入包含新目标的一个指示字的记录及其数据库目标识别符(296);以及L)将主存目标指示字的一个备份推进程序操作数堆栈指示字(298)。
虽然本发明是参考几个特定实施例进行描述的,但应该理解说明书只是对发明的示例性说明,而不能用来限制该发明。对本领域的技术人员来说,在不脱离由权利要求书限定的发明精神和范围的前提下,可以作许多修改。
权利要求
1.产生面向目标的计算机程序来存取和更新持久存储的目标的方法,包括以下步骤接收一个初始计算机程序,该程序包括原始指令,用于存取和更新存储在计算机主存中的目标;自动修改所述初始计算机程序,通过下述操作来产生修改的计算机程序加入目标装入指令,该指令在执行所述修改的计算机程序时,当每个所述相应目标被第一次存取时,将所述目标的相应的几个目标从持久存储器装入到所述主存中;加入目标存储指令,该指令在执行所述修改的计算机程序时,在出现预定事件时将所述计算机主存中的相应几个所述目标存储到所述持久存储器中。
2.根据权利要求1所述的方法,其中,所述修改步骤进一步包括加入无效目标标记指令,该指令在执行所述修改的计算机程序时,存储指示在所述计算机主存中的哪些目标包括新的和/或更新的数据的数据;其中所述目标存储指令在所述持久存储器中存储所述计算机主存中包含新的和/或更新的数据的那些所述目标。
3.根据权利要求1或2所述的方法,其中由所述原始指令存取和更新的所述目标包括在第一组目标类中的目标,并且由所述目标存储指令存储在所述持久存储器中的所述目标包括在第二组目标类中的目标,第二组目标类是所述第一组的子集;所述原始指令包括目标数据结构定义指令,用于定义与所述第一组目标类中的所述目标相关的数据结构;所述修改步骤进一步包括增加补充的目标定义指令,它修改与所述第二组目标类相关的所述数据结构,以便使得所述第二组目标类中的所述目标为由所述第二组目标类中的所述目标所参考的目标来存储主存目标指示字及持久存储器目标标识符。
4.根据权利要求3所述的方法,其中由所述目标装入指令装到主存中的目标包括在持久存储器中由装在主存中的所述目标所参考的目标的零目标指示字;所述修改步骤包括修改所述初始计算机程序,以便当所述第二组目标类中的一个目标的零目标指示字被存取时调用所述目标装入指令。
5.根据权利要求1所述的方法,其中由所述原始指令存取和更新的所述目标包括在第一组目标类中的目标,并且由所述目标存储指令存储在所述持久存储器中的所述目标包括在作为所述第一组的子集的第二组目标类中的目标;所述原始指令包括目标数据结构定义指令,用于定义与所述第一组目标类中的所述目标相关的数据结构;所述修改步骤进一步包括增加补充的目标定义指令,它们修改与所述第二组目标类相关的所述数据结构,以便使得所述第二组目标类中的所述目标为由所述第二组目标类中的所述目标所参考的目标来存储主存目标指示字和持久存储器目标标识符。
6.用于存储由在数据处理系统上执行的程序来存取的数据的一个存储器,所述存储器包括一个后处理程序,用于修改包括原始指令的初始计算机程序,该原始指令用于存取和更新存储在计算机主存中的目标;所述后处理程序包括用于自动修改所述初始计算机程序的指令,以便通过向所述初始计算机程序加入增补指令来产生修改的计算机程序,所述增补指令包括目标装入指令,它们在执行所述修改的计算机程序时,当每个所述相应目标被第一次存取时,将所述目标的相应几个目标从持久存储器装入到所述主存中;目标存储指令,该指令在执行所述修改的计算机程序时,在出现预定事件时将所述计算机主存中的相应几个所述目标存储到所述持久存储器中。
7.根据权利要求6所述的存储器,其中所述增补指令包括无效目标标记指令,该指令在执行所述修改的计算机程序时,存储指示在所述计算机主存中的哪些目标包括新的和/或更新的数据的数据;其中所述目标存储指令在所述持久存储器中存储所述计算机主存中包含新的和/或更新的数据的那些所述目标。
8.根据权利要求6或7所述的存储器,其中由所述原始指令存取和更新的所述目标包括在第一组目标中的目标,并且由所述目标存储指令存储在所述持久存储器中所述目标包括了在第二组目标类中的目标,该第二组是所述第一组的子集;所述原始指令包括目标数据结构定义指令,用于定义与所述第一组目标类中的所述目标相关的数据结构;所述增补指令进一步包括增补目标定义指令,该指令修改与所述第二组目标类相关的所述数据结构,以便使得所述第二组目标类中的所述目标为由所述第二组目标类中的所述目标所参考的目标来存储主存目标指示字及持久存储器目标标识符。
9.根据权利要求8所述的存储器,其中由所述目标装入指令装到主存中的目标包括在持久存储器中由装在主存中的所述目标所参考的目标的零目标指示字;所述后处理程序修改所述初始计算机程序,以便当所述第二组目标类中的一个目标的零目标指示字被存取时,调用所述目标装入指令。
10.根据权利要求6所述的存储器,其中由所述原始指令存取和更新的所述目标包括在第一组目标类中的目标,并且由所述目标存储指令存储在所述持久存储器中的所述目标包括在作为所述第一组的子集的第二组目标类中的目标;所述原始指令包括目标数据结构定义指令,用于定义与所述第一组目标类中的所述目标相关的数据结构;所述增补指令进一步包括增补的目标定义指令,它们修改与所述第二组目标类相关的所述数据结构,以便使得所述第二组目标类中的所述目标为由所述第二组目标类中的所述目标所参考的目标来存储主存目标指示字和持久存储器目标标识符。
11.一个计算机系统,包括存储器,包含有用于存储目标的一个主存储器;所述存储器进一步存储初始计算机程序、修改的计算机程序和后处理器程序,后处理程序用于修正包括用于存取和更新在所述主存中存储的目标的原始指令的初始计算机程序;所述后处理程序包括用于自动修改所述初始计算机程序的指令,以便通过向所述初始计算机程序增加补充指令来产生修改的计算机程序,所述补充指令包括目标装入指令,该指令在执行所述修改的计算机程序时,当每个所述相应目标被第一次存取时,将所述目标的相应几个从持久存储器装入到所述主存中;以及目标存储指令,该指令在执行所述修改的计算机程序时,在出现预定事件时就将所述计算机主存中的相应几个所述目标存储到所述持久存储器中。
12.根据权利要求11所述的计算机系统,其中,所述补充指令包括无效目标标记指令,该指令在执行所述修改的计算机程序时,存储指示在所述计算机主存中的哪些目标包括新的和/或更新的数据的数据;其中所述目标存储指令在所述持久存储器中存储所述计算机主存中包含新的和/或更新的数据的那些所述目标。
13.根据权利要求11或12所述的计算机系统,其中由所述原始指令存取和更新的所述目标包括在第一组目标类中的目标,并且由所述目标存储指令存储在所述持久存储器中的所述目标包括了在第二组目标类中的目标,该第二组是所述第一组的子集;所述原始指令包括目标数据结构定义指令,用于定义与所述第一组目标类中的所述目标相关的数据结构;所述补充指令进一步包括增补目标定义指令,该指令修改与所述第二组目标类相关的所述数据结构,以便使得所述第二组目标类中的所述目标为由所述第二组目标类中的所述目标所参考的目标来存储主存目标指示字及持久存储器目标标识符。
14.根据权利要求13所述的计算机系统,其中由所述目标装入指令装到主存中的目标包括在持久存储器中由装在主存中的所述目标所参考的目标的零目标指示字;所述后处理程序修改所述初始计算机程序,以便当所述第二组目标类中的一个目标的零目标指示字被存取时,调用所述目标装入指令。
15.根据权利要求11所述的计算机系统,其中由所述原始指令存取和更新的所述目标包括在第一组目标类中的目标,并且由所述目标存储指令存储在所述持久存储器中的所述目标包括在作为所述第一组的子集的第二组目标类中的目标;所述原始指令包括目标数据结构定义指令,用于定义与所述第一组目标类中的所述目标相关的数据结构;所述增补指令进一步包括增补的目标定义指令,该指令修改与所述第二组目标类相关的所述数据结构,以便使得所述第二组目标类中的所述目标为由所述第二组目标类中的所述目标所参考的目标来存储主存目标指示字和持久存储器目标标识符。
全文摘要
用于将存取主存中存储的目标的编译程序自动转换为存取并更新持续存储的目标的程序的系统和方法。初始程序包括一些原始指令。该原始指令系统来自动修改初始计算机程序。当一个持续存储的目标第一次被存取时,目标装入指令将其一个备份装入主存的一个相应目标中。目标存储指令只将主存中包含新的或更新后的数据的目标复制到相应的持续存储目标中。该系统产生修改的计算机程序,做法是在原始指令中加入无效目标标记指令,该指令跟踪主存中哪些目标包含新的和/或更新的数据。
文档编号G06F12/00GK1161505SQ97101080
公开日1997年10月8日 申请日期1997年2月5日 优先权日1996年2月9日
发明者西伦·D·托克, 罗德里克·G·G·卡特尔 申请人:太阳微系统有限公司