1. RRDS — conceito e estrutura de slots

Um RRDS organiza os dados em slots numerados sequencialmente a partir de 1. Cada slot tem o mesmo tamanho fixo e pode estar ocupado (contém um registro) ou vazio (slot nunca usado ou deletado). O acesso é feito diretamente pelo número do slot — sem índice, sem chave de negócio.

🦕 Analogia
Imagine um estacionamento numerado de 1 a 500. Você não precisa de uma chave para encontrar seu carro — só o número da vaga. Cada vaga tem o mesmo tamanho (um carro). Algumas vagas estão ocupadas, outras estão vazias. O RRDS funciona exatamente assim: slots numerados, tamanho fixo, acesso direto por número.

Internamente, um RRDS tem apenas um componente DATA — sem INDEX. Cada CI contém um número fixo de slots, determinado pelo tamanho do registro e pelo CISZ. O VSAM mantém um bit de flag por slot no RDF indicando se está ocupado ou vazio.

Estrutura interna de um CI do RRDS
┌──────────────────────────────────────────────────────────────┐
│  Slot 1    │  Slot 2    │  Slot 3    │  ...  │ CIDF │ RDFs  │
│ (ocupado)  │  (vazio)   │ (ocupado)  │       │      │       │
└──────────────────────────────────────────────────────────────┘

RDF por slot: flag 0x40 = ocupado  |  flag 0x00 = vazio
Todos os slots têm o mesmo tamanho = RECORDSIZE máximo

2. DEFINE CLUSTER para RRDS

IDCAMS — DEFINE CLUSTER RRDS
  DEFINE CLUSTER                              -
         (NAME(PROD.TABPARAM.RRDS)            -
          CYLINDERS(1 1)                      -
          RECORDSIZE(80 80)                   -
          NUMBERED                            -
          SHAREOPTIONS(2 3)                   -
          REUSE)                             -
         DATA                               -
         (NAME(PROD.TABPARAM.RRDS.DATA)      -
          CISZ(4096))

Diferenças em relação ao KSDS:

  • NUMBERED em vez de INDEXED — palavra-chave que declara RRDS
  • RECORDSIZE médio = máximo — slots são de tamanho fixo, sem exceção
  • Sem parâmetro KEYS — o "índice" é o número do slot
  • Sem componente INDEX — apenas DATA
  • Sem FREESPACE — não há inserção entre registros; slots são pré-alocados
  • REUSE — permite reabrir o dataset resetando para o slot 1 (útil para datasets temporários)
✅ Calcular quantidade de slots
Com CYLINDERS(1 1), RECORDSIZE(80) e CISZ(4096): cada CI comporta aproximadamente 4096 ÷ (80 + 3) ≈ 49 slots. Um cilindro 3390 tem 15 trilhas × 56.664 bytes ÷ 4096 ≈ 207 CIs × 49 slots ≈ 10.000 slots. Ajuste CYLINDERS de acordo com o número máximo esperado de registros — o RRDS não cresce além do espaço alocado.

3. RRDS no COBOL — RELATIVE KEY

No COBOL, RRDS é declarado com ORGANIZATION IS RELATIVE. O número do slot fica numa data item definida como RELATIVE KEY.

COBOL — RRDS com acesso aleatório
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT ARQ-PARAM ASSIGN TO TABPARAM
               ORGANIZATION IS RELATIVE
               ACCESS MODE IS RANDOM
               RELATIVE KEY IS WS-NUM-SLOT
               FILE STATUS IS WS-FS-PARAM.

       DATA DIVISION.
       FILE SECTION.
       FD  ARQ-PARAM.
       01  REG-PARAM.
           05 PAR-CODIGO       PIC 9(03).
           05 PAR-DESCRICAO    PIC X(50).
           05 PAR-VALOR        PIC 9(06)V99.
           05 PAR-ATIVO        PIC X(01).
           05 FILLER           PIC X(18).

       WORKING-STORAGE SECTION.
       01  WS-NUM-SLOT         PIC 9(08) COMP.
       01  WS-FS-PARAM         PIC XX.

       PROCEDURE DIVISION.

       0000-PRINCIPAL.
      *    Ler slot 7 diretamente
           MOVE 7 TO WS-NUM-SLOT
           READ ARQ-PARAM
               INVALID KEY
                   DISPLAY 'SLOT ' WS-NUM-SLOT ' VAZIO OU INVALIDO'
               NOT INVALID KEY
                   PERFORM 1000-PROCESSA-PARAM
           END-READ

      *    Gravar no slot 15
           MOVE 15              TO WS-NUM-SLOT
           MOVE 015             TO PAR-CODIGO
           MOVE 'TAXA JUROS MES' TO PAR-DESCRICAO
           MOVE 1.25            TO PAR-VALOR
           MOVE 'S'             TO PAR-ATIVO
           WRITE REG-PARAM
               INVALID KEY
                   DISPLAY 'SLOT 15 JA OCUPADO'
               NOT INVALID KEY
                   DISPLAY 'SLOT 15 GRAVADO'
           END-WRITE

      *    Atualizar slot corrente (apos READ)
           MOVE 7 TO WS-NUM-SLOT
           READ ARQ-PARAM
           MOVE 'N' TO PAR-ATIVO
           REWRITE REG-PARAM
               INVALID KEY
                   DISPLAY 'ERRO NO REWRITE'
           END-REWRITE

      *    Deletar slot 7
           MOVE 7 TO WS-NUM-SLOT
           DELETE ARQ-PARAM RECORD
               INVALID KEY
                   DISPLAY 'SLOT 7 JA VAZIO'
           END-DELETE

           STOP RUN.
