4 Understanding Storable Classes

Learn about storable classes, which define the storable objects that store data in the Oracle Communications Billing and Revenue Management (BRM) database.

Topics in this document:

About Storable Classes and Objects

Storable classes define the storable objects that store data in the BRM database. A storable class is a template consisting of a collection of fields in the BRM database. Objects are instances of storable classes.

Objects are stored persistently in SQL tables in the BRM database. To understand how objects are mapped to SQL tables, see "Storable Class-to-SQL Mapping" in BRM Developer's Reference.

Objects are passed in the form of flists between opcodes or programs that use the objects. For detailed information about flists, see "Understanding Flists".

You manipulate the objects by using opcodes in the Portal Communication Module Application Programming Interface (PCM API). For more information about the PCM API, see "Understanding the PCM API".

Each object has a unique Portal object ID (POID). The POID identifies the object in the BRM database.

The POID contains the following information:

database_number   object_type   object_id   object_revision_level

Example:

0.0.0.1 /account 1234 0

Storable Class Naming and Formatting Conventions

BRM uses the following conventions for storable class names and definitions:

  • A storable class name begins with a forward slash (/). For example: /config.

  • Each slash in a storable class name represents a level of class inheritance. For example /config/adjustment is a subclass of /config and /config/adjustment/event is a subclass of /config/adjustment.

Subclassing

You can subclass a storable class to extend its functionality. When you subclass a storable class, the subclass inherits all the fields defined in the parent class and can have additional fields specific to the subclass. For example, the /service/email storable class contains all the information in the /service storable class plus additional information, such as login name and email address, specific to the email service.

Base storable classes are parent classes predefined in BRM from which you can create subclasses to add new functionality. Subclasses of storable classes can be extended or unextended:

  • An extended subclass inherits all the fields defined in its base storable class and contains new fields that add functionality specific to the subclass, as illustrated by the /service/email subclass.

    You can create a subclass of an extended subclass to add functionality to an extended subclass. An example of this type of subclass is /config/adjustment/event.

  • An unextended subclass inherits all the fields defined in its base storable class but does not contain any new fields for additional functionality. The only difference between an unextended subclass and its base storable class is the storable class type.

    The unextended subclasses are primarily used for tracking and for grouping subclasses with similar functionality. For example, /event/billing is a subclass of /event, but it does not contain any additional fields. It is primarily used to group different BRM billing events, such as charge, debit, and payment.

When you subclass a predefined base storable class or a subclass by adding new fields, your new storable class has the following characteristics:

  • The same fields as its original base storable class with the attributes of that class.

  • Any new fields you add.

  • The common defined behavior and functionality of storable classes in BRM.

About Defining Storable Classes

You use fields to define storable classes. Fields in storable classes have corresponding fields in opcode input flists. The fields in the objects receive specific instructions and behavior from the corresponding fields in the opcode that manipulates the object.

Each field has the following parts:

  • A mnemonic name that describes its function. For example, PIN_FLD_LOGIN. Field names are unique within an flist. Applications must use this name to refer to the field.

    The default fields used in BRM start with PIN_FLD_. You can use a different prefix for your custom fields to distinguish them from the default fields.

  • A type that specifies its data type and defines the range of values it can accept. For example, PIN_FLDT_STR for string type.

    For information on the BRM data types, see "Understanding the BRM Data Types".

  • Permission, which specifies if the field is optional, mandatory, writable, and so on.

  • An ID number that establishes it in the data dictionary. When you define a new field, the field is added to the data dictionary and is assigned the next consecutive ID number in the ranges reserved for customer use. For example, if the ID of the last field you created is 10,500, your new field's ID number is 10,501.

    Table 4-1 lists the field ID ranges for Oracle-only use and for customer use.

    Table 4-1 BRM Field ID Restrictions

    Field ID Range Reserved For

    0 through 9999

    Oracle use only

    10,000 through 999,999

    Customer use

    1,000,000 through 9,999,999

    Oracle use only

    Over 10,000,000

    Customer use

Fields Common to All Storable Classes

