8.3 Enforce Serial Deliver Operations

Because UCM allows multiple developers to deliver work to the same integration stream concurrently, conflicts can occur if two or more developers attempt to deliver changes to the same element. If one developer's deliver operation has an element checked out, the second developer cannot deliver changes to that element until the first deliver operation is completed or canceled. The second deliver operation attempts to check out all elements other than the checked-out one, but it does not proceed to the merge phase of the operation. The second developer must either wait for the first deliver operation to finish or undo the second deliver operation.

You may want to implement a development policy that eliminates the confusion that concurrent deliveries can cause developers. This section shows three Perl scripts that prevent multiple developers from delivering work to the same integration stream concurrently:

Setup Script

This setup script creates a preoperation trigger type, a postoperation trigger type, and an attribute type. The preoperation trigger action fires when a deliver operation starts, as represented by the deliver_start operation kind (opkind). The postoperation trigger action fires when a deliver operation is canceled or completed, as represented by the deliver_cancel and deliver_complete opkinds, respectively.

The script runs on both UNIX and Windows platforms. Because the command-line syntax to run the preoperation and postoperation scripts on Windows differs slightly depending on whether the PVOB resides on Windows or UNIX, the setup script uses an IF ELSE Boolean expression to set the appropriate execwin command.

The mktrtype command uses the -ucmobject and -all options to specify that the trigger type applies to all UCM objects in the PVOB, but the -stream option restricts the scope to one integration stream.

The mkattype command creates an attribute type called deliver_in_progress, which the preoperation and postoperation scripts use to indicate whether a developer is delivering work to the integration stream.

# perl script to set up triggers for enforcing serial delivery.
use Config;

# define platform-dependent arguments.
my $PVOBTAG;
my $PREOPCMDW;
my $POSTOPCMDW;
if ($Config{'osname'} eq 'MSWin32') {
$PVOBTAG = '\cyclone_pvob';
$PREOPCMDW = '-execwin "ccperl \\\\pluto\disk1\ucmtrig_examples\ex1\ex1_preop.pl"';
$POSTOPCMDW = '-execwin "ccperl \\\\pluto\disk1\ucmtrig_examples\ex1\ex1_postop.pl"';
}
else {
$PVOBTAG = '/pvobs/cyclone_pvob';
$PREOPCMDW = '-execwin "ccperl \\\\\\pluto\disk1\ucmtrig_examples\ex1\ex1_preop.pl"';
$POSTOPCMDW = '-execwin "ccperl \\\\\\pluto\disk1\ucmtrig_examples\ex1\ex1_postop.pl"';
}

my $PREOPCMDU = '-execunix "Perl /net/pluto/disk1/ucmtrig_examples/ex1/ex1_preop.pl"';
my $POSTOPCMDU = '-execunix "Perl /net/pluto/disk1/ucmtrig_examples/ex1/ex1_postop.pl"';
my $STREAM = "stream:P1_int\@$PVOBTAG";
my $PREOPTRTYPE = "trtype:ex1_preop\@$PVOBTAG";
my $POSTOPTRTYPE = "trtype:ex1_postop\@$PVOBTAG";
my $ATTYPE = "attype:deliver_in_progress\@$PVOBTAG";

# set up the trigger types and attribute type.
print \Qcleartool mktrtype -ucmobject -all -preop deliver_start $PREOPCMDU $PREOPCMDW -stream $STREAM -nc $PREOPTRTYPE\Q;
print \Qcleartool mktrtype -ucmobject -all -postop deliver_complete, deliver_cancel $POSTOPCMDU $POSTOPCMDW -stream $STREAM -nc $POSTOPTRTYPE\Q;
print \Qcleartool mkattype -vtype integer -default 1 -nc $ATTYPE\Q;

Preoperation Trigger Script

This preoperation trigger action fires when a developer begins to deliver work to the specified integration stream. The script attempts to attach an attribute of type deliver_in_progress to the integration stream. If another developer is in the process of delivering work to the same stream, the mkattr command fails and the script displays a message suggesting that the developer try again later. Otherwise, the mkattr command succeeds and prevents other developers from delivering to the integration stream until the current deliver operation finishes.

# perl script that fires on deliver_start preop trigger.
use Config;

# define platform-dependent arguments.
my $PVOBTAG;
if ($Config{'osname'} eq 'MSWin32') {
$PVOBTAG = '\cyclone_pvob';
}
else{
$PVOBTAG = '/pvobs/cyclone_pvob';
}
my $STREAM = $ENV{"CLEARCASE_STREAM"};
my $ATTYPE = "attype:deliver_in_progress\@$PVOBTAG";

# try to create the attribute, capture the output.
$msg = 'cleartool mkattr -default $ATTYPE $STREAM 2>&1';

# if the attribute already existed, a deliver is in progress, disallow this delivery.
if (index($msg, "Error: Object already has an attribute") >= 0) {
print "***\n";
print "*** A deliver operation is already in progress. Please try again later.\n";
print "***\n";
exit 1;
}

# the attribute was created, deliveries will be disallowed until postop fires.
exit 0

Postoperation Trigger Script

This postoperation trigger action fires when a developer cancels or completes a deliver operation to the specified integration stream. This script removes the deliver_in_progress attribute that the preoperation script attaches to the integration stream at the start of the deliver operation. After the attribute is removed, another developer can deliver work to the integration stream.

# perl script that fires on deliver_complete or deliver_cancel postop trigger.
use Config;

# define platform-dependent arguments.
my $PVOBTAG;
if ($Config{'osname'} eq 'MSWin32') {
$PVOBTAG = '\cyclone_pvob';
}
else{
$PVOBTAG = '/pvobs/cyclone_pvob';
}
my $STREAM = $ENV{"CLEARCASE_STREAM"};
my $ATTYPE = "attype:deliver_in_progress\@$PVOBTAG";

# remove the attribute to allow deliveries.
print \Qcleartool rmattr -nc $ATTYPE $STREAM\Q;
exit 0;