IDMS developer on retainer: AGENTUPD FIND NEXT POLICY within AGENT-POLICIES does not retrieve data into working storage — all agents updated with first policy’s premium — CA IDMS developer, Broadcom IDMS developer on monthly retainer

Broadcom IDMS r20.0 • z/OS 2.4 • COBOL II AGENTUPD • schema AGENTDB • FIND vs OBTAIN • AGENT-POLICIES set • retainer billing

At Eastern States Casualty Insurance, the monthly commission calculation job AGENTUPDJ completed without error every month and moved on to the downstream commission payment run. The commission checks were wrong. The IDMS developer retainer was eventually engaged after agents in 73 of 93 regional offices reported receiving zero monthly commission — despite having active policies in the current period — and agents in the remaining 20 offices reported commissions that were multiples of their actual billings. The source of the error was a single word in the AGENTUPD source code: FIND, where it should have been OBTAIN.

In IDMS DML (Data Manipulation Language), FIND and OBTAIN are distinct operations. FIND establishes IDMS currency — it moves the database pointer to the target record, updating the current-of-run-unit, current-of-record-type, current-of-set, and current-of-area indicators — but does NOT transfer the record data into the COBOL working storage buffer. OBTAIN performs both: it establishes currency the same way FIND does AND transfers the record data from the database into the COBOL working storage buffer. AGENTUPD opened each agent’s policy set with OBTAIN FIRST POLICY (correctly loading the first policy’s data), then navigated through the remaining policies with FIND NEXT POLICY (moving currency without refreshing working storage). Every iteration after the first accumulated the first policy’s premium amount, not the current record’s.

IDMS currency and the FIND vs OBTAIN distinction

CA IDMS (Computer Associates IDMS, now Broadcom IDMS) is a CODASYL-model network database that runs on z/OS. CODASYL network databases organize records as nodes and relationships (sets) as directed edges between owner and member record types. Navigation through the database is explicit: COBOL programs issue IDMS DML statements to move a cursor (called currency) from one record to the next, following set relationships.

IDMS maintains several currency indicators simultaneously for each program run unit:

Both FIND and OBTAIN update all applicable currency indicators. The critical difference is data transfer: OBTAIN also executes an implicit GET to move the record from the database buffer pool into the COBOL working storage buffer for the record type. FIND does not. After a FIND NEXT POLICY, the currency indicators point to the next POLICY record, but the POLICY record area in COBOL working storage still contains the data from the last OBTAIN — typically the first record retrieved by OBTAIN FIRST.

The distinction matters because IDMS programs rely on the working storage buffer for all field access. When AGENTUPD references POLICY-PREMIUM-AMOUNT after a FIND NEXT POLICY, it reads from the working storage buffer, which was last populated by OBTAIN FIRST POLICY. The program correctly iterates through the set (currency advances, end-of-set detection works), but it processes the first policy’s data on every iteration.

AGENTUPD schema structure and the AGENT-POLICIES set

The AGENTDB schema defined two record types relevant to AGENTUPD:

The IDMS set AGENT-POLICIES defined a OWNER:AGENT / MEMBER:POLICY relationship with SET ORDER SORTED descending by POLICY-DATE — so OBTAIN FIRST POLICY WITHIN AGENT-POLICIES retrieves the most recently issued policy for the current agent. Each AGENT record owned an average of 16.9 POLICY member records (min: 1, max: 347 for a high-volume commercial lines agent).

AGENTUPD’s subschema AGENTUPD-SS defined views for both record types and included the AGENT-POLICIES set. The program’s purpose: walk all AGENT records, sum the PREMIUM-AMOUNT of all POLICY records in the current month (where POLICY-STATUS = ‘A’ and POLICY-DATE month = current month), update AGENT.MONTHLY-PREMIUM, and exit.

The FIND NEXT bug in the inner loop

The relevant section of AGENTUPD (simplified to show the DML statements):

PROCEDURE DIVISION.
1000-MAIN.
    BIND RUN-UNIT
    BIND AGENTUPD-SS

    OBTAIN FIRST AGENT WITHIN AGENT-AREA
    EVALUATE IDMS-STATUS
        WHEN 0
            CONTINUE
        WHEN 0326                                *> end of area sweep
            GO TO 9000-EOJ
    END-EVALUATE

    PERFORM 2000-PROCESS-AGENT
        UNTIL WS-AGENT-END

    GO TO 9000-EOJ.