Every BRM storable class requires the following fields for its object to be created in the system:

  • PIN_FLD_POID, which contains the POID. See "Portal Object ID (POID)" for more information.

  • PIN_FLD_NAME, which contains the name of the storable class.

  • PIN_FLD_CREATED_T, which contains the date the object was created.

  • PIN_FLD_MOD_T, which contains the date the object was modified.

  • PIN_FLD_READ_ACCESS, which specifies the read permissions for the object.

  • PIN_FLD_WRITE_ACCESS, which specifies the write permissions for the object.

These fields are available to the BRM applications and Facilities Modules (FMs), but you cannot write to them. They can be manipulated only by a Data Manager (DM).

Defining New Fields for Storable Classes

You define new fields and add them to the data dictionary by using the Storable Class Editor. After you define a field, you use the PIN_FLD_MAKE macro to create an encoded number for the field. You use this number to build flists for opcode and object manipulation in C code. The PIN_FLD_MAKE macro is defined in BRM_home/include/pcm.h, where BRM_home is the directory in which the BRM server software is installed.

For more information on creating custom fields and storable classes, see "Creating Custom Fields".

For information on defining new fields in C++, see "Creating Custom Fields".

For information on defining new fields in Java, see "Using Custom Fields in Java Applications".

Reading Objects

There are two ways to read the contents of objects in a BRM database:

  • Use Object Browser, part of Developer Center, to view objects in the BRM database. You can see a list of all the objects in a storable class and the contents of objects that you select. You can also save and print object contents.

  • You can run opcodes either programmatically or in a test application such as testnap.

You can use opcodes to read objects in the database by using the read operations included in BRM. These opcodes are optimized for the most frequently used operations in BRM. You can read only a portion of the fields in an object instead of the complete object.

Use one of these opcodes to read objects:

  • PCM_OP_READ_OBJ loads and returns the entire object, no matter how many rows and tables the object spans. See "Reading an Entire Object".

  • PCM_OP_READ_FLDS loads only the fields requested. It accesses fewer tables than when an entire object is read. See "Reading Fields in an Object".

Locking Objects when Reading them

You can lock an object to avoid an extra round trip to the database. To lock an object while the PCM_OP_READ_OBJ or PCM_OP_READ_FLDS opcode reads it, use the PCM_OPFLG_LOCK_OBJ flag. The query is turned into the equivalent of a select for update, which places an exclusive lock on the rows in the database.

When using the PCM_OPFLG_LOCK_OBJ flag during an opcode process, the flag works as follows:

  • If the Facilities Module (FM) opcode opens a read/write transaction, the PCM_OPFLG_LOCK_OBJ flag locks the object for a PCM_OP_READ_OBJ or PCM_OP_READ_FLDS operation.

  • If the FM opcode opens a read-only transaction and then tries to use PCM_OPFLG_LOCK_OBJ in any subsequent read calls, the DM returns an error.

  • If the FM opcode does not open a transaction and then tries to use PCM_OPFLG_LOCK_OBJ in any subsequent read calls, the DM returns an error.

Most opcode operations lock the account when they begin processing. Though this provides reliable data consistency, locking an account locks all of its associated objects and can prevent other opcodes from operating on them. This can decrease the throughput of the system. To alleviate this problem in affected systems, you may choose to lock the specific objects an opcode will change instead of the whole account; the objects an opcode does not change can still be accessed by other opcodes. See "Locking Specific Objects".

Reading an Entire Object

To read an entire object from the database, use the PCM_OP_READ_OBJ opcode. Specify the POID of the object to read in the input flist. The POID of the object and all fields in the object return, including array elements and substructures.

Audit trail information

PCM_OP_READ_OBJ checks for an audit flag to see whether the read request is for an audited object. If an audit flag is set in the call to this opcode, a search for the audit trail is performed.

For information about accessing audit trails, see "Accessing Audit Trail Information".

When a field is marked for auditing, a shadow object is created every time the field is modified. A shadow object is a replica of the original object that contains the POID revision number of the object before it was modified.

For more information about shadow objects, see "About Shadow Objects".

