Como interpretar o cabeçalho/headers de uma pagina
O motivo da necessidade de entender como é internamente uma pagina do Informix é para situações onde é preciso identificar um dado corrompido, identificar certos tipos de paginas devido algum bug , migração entre versões e até para questão de entendimento de como o dado está sendo realmente gravado e o espaço utilizad por ele.
O cabeçalho/header de uma pagina pode ser pego de duas forma, através da tabela sysmaster:syspaghdr ou do comando oncheck -pp/-pP
Observação, os exemplos aqui demonstrados são baseados na versão 11.50 UC3 Developer e pode ocorrer variações com relação a versões mais antigas ou mais novas
O resultado do comando oncheck será algo como :
$ oncheck -pP 1 20 -h addr stamp chksum nslots flag type frptr frcnt next prev 1:20 60655 ecfa 5 802 PARTN 324 1700 0 0
Campos exibidos no oncheck
- addr: Endereço fisico
- stamp: timestamp
- chksum: Checksum da pagina (este campo foi incluido na versão 9.40)
- nslots: Numero de slots utilizados (limite de 255)
- flag: Flags da pagina
- type: Tipo da pagina (baseado nos flags)
- frptr: Off-set para próximo slot livre
- frcnt: Bytes livres na pagina
- next: Endereço da proxima pagina (apenas quando registro utiliza mais de uma pagina)
Também é utilizado para identificar versão de pagina, onde é utilizado uma técnica muito simples, a contagem começa a partir da do valor 0x1000000 (16777216), a versão 2 possui o valor 0x2000000, a versão 3 é 0x3000000 e por ai vai. - prev: Endereço da pagina anterior (apenas quando registro utiliza mais de uma pagina)
Campos da tabela syspaghdr que não são exibidos no oncheck
- pg_partnum: Tblspace number que a pagina pertence
- pg_pagenum: Numero da logical page
- pg_pagesize: Tamanho da pagina (2k, 4k, 8k, 12k, 16k)
Flags
Os flags das paginas são exibidos em valores hexadecimal para o comando oncheck.
O script abaixo foi Copiado do $INFORMIXDIR/etc/sysmaster.sql
create table syspaghdr
(
pg_partnum integer, { partition number of page }
pg_pagenum integer, { logical page number in partn }
pg_chunk integer, { pg_chunk }
pg_offset integer, { pg_offset }
pg_stamp integer, { pg_stamp }
pg_chksum smallint, { pg_chksum }
pg_pagesize smallint, { pg_pagesize }
pg_nslots smallint, { pg_nslots }
pg_flags smallint, { pg_flags }
pg_frptr smallint, { pg_frptr }
pg_frcnt smallint, { pg_frcnt }
pg_next integer, { pg_pgnext }
pg_prev integer { pg_pgprev }
);
Campo flags
Baseado no script: $INFORMIXDIR/etc/sysmaster.sql com o comando abaixo é possível identificar os valores utilizados pelo campo FLAGS .
$ echo "select txt[1,40], flags, hex(flags) from flags_text where tabname = 'syspaghdr' " | dbaccess sysmaster txt flags (expression) Data Page 1 0x00000001 Partition Descriptor Page 2 0x00000002 Partition Free List Page 4 0x00000004 Chunk Free List Page 8 0x00000008 Remainder Data Page 9 0x00000009 Partition Resident BLOB Page 11 0x0000000B Blobspace Resident BLOB Page 12 0x0000000C BLOB Chunk Free List Bit Page 13 0x0000000D BLOB Chunk BLOB Map Page 14 0x0000000E B-Tree Node Page 16 0x00000010 B-Tree Root Node 32 0x00000020 B-Tree Twig Node 64 0x00000040 B-Tree Leaf Node 128 0x00000080 Logical Log Page 256 0x00000100 Last Page of Log Log 512 0x00000200 Sync Page of Log Log 1024 0x00000400 Physical Log Page 2048 0x00000800 Reserved Page 4096 0x00001000 Temporarily no physical logging required 8192 0x00002000 Temporarily no physical logging required 16384 0x00004000 B-Tree Leaf Page containing deleted Item 32768 0x00008000
Como identificar flags
Para identificar cada um destes flags pode utilizar a SPL BitVal existente no sysmaster ou através de outros meios matematicos, segue exemplos.
Exemplo de como identificar através de uma aplicação escrita em C .
$ cat flags.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// by Cesar Inacio Martins
// Copyright 2009 - todos os direitos reservados
//
// Este programa exibe em hexadecimal , decimal e binario
// cada flag ativo no numero passado como parametro.
// O motivo de criação deste programa é facilitar a identificacao de
// quais flags estão setados em page headers do Informix
//
// ATENÇÃO: O parametro recebido deve ser em base DECIMAL
void printBits(unsigned int pC);
int main(int argc, char *argv[] ) {
unsigned int i,x,y;
i=x=y=0;
if ( argc <= 0 ) {
printf("\nNenhum parametro informado!\n");
exit(1);
}
i=atoi(argv[1]);
printf(" hex: %#04x \t int: %03i \t bits:", i, i );
printBits(i);
printf("\n");
for ( x=32768; x!=0; x>>=1){
if ( x & i ) {
printf(" flag: %8i - %#8x - ",x,x);
printBits(x & i );
}
}
}
void printBits(unsigned int pC){
unsigned int i;
i=0;
for ( i=32768 ; i != 0x0 ; i>>=1 ) {
if ( i & 0x0888 ) printf ("-") ;
pC & i ? printf("1"): printf("0");
}
printf("\n");
}
$ gcc flags.c -o flags
$ ./flags 2050
hex: 0x802 int: 2050 bits:0000-1000-0000-0010
flag: 2048 - 0x800 - 0000-1000-0000-0000
flag: 2 - 0x2 - 0000-0000-0000-0010
Identificando flags utilizando a função bitval do Informix.
$ echo "
select pg_offset,hex(pg_chksum) chksum, hex(pg_flags) hexflags, pg_flags
, sysmaster:bitval(pg_flags,'0x01') is_data
, sysmaster:bitval(pg_flags,'0x02') is_tblspace
, sysmaster:bitval(pg_flags,'0x04') is_freetblspace
, sysmaster:bitval(pg_flags,'0x10') is_btreenode
, sysmaster:bitval(pg_flags,'0x80') is_btreeleaf
from syspaghdr
where pg_partnum = 11534412
" | dbaccess sysmaster
Database selected.
pg_offset 1516
chksum 0x0000226C
hexflags 0x00000804
pg_flags 2052
is_data 0
is_tblspace 0
is_freetblspace 1
is_btreenode 0
is_btreeleaf 0
pg_offset 1517
chksum 0x0000076E
hexflags 0x00002801
pg_flags 10241
is_data 1
is_tblspace 0
is_freetblspace 0
is_btreenode 0
is_btreeleaf 0
2 row(s) retrieved.
Database closed.
- 526 leituras





Comentar