2000-PROCESS-AGENT.
    MOVE ZEROS TO WS-PREMIUM-TOTAL

    OBTAIN FIRST POLICY WITHIN AGENT-POLICIES    *> OK: loads first policy data
    IF IDMS-STATUS = 0307                        *> empty set
        GO TO 2900-NEXT-AGENT
    END-IF

    PERFORM 2100-ACCUMULATE-POLICY
        UNTIL WS-POLICY-END

    MOVE WS-PREMIUM-TOTAL TO AGENT-MONTHLY-PREMIUM
    MODIFY AGENT
    GO TO 2900-NEXT-AGENT.

2100-ACCUMULATE-POLICY.
    IF POLICY-STATUS = 'A'
       AND POLICY-DATE-MONTH = WS-CURRENT-MONTH
        ADD POLICY-PREMIUM-AMOUNT TO WS-PREMIUM-TOTAL   *> BUG: WS stale after iteration 1
    END-IF
    FIND NEXT POLICY WITHIN AGENT-POLICIES               *> BUG: currency only, no data
    IF IDMS-STATUS = 0307                                *> end of set
        SET WS-POLICY-END TO TRUE
    END-IF.

2900-NEXT-AGENT.
    SET WS-POLICY-END TO FALSE
    OBTAIN NEXT AGENT WITHIN AGENT-AREA
    IF IDMS-STATUS = 0326
        SET WS-AGENT-END TO TRUE
    END-IF.

The first call to OBTAIN FIRST POLICY WITHIN AGENT-POLICIES correctly loads the first policy record’s data into working storage. The POLICY-STATUS, POLICY-DATE-MONTH, and POLICY-PREMIUM-AMOUNT fields in working storage reflect the first policy. The ADD POLICY-PREMIUM-AMOUNT TO WS-PREMIUM-TOTAL in 2100-ACCUMULATE-POLICY works correctly on the first iteration.

Then FIND NEXT POLICY WITHIN AGENT-POLICIES fires. IDMS advances the current-of-set cursor to the second POLICY record. IDMS-STATUS returns 0 (record found). But the COBOL working storage buffer for POLICY is NOT updated — it still contains the data from the first policy. The IF POLICY-STATUS = 'A' check, the POLICY-DATE-MONTH comparison, and the ADD POLICY-PREMIUM-AMOUNT TO WS-PREMIUM-TOTAL all operate on first-policy data again.

This repeats for every subsequent policy in the agent’s set. The loop exits when FIND NEXT POLICY returns IDMS-STATUS = 0307 (end of set) — which happens at the correct point, after the actual last policy record. The loop count is correct; only the data is wrong.

The commission calculation errors across 8,437 agents

For each agent, WS-PREMIUM-TOTAL after the inner loop reflects: (number of policies in agent’s set) × (POLICY-PREMIUM-AMOUNT and POLICY-STATUS and POLICY-DATE-MONTH values from the first policy in the set, which is the most recent policy due to SORTED descending by POLICY-DATE).

Two outcomes by agent:

The commission payment program downstream read AGENT.MONTHLY-PREMIUM, applied the commission rate (typically 8–12%), and generated ACH payments. The erroneous MONTHLY-PREMIUM values were accepted by the commission program without range validation. 6,214 agents received zero-dollar payments; 2,223 agents received payments 10–20 times their correct commission amounts. The total commission payment amount was $3.84M instead of the correct $1.12M — a discrepancy that triggered the reconciliation review.

The fix: OBTAIN NEXT replaces FIND NEXT

The corrected inner loop:

2100-ACCUMULATE-POLICY.
    IF POLICY-STATUS = 'A'
       AND POLICY-DATE-MONTH = WS-CURRENT-MONTH
        ADD POLICY-PREMIUM-AMOUNT TO WS-PREMIUM-TOTAL
    END-IF
    OBTAIN NEXT POLICY WITHIN AGENT-POLICIES    *> Fixed: currency + data retrieval
    IF IDMS-STATUS = 0307
        SET WS-POLICY-END TO TRUE
    END-IF.