To retrieve audit-trail revisions from the database, use these flags in the call to this opcode to send a request to the database DM:

  • PCM_OPFLG_USE_POID_GIVEN

    Runs a search-and-read operation for the POID you specify, which is the POID of the shadow object in the audit trail.

  • PCM_OPFLG_USE_POID_NEAREST

    Runs a search-and-read operation for the audit-trail revision number that you specify (the POID of the shadow object). If the exact POID is not found, it finds the POID with the revision number immediately preceding the revision number of the POID you specify.

  • PCM_OPFLG_USE_POID_NEXT

    Runs a search-and-read operation for the shadow object POID that contains the revision number next higher than the revision number in the POID you specify.

  • PCM_OPFLG_USE_POID_PREV

    Runs a search-and-read operation for the shadow object POID that contains the revision number immediately preceding the revision number in the POID you specify.

Reading Fields in an Object

To read one or more fields in an object, use the PCM_OP_READ_FLDS opcode. This opcode returns the POID of the object from which the fields were read, along with the specified fields and their values.

This opcode returns the POID of the object from which the fields were read, along with the specified fields and their values.

PCM_OP_READ_FLDS allows a client application to read specified fields in an object. Specify the POID of the object along with the list of fields to be read in the input flist. The POID is mandatory; the fields are optional. If there are no fields present, only the POID is read and returned.

To read an array element, specify the element in the input flist. If the array element contains a substructure that contains fields you want to read, you must also specify the substruct elements in the input flist.

Note:

To improve performance, some object arrays are stored in a special serialized format. When a client application requests fields from a serialized array, PCM_OP_READ_FLDS returns the entire array rather than just the specified fields.

You can read all the fields of a substructure or array in the following ways:

  • To read an entire substruct, put the substruct field in the input flist with a NULL value.

  • To read all the fields in an array element, put the array element in the input flist with a NULL value. This returns all fields, including those from substructs.

  • To read all the elements of an array, put the array element in the input flist with an element ID of PIN_ELEMID_ANY.

Examples

  • This opcode can be used with a read-only transaction to obtain a frozen view of an object. When a read-only transaction is open, all reads are performed on fields in the state they are in when the transaction is opened. This is an important consideration when you perform multiple reads and must ensure that the data does not change between reads, such as when adding up fields for a balance.

    For information about opening a read-only transaction, see "Using Transactions in Your Client Application".

  • You can use this opcode to find the value of a flag. This example shows the input and output flists for reading the value of the PIN_FLD_FLAGS field in the PIN_FLD_BALANCES array element in a /balance_group object:

    CM input flist: op PCM_OP_READ_FLDS, flags 0x0
    # number of field entries allocated 20, used 2
    0 PIN_FLD_POID                 POID [0] 0.0.0.1 /balance_group 685398 3
    0 PIN_FLD_BALANCES            ARRAY [840] allocated 20, used 1
    1     PIN_FLD_CREDIT_PROFILE    INT [0] 0
      
    CM output flist: op PCM_OP_READ_FLDS
    # number of field entries allocated 20, used 2
    0 PIN_FLD_POID                 POID [0] 0.0.0.1 /balance_group 685398 1
    0 PIN_FLD_BALANCES            ARRAY [840] allocated 20, used 1 
    1     PIN_FLD_CREDIT_PROFILE    INT [0] 22

Creating Objects

To create an object, use the PCM_OP_CREATE_OBJ opcode. This opcode creates a new object of the type specified in the input flist. You must specify the database type and storable class type subfields of the object POID on the input flist. The POID ID is ignored unless you use the PCM_OPFLG_USE_POID_GIVEN flag.

The PCM_OP_CREATE_OBJ input flist must include all the fields that the object requires. The fields required in the input flist depend on the type of object; for example, an /account object includes security code, account number, account type, balances, and credit fields.

This opcode returns the POID of the object created. If you use the PCM_OPFLG_READ_RESULT flag, it also returns all fields from the created object, including array elements and substructures.

PCM_OP_CREATE_OBJ Opcode Flags