⚠️ RELATIVE KEY é COMP, não DISPLAY
A data item de RELATIVE KEY deve ser um inteiro positivo definido como PIC 9(n) COMP (binary). Definir como DISPLAY ou com casas decimais causa erro de compilação. O tamanho mínimo prático é PIC 9(08) COMP para suportar datasets com até 999.999.999 slots.

FILE STATUS do RRDS

FILE STATUSSituação
00Operação bem-sucedida
02READ sequencial — registro duplicado encontrado (não se aplica a RRDS)
10READ sequencial atingiu fim do dataset
22WRITE — slot já ocupado (INVALID KEY em ACCESS RANDOM)
23READ/DELETE/REWRITE — slot vazio ou número fora do range
24WRITE — número de slot além do limite do dataset
30Erro de I/O permanente

4. Acesso sequencial e dinâmico em RRDS

Além do acesso aleatório, o RRDS suporta leitura sequencial (slot por slot, do menor para o maior) e acesso dinâmico (mistura de READ por número e READ NEXT).

COBOL — RRDS sequencial (varre todos os slots ocupados)
       FILE-CONTROL.
           SELECT ARQ-PARAM ASSIGN TO TABPARAM
               ORGANIZATION IS RELATIVE
               ACCESS MODE IS SEQUENTIAL
               RELATIVE KEY IS WS-NUM-SLOT
               FILE STATUS IS WS-FS-PARAM.

       PROCEDURE DIVISION.
       0000-PRINCIPAL.
           OPEN INPUT ARQ-PARAM
           PERFORM UNTIL WS-FS-PARAM = '10'
               READ ARQ-PARAM NEXT
                   AT END CONTINUE
                   NOT AT END
                       DISPLAY 'SLOT: ' WS-NUM-SLOT
                               ' COD: ' PAR-CODIGO
               END-READ
           END-PERFORM
           CLOSE ARQ-PARAM
           STOP RUN.
✅ READ NEXT pula slots vazios
Em acesso sequencial, o VSAM pula automaticamente os slots com flag de vazio e retorna apenas os slots ocupados, em ordem crescente de número. A RELATIVE KEY é atualizada a cada READ para refletir o número do slot lido.
COBOL — RRDS dinâmico (posicionar + varrer)
       FILE-CONTROL.
           SELECT ARQ-PARAM ASSIGN TO TABPARAM
               ORGANIZATION IS RELATIVE
               ACCESS MODE IS DYNAMIC
               RELATIVE KEY IS WS-NUM-SLOT
               FILE STATUS IS WS-FS-PARAM.

       PROCEDURE DIVISION.
       0000-PRINCIPAL.
           OPEN INPUT ARQ-PARAM

      *    Posicionar a partir do slot 50
           MOVE 50 TO WS-NUM-SLOT
           START ARQ-PARAM KEY >= WS-NUM-SLOT
               INVALID KEY DISPLAY 'NAO HA SLOTS >= 50'
           END-START

      *    Ler sequencialmente a partir do slot 50
           PERFORM UNTIL WS-FS-PARAM = '10'
               READ ARQ-PARAM NEXT
                   AT END CONTINUE
                   NOT AT END
                       DISPLAY 'SLOT ' WS-NUM-SLOT ': '
                               PAR-DESCRICAO
               END-READ
           END-PERFORM

           CLOSE ARQ-PARAM
           STOP RUN.

5. Slots vazios e deleção

Deletar um registro RRDS marca o slot como vazio — o espaço físico permanece alocado mas disponível para reuso. Um WRITE subsequente com o mesmo número de slot ocupa o slot vazio novamente.

