The FreezeScript tool dumpdb is used to examine a Freeze database. Its simplest invocation displays every record of the database, but the tool also supports more selective activities. In fact,
dumpdb supports a scripted mode that shares many of the same XML descriptors as
transformdb (see
Section 37.4), enabling sophisticated filtering and reporting.
A dumpdb descriptor file has a well-defined structure. The top-level descriptor in the file is
<dumpdb>. A
<database> descriptor must be present within
<dumpdb> to define the key and value types used by the database. Inside
<database>, the
<record> descriptor triggers database traversal. Shown below is an example that demonstrates the structure of a minimal descriptor file:
<dumpdb>
<database key="string" value="::Employee">
<record>
<echo message="Key: " value="key"/>
<echo message="Value: " value="value"/>
</record>
</database>
</dumpdb>
During traversal, type-specific actions are supported by the <dump> descriptor, which is a child of
<dumpdb>. One
<dump> descriptor may be defined for each type in the Slice definitions. Each time
dumpdb encounters an instance of a type, the
<dump> descriptor for the type is executed.
The <database>,
<record>, and
<dump> descriptors may contain general-purpose action descriptors such as
<if> and
<echo>. These actions resemble statements in programming languages like C++ and Java, in that they are executed in the order of definition and their effects are cumulative. Actions make use of the expression language described in
Section 37.8.
Although dumpdb descriptors are not allowed to modify the database, they can still define local symbols for scripting purposes. Once a symbol is defined by the
<define> descriptor, other descriptors such as
<set>,
<add>, and
<remove> can be used to manipulate the symbol’s value.
•
<database> is executed first. Each child descriptor of
<database> is executed in the order of definition. If a
<record> descriptor is present, database traversal occurs at that point. Any child descriptors of
<database> that follow
<record> are not executed until traversal completes.
•
For each record, dumpdb interprets the key and value, invoking
<dump> descriptors for each type it encounters. For example, if the value type of the database is a
struct, then
dumpdb first attempts to invoke a
<dump> descriptor for the structure type, and then recursively interprets the structure’s members in the same fashion.
See Section 37.6.4 for detailed information on the
dumpdb descriptors.
The <database> descriptor creates a global scope, allowing child descriptors of
<database> to define symbols that are accessible in any descriptor
1. Furthermore, certain other descriptors create local scopes that exist only for the duration of the descriptor’s execution. For example, the
<dump> descriptor creates a local scope and defines the symbol
value to represent a value of the specified type. Child descriptors of
<dump> can also define new symbols in the local scope, as long as those symbols do not clash with an existing symbol in that scope. It is legal to add a new symbol with the same name as a symbol in an outer scope, but the outer symbol will not be accessible during the descriptor’s execution.
The global scope is useful in many situations. For example, suppose you want to track the number of times a certain value was encountered during database traversal. This can be accomplished as shown below:
<dumpdb>
<database key="string" value="::Ice::Identity">
<define name="categoryCount" type="int" value="0"/>
<record/>
<echo message="categoryCount = " value="categoryCount"/>
</database>
<dump type="::Ice::Identity">
<if test="value.category == `Accounting'">
<set target="categoryCount"
value="categoryCount + 1"/>
</if>
</dump>
</dumpdb>
In this example, the <define> descriptor introduces the symbol
categoryCount into the global scope, defining it as type
int with an initial value of zero. Next, the
<record> descriptor causes traversal to proceed. Each occurrence of the type
Ice::Identity causes its
<dump> descriptor to be executed, which examines the
category member and increases
categoryCount if necessary. Finally, after traversal completes, the
<echo> descriptor displays the final value of
categoryCount.
To reinforce the relationships between descriptors and scopes, consider the diagram in
Figure 37.2. Several descriptors are shown, including the symbols they define in their local scopes. In this example, the
<iterate> descriptor has a dictionary target and therefore the default symbol for the element value,
value, hides the symbol of the same name in the parent
<dump> descriptor’s scope
2. In addition to symbols in the
<iterate> scope, child descriptors of
<iterate> can also refer to symbols from the
<dump> and
<database> scopes.
The top-level descriptor in a descriptor file. It requires one child descriptor, <database>, and supports any number of
<dump> descriptors. This descriptor has no attributes.
The attributes of this descriptor define the key and value types of the database. It supports any number of child descriptors, but at most one
<record> descriptor. The
<database> descriptor also creates a global scope for user-defined symbols (see
Section 37.6.3).
As an example, consider the following <database> descriptor. In this case, the Freeze map to be examined has key type
int and value type
::Employee:
Commences the database traversal. Child descriptors are executed for each record in the database, but after any
<dump> descriptors are executed. The
<record> descriptor introduces the read-only symbols
key,
value and
facet into a local scope. These symbols are accessible to child descriptors, but not to
<dump> descriptors. The
facet symbol is a string indicating the facet name of the object in the current record, and is only relevant for Freeze evictor databases.
Executed for all instances of a Slice type. Only one <dump> descriptor can be specified for a type, but a
<dump> descriptor is not required for every type. The read-only symbol
value is introduced into a local scope. The attributes supported by this descriptor are described in
Table 37.14.
|
|
|
|
|
If type denotes a Slice class, this attribute determines whether the <dump> descriptor of the base class is invoked. If true, the base class descriptor is invoked after executing the child descriptors. If not specified, the default value is true.
|
|
For class and struct types, this attribute determines whether descriptors are executed for members of the value. For sequence and dictionary types, this attribute determines whether descriptors are executed for elements. If not specified, the default value is true.
|
Below is an example of a <dump> descriptor that searches for certain products:
<dump type="::Product">
<if test="value.description.find(`scanner') != ‑1">
<echo message="Scanner SKU: " value="value.SKU"/>
</if>
</dump>
For class types, dumpdb first attempts to locate a
<dump> descriptor for the object’s most-derived type. If no descriptor is found,
dumpdb proceeds up the class hierarchy in an attempt to find a descriptor. The base object type,
Object, is the root of every class hierarchy and is included in the search for descriptors. It is therefore possible to define a
<dump> descriptor for type
Object, which will be invoked for every class instance.
Note that <dump> descriptors are executed recursively. For example, consider the following Slice definitions:
struct Inner {
int sum;
};
struct Outer {
Inner i;
};
When dumpdb is interpreting a value of type
Outer, it executes the
<dump> descriptor for
Outer, then recursively executes the
<dump> descriptor for the
Inner member, but only if the
contents attribute of the
Outer descriptor has the value
true.
Iterates over a dictionary or sequence, executing child descriptors for each element. The symbol names selected to represent the element information may conflict with existing symbols in the enclosing scope, in which case those outer symbols are not accessible to child descriptors. The attributes supported by this descriptor are described in
Table 37.15.
Shown below is an example of an <iterate> descriptor that displays the name of an employee if the employee’s salary is greater than $3000.
<iterate target="value.employeeMap" key="id" value="emp">
<if test="emp.salary > 3000">
<echo message="Employee: " value="emp.name"/>
</if>
</iterate>
See Section 37.8 for more information on the descriptor expression language.
Modifies a value. The value and
type attributes are mutually exclusive. If
target denotes a dictionary element, that element must already exist (i.e.,
<set> cannot be used to add an element to a dictionary). The attributes supported by this descriptor are described in
Table 37.17.
|
|
|
|
|
|
|
|
|
An integer expression representing the desired new length of a sequence. If the new length is less than the current size of the sequence, elements are removed from the end of the sequence. If the new length is greater than the current size, new elements are added to the end of the sequence. If value or type is also specified, it is used to initialize each new element.
|
|
If true, additional type conversions are supported: between integer and floating point, and between integer and enumeration. Transformation fails immediately if a range error occurs. If not specified, the default value is false.
|
The <set> descriptor below modifies a member of a dictionary element:
<set target="new.parts['P105J3'].cost"
value="new.parts['P105J3'].cost * 1.05"/>
This <set> descriptor adds an element to a sequence and initializes its value:
<set target="new.partsList" length="new.partsList.length + 1"
value="'P105J3'"/>
Adds a new element to a sequence or dictionary. It is legal to add an element while traversing the sequence or dictionary using
<iterate>, however the traversal order after the addition is undefined. The
key and
index attributes are mutually exclusive, as are the
value and
type attributes. If neither
value nor
type is specified, the new element is initialized with a default value. The attributes supported by this descriptor are described in
Table 37.18.
Below is an example of an <add> descriptor that adds a new dictionary element and then initializes its member:
<add target="new.parts" key="'P105J4'"/>
<set target="new.parts['P105J4'].cost" value="3.15"/>
|
|
|
|
|
|
|
|
|
If true, additional type conversions are supported: between integer and floating point, and between integer and enumeration. Execution fails immediately if a range error occurs. If not specified, the default value is false.
|
Below are two examples of the <define> descriptor. The first example defines the symbol
identity to have type
Ice::Identity, and proceeds to initialize its members using
<set>:
<define name="identity" type="::Ice::Identity"/>
<set target="identity.name" value="steve"/>
<set target="identity.category" value="Admin"/>
<define name="manufacturer" type="::BigThree"
value="::DaimlerChrysler"/>
Removes an element from a sequence or dictionary. It is legal to remove an element while traversing a sequence or dictionary using
<iterate>, however the traversal order after removal is undefined. The attributes supported by this descriptor are described in
Table 37.20.
Causes transformation to fail immediately. If test is specified, transformation fails only if the expression evaluates to
true. The attributes supported by this descriptor are described in
Table 37.21.
The following <fail> descriptor terminates the transformation if a range error is detected:
<fail message="range error occurred in ticket count!"
test="value.ticketCount > 32767"/>
Shown below is an <echo> descriptor that uses both
message and
value attributes:
<if test="value.ticketCount > 32767">
<echo message="range error occurred in ticket count: "
value="value.ticketCount"/>
</if>