Brief: Activation groups are a critical and confusing aspect of ILE technology.
With a better understanding of activation groups, you can improve your ILE
programming skills across the board. This article will explain the concepts
behind activation groups and help you put them to work for you.
In my last article ("V3R1 Announcement Follow-up: An Introduction to Program
Binding," MC, August 1994), I talked about program binding in ILE. This article
will concentrate on the ILE feature of activation groups. An activation group
is not specific to any ILE language. As such, this article will remain ILE
language-independent for the most part, and will only talk about specific
languages to show how they may achieve a particular ILE behavior.
The first thing that this article will do is introduce you to what an
activation group is. It will then show you how activation groups are used. In
doing so, I will try to illustrate the benefits of knowing how activation
groups work; i.e., resource isolation and performance considerations.
An activation group is similar to an extended program model (EPM) environment.
Since only EPM C/400 and PASCAL/400 used EPM, RPG and COBOL users will not be
familiar with EPM environments, so I will explain activation groups from the
beginning.
Activation groups are probably the most critical concept to know in ILE, and
probably one of the hardest to understand. Therefore, I will relate activation
groups to a concept you should be more familiar with: a cardboard box. Think of
an activation group in terms of a box. A box can contain various items, whereas
an ILE activation group contains resource. A box has storage space, whereas an
activation group has heap storage (the heap refers to storage that can be
dynamically allocated, reallocated and freed), static, and automatic storage.
This may be stretching it a little bit, but you could think of the strength of
the box's material as analogous to the commit scope in an activation group.
What I am trying to get across is that even though an activation group is not a
physical item, it still has certain characteristics that are defined by the
resources it owns. More precisely, an activation group is used to own resources
for an ILE application. A few of the resources that are owned by an activation
group are program static and automatic variables, heaps, Open Data Paths
(ODPs), and commit scope. Given that these resources are all scoped to an
activation group in ILE, this allows for optional isolation of applications,
giving the following results:
o Much larger amounts of storage can be made available to an application.
(This is possible because ILE activation groups have far greater storage
available to them than OPM applications; and multiple activation groups can
exist in an application, each with their own storage allocation.)
o Independent file sharing (when sharing is limited to an activation group).
o Independent commitment control (within the activation group).
o Isolated error handling within an application (based on activation group
boundaries).
o Addressing protection.
Activation Group Creation
Now that you have a general idea of what is owned by activation groups, the
next logical questions are, "How are activation groups created, and what is the
correspondence between activation groups and programs?" An active activation
group can contain running programs and/or service programs.
Going back to the box analogy, you can think of an active activation group as
an open box that has some items inside. I have to point out that an activation
group is not a physical object on the system like a program, but rather is
created (activated) when a program is run. The determination of which
activation group a program is activated into is done at the program creation
step. The ACTGRP parameter of the Create Program (CRTPGM) command allows you to
specify *NEW, *CALLER, or the name of an activation group.
Although you specify the activation group on the CRTPGM command, the activation
group is not created until the program is called.
1 illustrates calling a program that was created with ACTGRP(*NEW). The
Figure 1 illustrates calling a program that was created with ACTGRP(*NEW). The
system will always create a new activation group when the program is called, as
well as clean up the activation group when the program is done. Note that the
system will generate a name for the activation group that is created. In this
example, the system-generated name for the activation group is 1579234.
2 shows what happens when a program is created with ACTGRP set to a
Figure 2 shows what happens when a program is created with ACTGRP set to a
given name. As illustrated in step three, the first time program ORDERENTRY is
called, the activation group ORDENT will be created, and all static storage
will be allocated and initialized. Step five shows what happens the second time
ORDERENTRY is called. In this case, the activation group ORDENT already exists,
so no activation group is created, and the program ORDERENTRY reattaches to the
activation group ORDENT.
Notice that no static initialization is done the second time ORDERENTRY is
called. Calling a program the second time when it is in a named activation
group is similar in notion to calling an Original Program Model (OPM) RPG
program a second time when you are using LR off. The above is true in the
"strictest letter of the law" sense for ILE. ILE RPG, however, is the one
exception to this generalization. If you are entering a named activation group
for the second time in ILE RPG and the first call ended with LR on, then the
RPG program will do the static initialization. This is deviating from one of
the intents of a named activation group in ILE, but ILE RPG must retain
compatibility with earlier versions of RPG for the case when LR is on.
3 illustrates calling a program that was created with ACTGRP *CALLER. In
Figure 3 illustrates calling a program that was created with ACTGRP *CALLER. In
this example, a program INVENTORY is created with ACTGRP *CALLER. When
INVENTORY is called from program ORDERENTRY (from the previous example), it
runs in activation group ORDENT. When program INVENTORY is finished running,
activation group ORDENT continues to exist with program ORDERENTRY still
running in it, even though INVENTORY is no longer active.
The ACTGRP parameter is also available on the Create Service Program
(CRTSRVPGM) command. The valid values are *CALLER or the name of an activation
group.
Notice that *NEW is not an option. The *CALLER and name values function in the
same fashion as on the ACTGRP parameter on the CRTPGM command.
Getting Rid of Activation Groups
Now that you know how activation groups are created, I would like to talk about
how activation groups are destroyed. Before I do this, though, I need to
discuss the concept of a control boundary. A control boundary is a call stack
entry that exists within your application whenever you call between activation
groups.
To be a little more precise, a control boundary is either an ILE call stack
entry whose immediately preceding call stack entry is in a different activation
group, or an ILE call stack entry whose immediately preceding call stack entry
is an OPM program. These definitions are a little dry, but I will show various
examples that will illustrate how control boundaries work later in the article.
Now that control boundaries are out of the way, we can move onto terminating
activation groups.
In order to understand how activation groups are terminated, it is best to
classify the ways that you can leave an activation group. The two forms of
leaving an activation group are a hard leave and a soft leave. Soft leaves have
the characteristic that they return to the immediate caller and the activation
group is left in the process. They will also leave files open, and static
storage for all programs is left in the last-used state. In other words, the
activation group and its associated resources are left in a last-used state.
Hard leaves are classified as either normal or abnormal hard leaves. The
characteristic of a hard leave is that it will cancel call stack entries until
it reaches a control boundary.
If the control boundary is the first one in an ILE activation group, then the
activation group will be destroyed. After the activation group is destroyed,
control will return to the caller of the destroyed activation group. Before the
activation group is destroyed, the activation group's files will be closed;
OS/400 will free up the storage and will do an implicit commit or rollback.
4 shows the language verbs used to achieve soft and hard leaves in
Figure 4 shows the language verbs used to achieve soft and hard leaves in
different languages. Refer to the sidebar, "The Details of Activation Group
Termination," for examples that illustrate how soft and hard leaves function
for *NEW, *CALLER, and named activation groups.
You can use the ILE APIs CEETREC and CEE4ABN from any ILE language to achieve a
hard leave. Furthermore, when an unhandled function check reaches a control
boundary, it will follow the same rules as the language verbs for hard leaves
in terms of terminating the activation group. With regards to clean up,
however, the semantics can be different (this falls under a separate discussion
on exception handling, which I will not be going into in this article).
Now that you understand how activation groups are created and destroyed, I
should mention where activation groups existùwithin jobs. As my previous
examples show, you can have one or more activation groups within a given job,
but you cannot share activation groups across jobs. This should be easy to
remember if we go back to my box analogy. If you consider a storage locker to
be a job, then it is easy to remember that you can have multiple boxes
(activation groups) in a storage locker (job), but you cannot share a box
between storage lockers.
There are always two special activation groups on the systemùthe user default
activation group and the system default activation group. The system default
activation group is used only by operating system functions, so I will skip
over it.
The more interesting activation group is the user default activation group,
which I will refer to as the Default Activation Group (DAG). There are a few
things that make the DAG special. First, every job has a DAG. Second, all OPM
programs run in the DAG.
You may not have realized that in V2R3 all RPG and COBOL programs ran in the
DAG. Yes, this does mean that OPM applications actually are running under ILE.
It is the special characteristics of the DAG that enable OPM programs to run
under ILE and still keep the same behavior they had prior to V2R3. Another
special characteristic is that you cannot delete the DAG. The DAG can only be
deleted by the operating system when your job ends.
Performance Considerations
It is very important from a performance standpoint to realize that activation
group creation is not very fast. Once again drawing an analogy to a box, it is
much faster to put items into a box that is already created than to have to
take cardboard, fold it, cut it, and tape it to create a box. In the same way,
an activation group takes time to start off before the application starts
running. If you reattach to an activation group that is already running, then
you can start the application almost immediately.
Reattaching to an activation group is possible when using either *CALLER or a
named activation group. 5 shows two possible ways to set up an
named activation group. Figure 5 shows two possible ways to set up an
application. Method one has program MAINPGM running in an activation group
called ONE. Each service program that MAINPGM is calling functions from is
running in its own named activation group. Method two has program MAINPGM
running in an activation group called ONE and has all of the service programs
running in *CALLER. Thus, all the service programs will be activated into
activation group ONE. Method one would have better isolation of resources (I'll
talk more about this shortly), but would have far poorer start-up performance
than method two.
To further illustrate the benefits of understanding activation groups from a
performance standpoint, 6 cites some performance figures for calling an
performance standpoint, Figure 6 cites some performance figures for calling an
RPG program (or procedure) a large number of times. These performance numbers
were obtained under lab conditions on a V3R1 system and will not necessarily be
achieved in any given AS/400 environment. Further, I have normalized the
numbers and rounded them off. I use this data to give you a rough idea of how
important it is to understand activation groups and the major benefits you can
get by using activation groups effectively. I would encourage you to conduct
your own tests in your environment.
The OPM numbers, which shouldn't be a big surprise to RPG programmers, can be
taken at face value. If the ILE RPG program is running in the DAG, the ILE
numbers are better than OPM since there are some savings inherent in the
initialization done by ILE RPG. You can see the huge performance benefit when
calling a named activation group. The main reason for this performance increase
is due to persistence. In other words, the resources you use will stay around.
Given this, be aware that if you call into a named activation group over and
over again, and use new resources each time, you may eventually run into
resource (e.g., storage) problems, because the amount of resources you are
using would continue to grow. The incredibly high numbers for calling into a
*NEW activation group are due to the time required to create and activate each
*NEW activation group.
Notice that the difference between using LR on and LR off is lost when using a
*NEW activation group. Finally, notice the improved times when using a CALLB
(call bound) over a CALL (external call). The difference between a CALLB with
LR off and a CALL with LR off is the difference in performance between an
external call and a bound call. In the case of LR on, the CALLB case is faster
because of the increased speed of a bound call and because there is no
deactivate program required.
I hope this has solidified some of the benefits you get from a performance
standpoint if you understand ILE, particularly activation groups.
Resource Scoping
The last thing I would like to discuss is the scoping of resources. Resource
scoping refers to how resources are shared and the locality of where the
resources exist. The simplest resource to understand is the storage for your
application. Storage for a program is scoped to an activation group.
Thus, if your application is made up of two activation groups, you will have
two isolated storage areas. Having two separate storage areas can protect
sensitive data within an application from being damaged from things like "wild
pointers."
Separate storage areas will also allow the application designer to break an
application into separate logical entities whose data areas must only be
accessible within each entity. For example, you may have an application that
has an order entry portion, as well as a payroll portion. In this case, you
would put the order entry portion in one activation group and the payroll
portion in another. This would prevent any user of the order entry system from
being able to access the payroll data. Because of this isolation, we often
refer to an activation group as a firewall for resources.
As mentioned at the beginning of the article, the heap storage for your
application is also scoped to an activation group, as is the name space for
exported procedures.
The last type of resource scoping I will discuss is Data Management scoping.
There are many different types of Data Management resources, such as open file
operations, overrides, commitment definitions, and local SQL cursors. Each Data
Management resource has certain defining rules and default settings on how they
are scoped, be it call level, activation group, or job scoped. Thus, I will
just talk about one of the main ones, and refer you to the ILE Concepts guide
if you want further information on the other resources.
The Data Management resource I will discuss is overrides. Normally, the extent
of a file override is to the call level, so that only programs running lower in
the invocation stack are affected. Now, with ILE, you have far more flexibility
in how you can control overrides. To cite a specific example, the OVRDBF
command has an option for the override scope called OVRSCOPE.
The possible choices for this option are *ACTGRPDFN, *CALLLVL, and *JOB.
Obviously, *JOB means that there will be job level scoping, and *CALLLVL means
that there will be call level scoping. The *ACTGRPDFN choice is a little more
interesting. If you specify *ACTGRPDFN and the caller is in the DAG, then you
will get call level scoping on the overrides. If you specify *ACTGRPDFN and the
caller is not in the DAG, then the overrides will be scoped to the activation
group of the calling program.
As you can see, ILE gives you flexibility in terms of how you control the
resources within your application. In ILE, you have the ability to control
resources at a more granular level. More importantly, you can control resources
at a more logical level. For example, you may want your order entry application
to have its resources separate from the rest of your application. This can
easily be achieved by having the order entry portion of your application run in
its own activation group, and scoping the resources to the activation group.
I've introduced many different concepts, which are summarized in 7. As
I've introduced many different concepts, which are summarized in Figure 7. As
illustrated, activation groups are scoped to a JOB. Also demonstrated is the
fact that there can be many activation groups within a JOB. Activation groups
can have one or more programs or service programs running in them.
The three ways to specify which activation group a program or service program
is activated into are *NEW, *CALLER, and name. If you want to have an ILE
program run in the default activation group, then you must create the ILE
program as *CALLER and call it from an OPM program, as illustrated for the DAG.
You can have multiple programs and service programs activated into a named
activation group, as shown in the example for MYNAMEDAG. The activation group
MYNAMEDAG also shows that a service program can be bound by reference to
multiple different programs. Activation group 187526 shows that an activation
group will be created when you call a program that was created with
ACTGRP(*NEW). It also shows that service programs can be activated into an
activation group that was created as *NEW if the service program was created
with ACTGRP(*CALLER). Lastly, as a review, ILE programs and service programs
are created from one or more *MODULE objects.
All of the preceding verbiage leads to one conclusion: by understanding ILE,
and activation groups in particular, you will be able to design applications
that have better performance, and you will have much better control of how your
resources are used and protected within the application.
Glen Sakuth is a computer engineer working in the AS/400 Languages Design
Control Group (DCG) at the IBM Toronto Lab. He was one of the principle
designers and programmers of the CUBE-3 back-end used by all ILE languages. He
is currently the architect for the ILE C/400 compiler and the performance DCG
for all ILE languages. He is a frequent speaker at COMMON conferences and can
be reached through Internet at
Activation Group Concepts
Figure 1Using a *NEW Activation Group
UNABLE TO REPRODUCE GRAPHICS
Activation Group Concepts
Figure 2Using a Named Activation Group
UNABLE TO REPRODUCE GRAPHICS
Activation Group Concepts
Figure 3Using a *CALLER Activation Group
UNABLE TO REPRODUCE GRAPHICS
Activation Group Concepts
Figure 4Language Verbs for Hard and Soft Leaves
Language Soft Leave Normal Hard Leave Abnormal Hard Leave --------------------------------------------------------------------- ILE API N/A CEETREC CEE4ABN ILE C return() if exit() or return() abort not in main() from main() ILE RPG RETURN with CALLB to CEETREC CALLB to CEE4ABN LR on or off ILE COBOL N/A STOP RUN CALL to CEE4ABN
Activation Group Concepts
Figure 5Two Methods of Setting Up Activation Groups
UNABLE TO REPRODUCE GRAPHICS
Activation Group Concepts
Figure 6Calling Times for an Empty RPG Program
OPM ILE(DAG) ILE(named AG) ILE(*NEW AG) -------------------------------------------------------------- CALL (LR ON) 121.6 90.5 7.2 4744.6 CALL (LR OFF) 5.7 4.7 4.8 4744.6 CALLB (LR ON) N/A 2.7 Similar to N/A (*CALLER) ILE (DAG) CALLB (LR OFF) N/A 1.0 Similar to N/A (*CALLER) ILE (DAG)
Activation Group Concepts
Figure 7Activation Group Concepts Summary
UNABLE TO REPRODUCE GRAPHICS
LATEST COMMENTS
MC Press Online