Use these flags when creating objects.

  • PCM_OPFLG_USE_POID_GIVEN

    If you use the PCM_OPFLG_USE_POID_GIVEN flag, PCM_OP_CREATE_OBJ uses the POID ID you specify on the input flist. If the ID is a duplicate, a new POID ID is assigned. If you do not use the PCM_OPFLG_USE_POID_GIVEN flag, this opcode assigns a new POID ID.

    Not all object POID IDs can be assigned by a user. For information on which object POID IDs can be assigned, see the object specifications in "Storable Class Definitions" in BRM Developer's Reference.

  • PCM_OPFLG_READ_RESULT

    Returns all fields from the created object, including array elements and substructures.

  • PCM_OPFLG_CACHEABLE

    Enables caching each transaction's objects in the Connection Manager (CM) instead of writing them immediately to the database. See "Improving Performance when Working with Objects".

    If the PCM_OPFLG_CACHEABLE flag is not set, the opcode writes the input flist to the database immediately and writes it to the cache for future use.

Writing Fields in Objects

To write fields in an object, use the PCM_OP_WRITE_FLDS opcode. This opcode returns the POID of the object whose fields were written, including the new revision number. This opcode allows a client application to set the values of fields in an object. Specify the fields and values to set, along with the POID of the object, on the input flist. You must update at least one field.

The field values are absolutely set to the values you provide. To make a relative change to a numeric field value, use the PCM_OP_INC_FLDS opcode.

Update array element fields by specifying the array element ID and the field element ID in the input flist. If there is no array element for the fields you want to update, you must create the element by using the PCM_OPFLG_ADD_ENTRY flag.

Note:

This flag is required because BRM allocates space for array elements only when they are created and assigned a value. If you do not use the PCM_OPFLG_ADD_ENTRY flag, you receive an error when you try to update array fields in an element that doesn't exist.

The PCM_OPFLG_ADD_ENTRY flag is required only for array fields. Fields that are not part of an array element must already exist (assuming the object exists) so they are updated as requested.

If you set an array element in the input flist and use the element ID PIN_ELEMID_ASSIGN, the element is created with an element ID numbered next higher than the highest existing element ID for that array.

Not all fields in each object are writable by the application. For details on which fields are writable, see "Storable Class Definitions" in BRM Developer's Reference.

PCM_OP_WRITE_FLDS Opcode Flags

Use these flags:

  • PCM_OPFLG_ADD_ENTRY

    Creates an array element and updates fields as requested. If the array element already exists, this flag is ignored. PCM_OPFLG_ADD_ENTRY cannot be used to create ordinary fields.

  • PCM_OPFLG_READ_RESULT

    Returns all fields from the created object, including array elements and substructures.

  • PCM_OPFLG_NO_RESULTS

    Although this flag can be included, the PCM_OP_WRITE_FLDS opcode ignores it and returns the POID.

  • PCM_OPFLG_CACHEABLE

    Enables caching each transaction's objects in the CM instead of writing them immediately to the database. See "Improving Performance when Working with Objects".

    If the PCM_OPFLG_CACHEABLE flag is not set, the opcode writes the input flist to the database immediately and writes it to the cache for future use.

    If an array element in the input flist has an element ID of PIN_ELEM_ID_ASSIGN, the element is not cached, even if the PCM_OPFLG_CACHEABLE flag is set.

    If neither PCM_OPFLG_CACHEABLE nor PCM_OPFLG_ADD_ENTRY is set, and the array entry does not exist, the opcode fails. If PCM_OPFLG_CACHEABLE is set but PCM_OPFLG_ADD_ENTRY is not set, and the array entry does not exist, the opcode also fails, but it does not return the error immediately. The delayed error appears when the fields are actually written to the database.

Incrementing Fields in Objects

To increment fields in an object, use the PCM_OP_INC_FLDS opcode. This opcode returns the POID of the object whose fields were updated, including the new revision number. It also returns the revised values of the selected fields unless the PCM_OPFLG_NO_RESULTS flag is used.

This opcode increments or decrements fields specified in the input flist. Only fields of type PIN_FLDT_INT and PIN_FLDT_DECIMAL can be incremented or decremented, and both types must be signed in the input flist. The signed value of the field in the input flist determines whether the field is incremented or decremented.

You must update at least one field. Specify the POID of the object that contains the fields to update, along with at least one field, in the input flist.

