ClearQuest V7.1从乐观锁定到悲观锁定
 

2009-12-25 作者:高嫄 来源:IT168

 

随着IT科技的不断普及,越来越多公司引入项目管理工具,这使得项目管理更具有实时性,并更加透明化。ClearQuest是一个在项目管理中常用的工具,项目参与者不仅可以通过它实时更新项目,同时也可以了解项目其他成员的进度和相关情况。

当多人次同时对同一记录编辑时,显然需要软件拥有一种处理机制来避免由于这样的操作所带来信息冲突和不便。在这种情况下,ClearQuest应对不同的客户需求,提供了两种解决机制,称之为"乐观锁定"和"悲观锁定"。

1. 背景介绍

在ClearQuest v7.1以前的版本中,只有一种锁定机制"乐观锁定"。它使用户很方便地更新数据,不需要做任何设置更改,也不需要在乎其他人对该记录的操作,只要该用户直接编辑,便可顺利的完成整个数据更新步骤。从而使用户避免了复杂的加锁解锁操作。这种情况下,在一条数据被"Apply"后,同时更新该记录的其他用户只允许编辑,而不能"Commit"。

然而在使用的过程中,越来越多的用户发现这种处理机制带来了很多的不方便,常常做了很多更改后才发现不能"Apply",而不得不重新来做。如何使用户在编辑时就知道,该记录已经被锁定,从而避免做无用功呢?在ClearQuest v7.1中,一种新的锁定机制被引用"悲观锁定"。如果用户A希望某条记录只能由自己编辑,其他人在这期间想要更新该记录时,可以得到提示表明该记录已被用户A 锁定,便可使用"悲观锁定"。该机制需要用户做一些简单的设置才能生效。下图说明了"悲观锁定"的工作方式。

接下来,本文会着重介绍ClearQuest v7.1中这种新的锁定机制"悲观锁定"。

2. 悲观锁定简介

概括的说,悲观锁定避免了在乐观锁定时,用户同时编辑记录的冲突,让每条记录有顺序的被更新。

2.1 悲观锁定的特点

  • 悲观锁定适用Feature level 7的数据库
  • 使用Hook脚本对其设置
  • 在执行"Apply","Revert"或是超时后,锁定记录被自动解锁
  • 超级用户可以强制性解除锁定,每个用户也可以解除自己的锁定
  • 可以使用"Lock_by"域来查询被锁记录

2.2 设置悲观锁定

ClearQuest v7.1中不能直接通过客户端使用悲观锁定,必须通过一定的配置来实现该功能。下面以一个常用的操作为例子,介绍一下如何进行设置。

假设两个用户Alice,Bob同时更改记录SAMPL00000001,Alice对该记录做了锁定设置,当Bob此时想要编辑该记录时,被提示该记录被锁定,通知管理员解锁。

第一步,在ClearQuest Designer中新建一个类型为Base的行为Lock,对该行为新建一个初始化行为(Action_Initialization)脚本LockRecord,编写脚本:"$entity->LockRecord(0)",这里我们选用perl脚本作为编辑脚本。

第二步,用类似的方法再建一个UnLockRecord行为,选择此行为的类型为RECORD_SCRIPT_ALIAS,新建记录脚本UnLockRecord,并与UnLockRecord行为关联。

脚本UnLockRecord:

    sub Defect_UnlockRecord {
        my($result);
        my($param) = @_;
        # record type name is Defect  
        $result = "";
        my $locked_by = $entity->GetLockOwner();
        if ($locked_by ne "") {
            my $do_unlock = $session->IsUserSuperUser();
            if (! $do_unlock) {
                # If the current user holds the lock, let them unlock it.
                my $username = $session->GetUserLoginName();
                if ($username =~ /^$locked_by$/i) {
                    $do_unlock = 1;
                }
            }
            if (! $do_unlock) {
                # Additional options to "authorize" unlocking:
                # 1) allow if user is a member of an "unlock" group
                #    get user's groups, check if member
                # 2) allow for privileged users, e.g. Security Administrator
                #    check session for the chosen privilege
                # 3) many other possibilities
                #
                # if ( user-should-be-allowed-to-unlock-the-record ) {
                #     $do_unlock = 1;
                # }
            }
            if ($do_unlock) {
                $entity->UnlockRecord();
            }
            else {
                $result = "You are not allowed to unlock this record.";
            }
        }
        return $result;
    }