Ciclo de vida de um slot RRDS
Estado inicial:  slot 5 = VAZIO
WRITE slot 5  →  slot 5 = OCUPADO (com dados)
REWRITE slot 5 → slot 5 = OCUPADO (dados atualizados)
DELETE slot 5  → slot 5 = VAZIO   (espaço disponível)
WRITE slot 5  →  slot 5 = OCUPADO (novo registro)

READ slot 5 com slot VAZIO → FILE STATUS '23' (INVALID KEY)
💗 Por que isso importa?
Em KSDS, um DELETE libera espaço lógico mas o registro deletado fica como "lixo" até a reorganização. No RRDS não há lixo — o slot deletado pode ser reocupado imediatamente, sem fragmentação, sem reorganização. Essa é uma vantagem do RRDS sobre o KSDS quando você tem muitas inserções e deleções no mesmo espaço de chaves.

Verificar se um slot está vazio antes de gravar

COBOL — verificar slot antes do WRITE
       1000-GRAVAR-SLOT.
           MOVE WS-NUMERO-DESEJADO TO WS-NUM-SLOT
           READ ARQ-PARAM
           EVALUATE WS-FS-PARAM
               WHEN '23'
      *            Slot vazio — pode gravar
                   PERFORM 1100-WRITE-SLOT
               WHEN '00'
      *            Slot ocupado — decidir: rewrite ou erro
                   DISPLAY 'SLOT JA TEM DADOS: ' PAR-DESCRICAO
               WHEN OTHER
                   DISPLAY 'ERRO INESPERADO: ' WS-FS-PARAM
           END-EVALUATE.

6. Casos de uso do RRDS

CenárioPor que RRDS é adequado
Tabela de parâmetros por código numérico Código 001–500 mapeia diretamente para slot 1–500; acesso O(1) sem índice
Tabela de agências bancárias por número Agência 0001–9999 → slot 1–9999; busca instantânea sem KSDS overhead
Fila de trabalho com slots numerados Produtor grava no slot N; consumidor lê o slot e deleta; reuso imediato
Tabela de dispatch/lookup Código de transação (1–200) mapeia para configuração; leitura direta sem WHERE clause
⚠️ Quando NÃO usar RRDS
RRDS não é adequado quando a chave de negócio não é numérica sequencial compacta. Se os códigos forem esparsos (ex: 1, 5, 200, 9999), você desperdiça slots vazios entre eles. Se a chave for alfanumérica, use KSDS. Se não precisar de acesso direto e só vai ler em sequência, use ESDS.

7. LDS — Linear Data Set

LDS é o tipo VSAM mais incomum do ponto de vista de programação COBOL: ele não tem estrutura de registro. É simplesmente um array contíguo de bytes endereçáveis por RBA (Relative Byte Address), sem CIDF, sem RDF, sem qualquer metadado VSAM dentro dos CIs.

Estrutura interna de um CI do LDS
KSDS/ESDS/RRDS:
┌───────────────────────────────────┬──────┬──────┐
│  Dados dos registros              │ CIDF │ RDFs │
└───────────────────────────────────┴──────┴──────┘

LDS:
┌──────────────────────────────────────────────────┐
│  Dados brutos (bytes 0 a CISZ-1)                 │
│  Sem CIDF, sem RDF, sem estrutura                │
└──────────────────────────────────────────────────┘

O acesso ao LDS é exclusivamente por endereço de byte (RBA), via serviços do sistema operacional — não pelo COBOL READ/WRITE convencional. O programador COBOL raramente interage diretamente com um LDS.

🦕 Analogia
Se o KSDS é como um arquivo de fichas bem organizado com índice, o LDS é como um rolo de fita virgem: bytes de 0 ao fim, sem separadores, sem etiquetas, sem estrutura. Quem grava é responsável por saber o que está em qual posição de byte.

8. DEFINE CLUSTER para LDS

IDCAMS — DEFINE CLUSTER LDS
  DEFINE CLUSTER                              -
         (NAME(DB2PM.DBNAME.TSNAME)           -
          CYLINDERS(50 10)                    -
          LINEAR                              -
          SHAREOPTIONS(3 3))                 -
         DATA                               -
         (NAME(DB2PM.DBNAME.TSNAME.DATA)     -
          CISZ(4096))

Características do DEFINE para LDS:

  • LINEAR — palavra-chave que declara LDS
  • Sem RECORDSIZE — não há conceito de registro
  • Sem KEYS — sem índice
  • Sem FREESPACE — sem estrutura de inserção
  • Apenas componente DATA
  • SHAREOPTIONS(3 3) — típico em DB2 tablespaces que precisam de acesso concorrente