Update array element fields by specifying the array element ID along with the field element ID in the input flist. If there is no array element for the fields you want to update, you must create the element by using the PCM_OPFLG_ADD_ENTRY flag.

Note:

This flag is required because BRM allocates space for array elements only when they are created and assigned a value. If you do not use the PCM_OPFLG_ADD_ENTRY flag, you receive an error when you try to update array fields in an element that doesn't exist. An error also occurs if the array contains any nonincremental fields or mandatory fields of a nonincremental type.

The PCM_OPFLG_ADD_ENTRY flag is required only for array fields. Fields that are not part of an array element must already exist (assuming the object exists) so they are updated as requested.

If you set an array element on the input flist and assign the element ID a value of PIN_ELEMID_ASSIGN, the element is created with an element ID that is numbered next higher than the highest existing element ID for that array.

Updating Decimal Data Types

When you increment or decrement fields of decimal data type, the result depends on the value of the field both in the database and in the input flist. If the value of the field in the database is NULL, BRM converts that value to 0 before updating. If the value of the field in the input flist is NULL or 0, no action is taken on the value in the database. This prevents a non-NULL value in the database from being converted to NULL.

Table 4-2 shows the three possible results of an increment (0, NULL, or non-NULL) for all possible field value combinations. These results apply only to decimal data types:

Table 4-2 Incrementing Database Field Values

Database Field Value Flist Increment Value Result of Increment

NULL

NULL or 0

NULL

NULL

Non-NULL

Non-NULL

0

NULL or 0

0

0

Non-NULL

Non-NULL

Non-NULL

NULL or 0 or non-NULL

Non-NULL

If you want a field value to remain open (such as a credit limit), you should increment the field by a value of either 0 or NULL.

You can prevent the conversion of the field value in the database from NULL to 0 by using the PCM_OPFLG_USE_NULL flag. This flag assigns a NULL value to the field in the input flist, which prevents a change to the database value.

Updating Integer Data Types

You cannot assign a NULL value to fields of type INT in the input flist. If you update an INT data type, the PCM_OPFLG_USE_NULL flag is ignored. To maintain a NULL value in the database for a field of type INT, you must increment with 0. If the increment value is nonzero in the input flist, the result is always nonzero.

Not all fields in each object can be incremented by an application. For information on which fields can be incremented, see "Storable Class Definitions" in BRM Developer's Reference.

PCM_OP_INC_FLDS Opcode Flags

Use these flags:

  • PCM_OPFLG_ADD_ENTRY

    Creates an array element, if it doesn't already exist, and updates the specified fields as requested. It cannot be used to create nonarray fields. If the array element already exists, this flag is ignored.

  • PCM_OPFLG_READ_RESULT

    Returns all fields from the created object, including array elements and substructures.

  • PCM_OPFLG_USE_NULL

    Prevents a NULL field value in the database from being converted to 0 and updated.

  • PCM_OPFLG_NO_RESULTS

    Returns only the POID, without the updated data. This flag provides higher performance by skipping the extra processing of returning updated data.

Deleting Objects

To delete an object, use the PCM_OP_DELETE_OBJ opcode. Specify the POID of the object to delete in the input flist. This opcode ignores the field values of the object to be deleted. When an object is deleted, its POID ID cannot be reused.

This opcode deletes only the object passed in. No integrity checks are performed to ensure that the object is not referenced in any way.

Note:

To maintain database consistency, you must make sure that your application deletes any other objects that reference or are referenced by the object you delete.

This opcode returns the POID of the deleted object.

Deleting Fields in Objects

To delete fields in an object, use the PCM_OP_DELETE_FLDS opcode. This opcode returns the POID of the object from which an element was deleted, including the new revision number.

You must delete at least one array element. Specify the POID of the object from which to delete elements in the input flist. Also specify the array element ID for each element to be deleted. To delete an entire array, put the array in the input flist and use the element ID PCM_RECID_ALL.

The value for each array element to be deleted must be NULL. The value of fields within an array element to be deleted are ignored. You cannot delete fields within an array element without deleting the array element.