现在升级你的数据库,至此我们便完成了锁定设置。

接下来,在ClearQuest客户端中建立一个对锁定记录的查询,这里使用域"Lock_by"作为filter,选择觉得可能的Owner。值得提一下的是,这个域在v7.1之前作filter是无效的,而在v7.1中加入悲观锁定功能后,通过它可以看到哪些记录被锁了,谁锁了等等这些信息。

2.3 验证

下面检验一下刚才的设置。

第一步,使用ClearQuest Administrator创建两个用户Alice,Bob,见下图。

第二步,分别使用Alice和Bob两个帐号登录ClearQuest客户端。先让我们检查一下Unlock Action是不是在Action Dropdown list中以及新建的域Lock_by能否在客户端显现。

第三步,假设Alice正在对记录SAMPL00000001编辑,Bob试图修改该记录,发现此记录被锁,于是告知管理员希望他解除锁定。

第四步,在进行解锁之前,我们利用刚才建的查询,查看一下,现在被锁定的记录,返回结果当前只有一条记录被锁,即SAMPL00000001。

第五步,我们有Apply,Revert和Unlock三种方式解除记录锁定,先看看这三种方式有什么不同。

Apply -- Bob在此动作后编辑SAMPL00000001,会发现自己仍然不能进行操作,这是因为此时两人所属的数据库并不同步,Bob如果想要继续编辑记录,需要重新连接数据库.

Revert -- 大家应该已经猜到了,这个时候Bob可以成功编辑SAMPL00000001

Unlock -- 这是通过hook脚本来解除锁定,所以Bob也可以编辑SAMP SAMPL00000001

对于前两种操作,作为用户的Alice都可以帮助Bob解除记录锁,但是如果想要使用Unlock动作,我们必须通知高级管理员,普通用户并没有权限执行该动作。

第六步,这里我们用上面设置的Unlock行为来解锁。使用Admin用户登录ClearQuest客户端,点击"Unlock"。回头再来看看,Bob现在能不能编辑SAMPL00000001。可以看到,现在Bob可以成功编辑SAMPL00000001了。

3. 补充

实际上,锁定一条或多条记录,除了上面讲到的建立一个Base的行为Lock以外,也可以类似与Unlock行为一样,建立一个类型为RECORD_SCRIPT_ALIAS的Lock行为,这样做可以方便用户自己决定是否锁定记录。

感兴趣的朋友还可以通过findrecordlocks.pl 进一步找到当前被锁记录的一些相关信息,该脚本在ClearQuest V7.1的安装目录下 \IBM\RationalSDLC\ClearQuest\,运行:

    cqperl findrecordlocks.pl  [-dbset <dbset_name>]
                               [-database <user_database>]
                               <clearquest_login>
                               <clearquest_password>
                               { <record_type_list> | -all }
                               [-unlock]
                               [-scan <interval>]
                               [-timeout <interval>]
                               [-times <times>]
                               [-loglevel <error|info|verbose>]

以上面的记录SAMPL00000001为例,Alice锁住了记录SAMPL00000001,运行:

cqperl "F:\Program Files\IBM\RationalSDLC\ClearQuest\findrecordlocks.pl"-dbset ss admin "" Defect,看看结果是不是如实际操作的一样。

4. 附录

类型为RECORD_SCRIPT_ALIAS的Lock行为的perl脚本

    sub Defect_LockRecord {
        my($result);
        my($param) = @_;
        # record type name is Defect

        if (ref ($param) eq "CQEventObject") {
            # add your CQEventObject parameter handling code here
        } elsif (ref (\$param) eq "SCALAR") {
            # add your scalar parameter handling code here
            # The Web clients support scalar paramter type only,
            # so the hook code added in the above section, needs to be duplicated here
        } else {
            # add your handling code for other type parameters here, for example:
            # die("Unknown parameter type");
    }
    $entity->LockRecord(0);
        return $result;
    }

5.结束语

本文介绍了ClearQuest V7.1中的记录锁定机制,重点让大家了解了两种锁定机制及如何使用"悲观锁定。"

火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。

资源网站: UML软件工程组织