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.
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.
┌──────────────────────────────────────────────────────────────┐ │ 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
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)
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.
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.
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 STATUS | Situação |
|---|---|
| 00 | Operação bem-sucedida |
| 02 | READ sequencial — registro duplicado encontrado (não se aplica a RRDS) |
| 10 | READ sequencial atingiu fim do dataset |
| 22 | WRITE — slot já ocupado (INVALID KEY em ACCESS RANDOM) |
| 23 | READ/DELETE/REWRITE — slot vazio ou número fora do range |
| 24 | WRITE — número de slot além do limite do dataset |
| 30 | Erro 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).
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.
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.
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.
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)
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
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ário | Por 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 |
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.
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.
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
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.
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ção | O 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 |
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
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)
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.