Only optional arrays and array elements can be deleted. Attempting to delete a mandatory element will return an error. You cannot delete fields that are not part of an array element, and you cannot delete arrays or array elements within a substructure.

Managing a Large Number of Objects

In addition to working with individual objects, you can use base opcodes to perform the following operations on a large number of objects in one database operation instead of accessing the database for every object:

Creating a Large Number of Objects

To create a large number of objects of the same type, use the PCM_OP_BULK_CREATE_OBJ opcode.

The PCM_OP_BULK_CREATE_OBJ input flist must include all the fields that the objects of the storable class requires. The required input flist fields depend on the type of objects that you are creating; for example, an /account object includes security code, account number, account type, balances, and credit fields. You can use the PIN_FLD_COMMON_VALUES array in the input flist for fields that have common values for all objects being created.

Note:

You cannot use this opcode to create a new storable class. You can use it only to create objects in an existing storable class.

You can use the same flags with this opcode as you can with the PCM_OP_CREATE_OBJ opcode, except that the following flags are not supported:

  • PCM_OPFLG_USE_POID_GIVEN

  • PCM_OPFLG_READ_RESULT

This opcode returns the type-only POID of the objects created, but it does not return the full POIDs of the individual objects created.

Editing a Large Number of Objects

To update fields in a large number of objects of the same type, use the PCM_OP_BULK_WRITE_FLDS opcode.

This opcode updates the values of the fields or adds new fields in the objects that meet the conditions you specify in the input flist. It returns the POID type and count of the objects.

To update array element fields, specify the array element ID and the field element ID in the input flist. You can update first- and second-level array fields. If there is no array element for the fields you want to update, you must create the element by using the PCM_OPFLG_ADD_ENTRY flag.

Note:

This flag is required only for array elements because BRM allocates space for array elements only when they are created and assigned a value. If you do not use the PCM_OPFLG_ADD_ENTRY flag, you receive an error when you try to update array fields in an element that doesn't exist.

Fields that are not part of an array element must already exist for an object, and they are updated.

If you set an array element in the input flist and use the element ID PIN_ELEMID_ASSIGN, the element is created with an element ID higher than the highest existing element ID for that array.

Deleting a Large Number of Objects

To delete a large number of objects of the same type, use the PCM_OP_BULK_DELETE_OBJ opcode. This opcode deletes the objects of the type that meet the conditions you specify in the where clause of the query. It returns the POID type and the count of the objects deleted.

Note:

  • You cannot use the opcode to delete specific fields in an object, only to delete complete objects.

  • You cannot use the opcode to delete an entire storable class, only to delete objects in that class.

Locking Objects when Editing or Deleting a Large Number of Objects

To enforce the data integrity of bulk operations (the PCM_OP_BULK_WRITE_FLDS and PCM_OP_BULK_DELETE_OBJ opcodes), specify the PCM_OPFLG_LOCK_OBJ flag for the opcodes.

Note:

The PCM_OP_LOCK_DEFAULT flag is ignored by the bulk opcodes.

When the PCM_OPFLG_LOCK_OBJ flag is specified, the balance groups of the known objects or the unknown objects will be locked. The rules for identifying which balance groups are locked are identical to the rules used in "Locking Specific Objects".

Improving Performance when Working with Objects

Some opcodes used for searching and manipulating objects use the PCM_OPFLG_CACHEABLE flag. This flag enables caching each transaction's objects in the Connection Manager (CM) instead of writing them immediately to the database. Caching makes the CM and the DM more efficient because the CM doesn't request the DM to write the same object to the database multiple times.

Objects are cached at the end of a transaction unless they must be written to the database earlier. For example, a search causes immediate execution of all pending writes so that the search can work on the most current data.

If the PCM_OPFLG_CACHEABLE flag is not set, the opcode immediately writes the input flist to the database and then to the cache for future use.

The CM writes flist fields to the database when the application does the following:

  • Runs one of the following opcodes:

    • PCM_OP_CREATE_OBJ

    • PCM_OP_SEARCH

    • PCM_OP_STEP_SEARCH

    • PCM_OP_STEP_NEXT

    • PCM_OP_GLOBAL_SEARCH

    • PCM_OP_GLOBAL_STEP_SEARCH

    • PCM_OP_GLOBAL_STEP_NEXT

    • PCM_OP_READ_OBJ

    • PCM_OP_READ_FLDS

    • PCM_OP_WRITE_FLDS

  • Runs PCM_OP_INC_FLDS, and the fields are part of the object in the writable cache.