Replacing FIND NEXT POLICY with OBTAIN NEXT POLICY causes IDMS to advance currency AND transfer each successive POLICY record’s data into working storage. Each iteration of 2100-ACCUMULATE-POLICY now processes the current record’s actual POLICY-STATUS, POLICY-DATE-MONTH, and POLICY-PREMIUM-AMOUNT. End-of-set detection still works correctly — OBTAIN NEXT returns IDMS-STATUS = 0307 at the end of the set, just as FIND NEXT did.

After recompiling and testing AGENTUPD against 10 sample agents with known policy counts and current-month premium totals, all AGENT.MONTHLY-PREMIUM values matched the expected sums. The full AGENTUPDJ run was reexecuted against a database backup from prior to the erroneous run; MONTHLY-PREMIUM values were corrected for all 8,437 agents; and the commission payment run was resubmitted with the corrected data. The net effect was a $3.84M reversal and $1.12M reissuance of ACH payments.

A secondary fix was added to the commission payment program: a validation step that flags any AGENT where MONTHLY-PREMIUM exceeds the agent’s highest prior month by more than 300%, generating an exception report for manual review before ACH submission. This validation would have caught the FIND vs OBTAIN error before the payments were sent.

How HourTab helps IDMS developer retainers

The Eastern States Casualty engagement spanned two phases. Root cause investigation: 0.5h commission output analysis (confirming pattern of zeros vs. inflated amounts), 1.5h AGENTUPD source code review (reading all IDMS DML statements in the navigation loops, identifying FIND NEXT in the inner policy loop), 0.5h FIND vs OBTAIN distinction verification, 0.5h fix (one-word change), 1.0h test (10 sample agents, MONTHLY-PREMIUM verified against manual calculations) = 4.0h. Recovery coordination: 1.0h rerun coordination with operations (database backup identification, AGENTUPDJ reexecution against prior backup, commission payment run resubmission) = 1.0h.

In a HourTab retainer log, the investigation session reads: “AGENTUPD FIND NEXT POLICY (FIND = currency only, no data retrieval) used instead of OBTAIN NEXT POLICY (OBTAIN = currency + data) in 2100-ACCUMULATE-POLICY inner loop; working storage retained first policy’s POLICY-PREMIUM-AMOUNT and POLICY-DATE-MONTH across all iterations; 6,214 agents: MONTHLY-PREMIUM = zero (first policy in AGENT-POLICIES set was prior month); 2,223 agents: MONTHLY-PREMIUM = policy_count × first_policy_premium (inflated); fix: FIND NEXT replaced with OBTAIN NEXT in 2100-ACCUMULATE-POLICY; 10 sample agents tested — all MONTHLY-PREMIUM values correct; AGENTUPDJ rerun against prior backup; commission run resubmitted; 4.0h.” Eastern States Casualty’s IT manager can immediately see the root cause and the recovery steps taken.

HourTab turns a time-tracker CSV into a public retainer-hours URL your client can bookmark — no login, no portal, no “how many hours do I have left?” emails. Free for one retainer. $9/mo for up to ten.

FAQ: IDMS developer retainers

What does an IDMS developer on retainer typically do?

A CA IDMS (Broadcom IDMS) developer on monthly retainer covers IDMS CODASYL network database application maintenance on z/OS, including COBOL II and Enterprise COBOL programs that use IDMS DML statements (OBTAIN, FIND, GET, STORE, MODIFY, ERASE, CONNECT, DISCONNECT) to navigate schema records and set relationships. Typical retainer work: IDMS DML navigation maintenance — diagnosing FIND vs OBTAIN confusion (FIND establishes currency only; OBTAIN establishes currency + retrieves data; using FIND where OBTAIN is needed leaves working storage stale across loop iterations), set membership currency management (OBTAIN FIRST/NEXT WITHIN SET-NAME, OWNER WITHIN SET-NAME), and IDMS status code interpretation (0000 success, 0307 end-of-set, 0326 end-of-area); schema and subschema maintenance; IDMS run-unit management including COMMIT checkpoint placement for batch programs running concurrently with CICS/DC; and IDMS DC program and ADS/O dialogue maintenance.