9. Como o LDS é usado na prática

DB2 tablespaces

O uso mais importante do LDS no z/OS é como armazenamento de tablespaces do DB2. Cada tablespace do DB2 é fisicamente um LDS — o DB2 gerencia sua própria estrutura interna de páginas (4KB ou 32KB) dentro do espaço de bytes brutos que o LDS fornece.

Relação DB2 → LDS
DB2 tablespace DBASE001.TSPACE01
    └── LDS: DBASE001.TSPACE01.I0001.A001
              (criado automaticamente pelo DB2 ao criar o tablespace)

Páginas DB2 (4KB)  →  CIs do LDS (4096 bytes)
Extensão de página  →  RBA no LDS

O programador COBOL nunca precisa criar ou manipular esses LDS diretamente — o DB2 faz isso transparentemente. O DBA usa IDCAMS LISTCAT para verificar espaço, mas não faz REPRO ou PRINT no LDS de um tablespace ativo.

Hiperspace e dados em memória

Programas assembler e alguns subsistemas do z/OS usam LDS como área de memória expandida (hiperspace). O LDS é mapeado no espaço de endereços do programa, permitindo acesso por ponteiro como se fosse memória. Isso é completamente transparente ao COBOL.

O que o programador COBOL precisa saber sobre LDS

SituaçãoO que fazer
LISTCAT mostra LDS em vez de CLUSTER Normal — é um tablespace DB2. Não altere.
Job tenta abrir LDS como VSAM no COBOL Vai falhar — LDS não é acessível via SELECT/OPEN/READ COBOL
REPRO num LDS Possível com REPRO INFILE/OUTFILE, mas o conteúdo é bytes brutos — sem utilidade fora do sistema que o criou
PRINT num LDS Possível, mas a saída será HEX bruto sem interpretação de registros
💗 Resumo prático do LDS
Como programador COBOL, você vai encontrar LDS principalmente no LISTCAT de ambientes com DB2. Não tente abrir, ler ou escrever num LDS com COBOL — não é possível via operações de arquivo convencionais. O LDS é domínio do DB2 e do z/OS, não do programa de aplicação.

10. Comparativo completo dos 4 tipos VSAM

Característica KSDS ESDS RRDS LDS
Palavra-chave DEFINE INDEXED NONINDEXED NUMBERED LINEAR
Componentes DATA + INDEX DATA DATA DATA
Chave de acesso Campo do registro (KEYS) RBA (posição byte) Número relativo do slot RBA (bytes brutos)
Acesso aleatório Sim — por chave Sim — por RBA Sim — por número Não via COBOL
Acesso sequencial Sim — ordem de chave Sim — ordem de inserção Sim — ordem de slot Não via COBOL
Tamanho de registro Variável ou fixo Variável ou fixo Fixo obrigatório Sem registro
Inserção no meio Sim (com CI/CA Split) Não — só no fim Não — slot pré-alocado N/A
DELETE de registro Sim (lógico) Não Sim (slot fica disponível) N/A
Freespace Sim (CI% e CA%) Não Não N/A
COBOL ORGANIZATION INDEXED SEQUENTIAL RELATIVE Não acessível
Reorganização necessária Sim (CI/CA Splits) Raramente Não N/A
Uso típico Cadastros, tabelas, contas Logs, auditoria, filas Tabelas por código numérico DB2 tablespaces, hiperspaces

Quando escolher cada tipo

Árvore de decisão — escolha do tipo VSAM
Precisa de acesso por campo de negócio (nome, CPF, conta)?
  └─ SIM → KSDS

Só grava no final, nunca atualiza registros antigos (log, auditoria)?
  └─ SIM → ESDS

A chave é um número sequencial compacto (1 a N) sem buracos?
  └─ SIM → RRDS

É armazenamento interno de subsistema (DB2, IMS buffer pool)?
  └─ SIM → LDS (você não escolhe — o subsistema cria)
🟣 RRDS vs KSDS com chave numérica
Se você tem uma tabela de agências numeradas de 1 a 9999, RRDS é mais eficiente que KSDS: sem componente INDEX (economia de espaço e I/O), sem CI/CA Splits, sem reorganização. O KSDS com chave numérica ainda requer o index B+ para localizar o registro. No RRDS, o número do slot é a posição física — o VSAM calcula o RBA diretamente por aritmética: RBA = (slot − 1) × RECORDSIZE. Isso torna o READ de RRDS ligeiramente mais rápido que o READ de KSDS.