Sometimes, the object can be partially available in the cache due to previous executions of PCM_OP_READ_FLDS or PCM_OP_WRITE_FLDS. If the partial object is in the read-only cache, the CM destroys it and reads a complete object from the database through the DM. The CM caches that object before returning it to the application. If the partial object has been updated and therefore is in the writable cache, the CM writes it to the database before reading and caching the complete object.

The scope of a transaction cache is one transaction.

Note:

Transaction caching is not always beneficial. For example, if a transaction reads a given object only once, it should not use the PCM_OPFLG_CACHEABLE flag.

Locking Specific Objects

Locking on an account level (higher object hierarchy) can cause contention between opcodes and therefore create a bottleneck, reducing the throughput of the BRM system. Because the default locking process locks at the account level, performance can be improved by locking only the working objects rather than the account.

You can lock balance groups for the specific operations that are impacting performance. If you do not specify a more granular locking procedure, transactions lock account objects; no code change is required.

There are some frequently used operations that can take advantage of granular locking on balance group objects. They may lock the object's default or associated balance group to improve performance.

Note:

Exercise caution when customizing locking strategies. Changes to lower-level locking on balance group objects may cause a deadlock if you are not familiar with the execution paths of the Facilities Module (FM) utility subroutines.

BRM supports balance group locking for transactions and opcodes that open the following known objects:

  • A given account

  • A given service

  • A given group

  • A given bill unit (/billinfo object)

  • A given bill

  • A given balance group

  • A given profile

  • A purchased charge offer

  • A purchased discount offer

  • An event

  • A journal

You use the following flags to lock balance groups:

  • Use the PCM_TRANS_OPEN_LOCK_OBJ flag to lock all the associated balance groups (multiple balance groups) during the opening of a transaction. The equivalent flag for use with the other base opcodes is PCM_OPFLG_LOCK_OBJ.

    For example:

    fm_utils_trans_open(ctxp, opflags|PCM_TRANS_OPEN_LOCK_OBJ, pdp, ebufp);
      
  • Use the PCM_TRANS_OPEN_LOCK_DEFAULT flag to lock the default balance group during the opening of a transaction. The equivalent flag for use with the base opcode is PCM_OPFLG_LOCK_DEFAULT.

    For example:

    PCM_OP(ctxp, PCM_OP_READ_FLDS, PCM_OPFLG_LOCK_OBJ, s_flistp, &o_flistp, ebufp);
      

Using these flags can improve your system's performance if many balance groups are associated with the object you are targeting with the lock request. Each flag locks balance groups according to the object type opened by the opcode or utility as shown in Table 4-3:

Table 4-3 Balance Locking Flags

Object Types PCM_TRANS_OPEN_LOCK_OBJ PCM_TRANS_OPEN_LOCK_DEFAULT

Account

Generate a SQL template to do bulk locking on all the account's balance groups.

Lock the account's default balance group.

BillInfo

Generate a SQL template to do bulk locking on all the bill unit's balance groups.

Lock the bill unit's default balance group.

Balance Group

Lock the balance group.

Note: This rule is identical to that of PCM_TRANS_OPEN_LOCK_DEFAULT.

Lock the balance group.

Service

Lock the service's default balance group.

Note: This rule is identical to that of PCM_TRANS_OPEN_LOCK_DEFAULT.

Lock the service's default balance group.

Profile

Lock all the parent account's balance groups (alternatively).

Note: There may be some ambiguity in this rule.

Lock the parent's default balance group.

Group

Lock all the owner account's balance groups.

Lock the owner account's default balance group.

Bill

Lock all bill unit's balance groups.

Lock the bill unit's default balance group.

Item

Lock the item's default balance group.

Note: This rule is identical to that of PCM_TRANS_OPEN_LOCK_DEFAULT.

Lock the item's default balance group.

Journal