What IDMS work is most commonly underlogged on retainer?

FIND vs OBTAIN confusion is the most systematically underlogged IDMS retainer work. FIND establishes IDMS currency (record pointer) but does NOT transfer data into working storage. OBTAIN does both. A program using OBTAIN FIRST then FIND NEXT in a loop has correct currency (end-of-set detection works) but stale working storage data — every iteration processes the first record’s field values. The symptom: all records in the set are processed (loop count correct, termination correct), but all processing uses the first record’s data. MODIFY operations in the loop update each subsequent record with the first record’s values. The fix is always replacing FIND NEXT with OBTAIN NEXT. Investigation requires reviewing all navigation loops in the COBOL source for FIND statements that should be OBTAIN, and verifying that end-of-set detection (db-status 0307 or 1208) is unaffected by the change (it is — both FIND and OBTAIN return 0307 at end of set).

What are typical IDMS developer retainer rates?

Entry-level IDMS developers with DML basics (OBTAIN, FIND, GET, STORE, MODIFY, ERASE; BIND RUN-UNIT; 0000/0307 status checking; OBTAIN FIRST/NEXT WITHIN SET-NAME navigation) typically bill at $80 to $135 per hour. Mid-level IDMS developers with FIND vs OBTAIN distinction mastery, CONNECT/DISCONNECT for set membership management, IDMS run-unit COMMIT checkpoint placement, schema and subschema maintenance, and IDMS DC program maintenance typically bill at $120 to $195 per hour. Senior IDMS developers with IDMS CV architecture (journal maintenance, DMCL generation, area allocation), IDMS performance analysis (log analysis, lock contention, buffer pool tuning), schema migration in production CV environments, and IDMS IDD management typically bill at $165 to $280 per hour. Monthly retainer ranges: $5,500 to $11,000 per month for IDMS COBOL batch program maintenance; $9,000 to $18,000 per month for schema architecture and CV administration.

What should an IDMS developer retainer agreement include?

An IDMS retainer agreement should specify: CA IDMS or Broadcom IDMS release version; which schemas and subschemas are in scope; whether batch program maintenance (BIND RUN-UNIT programs) and DC program maintenance (online BIND MAP programs) are separately scoped; whether schema maintenance is included — DDL changes require a CV outage window; whether run-unit lock management is in scope — batch programs with deferred COMMIT can conflict with DC online programs; whether ADS/O dialogue maintenance is covered; whether deadlock analysis between batch run units and DC tasks is included; whether IDMS db-status error code investigation (0307, 0326, 0801 record locked, 2002 bind sequence error) and root cause tracing are within the retainer scope; and whether recovery from IDMS ABEND-leaving-run-unit-open incidents (requiring DCMT VARY TASK TERM intervention) is included in the retainer or billed separately as incident response.

How should IDMS developer retainer hours be logged?

Log each IDMS retainer session with: IDMS release, schema name, subschema name, program name, the DML statement that was wrong, the expected behavior, the actual behavior, the business impact, the fix, and the test result. For a FIND vs OBTAIN investigation: Broadcom IDMS r20.0; z/OS 2.4; schema AGENTDB; subschema AGENTUPD-SS; COBOL II AGENTUPD; AGENTUPDJ job; schema records AGENT (8,437) and POLICY (142,293); set AGENT-POLICIES (OWNER: AGENT, MEMBER: POLICY, SORTED by POLICY-DATE DESC); bug: OBTAIN FIRST POLICY (correct for first iteration) then FIND NEXT POLICY in loop (currency only — working storage not refreshed); POLICY-PREMIUM-AMOUNT stale at first-policy value across all iterations; 6,214 agents: MONTHLY-PREMIUM = zero (first policy prior month); 2,223 agents: MONTHLY-PREMIUM inflated (first policy current month × policy count); fix: FIND NEXT replaced with OBTAIN NEXT; 10 sample agents tested — all MONTHLY-PREMIUM values correct; AGENTUPDJ rerun against backup; hours: 0.5h commission output analysis + 1.5h source review + 0.5h fix + 1.0h test + 1.0h recovery = 4.5h total.

See also: IMS/DB developer retainer · Db2 developer retainer · Datacom developer retainer