Lock the journal object as is by returning its POID.

Note: This rule is identical to that of the PCM_TRANS_OPEN_LOCK_DEFAULT

Lock the journal object as is by returning its POID.

Event

Lock the event object as is by returning its POID.

Note: This rule is identical to that of PCM_TRANS_OPEN_LOCK_DEFAULT.

Lock the event object as is by returning its POID.

Purchased Charge Offer

Lock all of the service's default balance groups (if any) or parent account's default balance groups (alternatively).

Note: This rule is identical to that of PCM_TRANS_OPEN_LOCK_DEFAULT.

Lock the all the service's default balance groups (if any) or parent account's default balance groups (alternatively).

Purchased Discount Offer

Lock all of the service's default balance groups (if any) or parent account's default balance groups (alternatively).

Note: This rule is identical to that of PCM_TRANS_OPEN_LOCK_DEFAULT.

Lock the all the service's default balance groups (if any) or parent account's default balance groups (alternatively).

Others

Lock all the balance groups of the parent account, provided the account is not the root or the PCM login account. Otherwise, lock the object as is.

Note: BRM assumes that the login user ID is an account POID.

Lock the default balance group of the parent account provided that the account must not be the root or the PCM login account. Otherwise, lock the object as is.

Note:

When using either flag, be aware of what is locked and what is not locked. A deadlock can occur when two different transaction contexts lock on a common set of objects and the lock sequences are not synchronized.

Oracle can detect the database-level deadlocks and throws an error to the DM. Users may also dump the CM lock map to determine the object that caused the deadlock. The technique is as follows:

  1. Obtain the lock map flist using PCP_GET_TRANS_FLIST.

  2. Use PIN_ERR_LOG_FLIST to display the lock map flist.

There are many opcodes that can lock based on the objects in the list. In some cases, it should be okay to leave things as they are. If you decide not to change anything, things should still work as before and performance should not degrade.

Some sample strategies that may be employed to assist performance are:

  • Change PCM_OPFLG_LOCK_OBJ to PCM_OPFLG_LOCK_ DEFAULT in an operation you already use. This may change its locking behavior but typically if you were not experiencing deadlocks with this operation before, it can be changed safely.

  • Change the object to lock. If an opcode works on only the /service object, try using the PCM_OPFLG_LOCK_DEFAULT flag on the /service object if it is provided in the input flist. In this way, objects that are not changed are not locked and therefore a given opcode will not interfere with objects that it does not change.

You can lock only when you are in a read-write transaction. Otherwise, your lock flags will be ignored or may result in a fatal PCM error.

Disabling Granular Object Locking

By default, granular object locking is enabled in BRM. Performance is better when you use granular object locking.

To disable granular locking, run the pin_bus_params utility to change the LockConcurrency business parameter. For information about this utility, see "pin_bus_params".

The default behavior, which corresponds to the LockConcurrency value of high, allows you to call opcodes with the PCM_OPFLG_LOCK_OBJ and PCM_OPFLG_LOCK_DEFAULT flags to determine the locking procedure. See "Locking Specific Objects".

When you disable granular locking, the following rules apply:

  • There is no differentiation of the PCM_OPFLG_LOCK_OBJ and PCM_OPFLG_LOCK_DEFAULT flags.

  • A given balance group object is locked as is.

  • All other objects are translated to lock its associated account (if any).

  • The root login account will be ignored.

  • The object that has no account association will be locked as is.

To disable granular object locking:

  1. Go to BRM_home/sys/data/config.

  2. Create an XML file from the /config/business_params object:

    pin_bus_params -r multi_bal financial/config/xml_utils/bus_params_multi_bal.xml
  3. In the file, change high to normal:

    <LockConcurrency>high</LockConcurrency>
  4. Save the file as financial/config/xml_utils/bus_params_multi_bal.xml..

  5. Load the XML file into the BRM database:

    pin_bus_params financial/config/xml_utils/bus_params_multi_bal.xml
  6. Stop and restart the CM.

  7. (Multischema systems only) Run the pin_multidb script with the -R CONFIG parameter. For more information, see "pin_multidb" in BRM System Administrator's Guide.