home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / support / pagedoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-11  |  11.4 KB  |  494 lines

  1. /*
  2.  *  pagedoc.c -- postgres page doctor.
  3.  *
  4.  *    This program understands page formats for postgres heap and index
  5.  *    relations, and can be used to dump the pages.  it doesn't know
  6.  *    about user data in tuples; it only knows about tuple headers.
  7.  *
  8.  *    Usage:
  9.  *        pagedoc [-h|b|r] [-d level] filename
  10.  *
  11.  *        -h, -b, and -r are for heap, btree, and rtree files,
  12.  *            respectively.
  13.  *        -d level sets the detail level:  0 is just page summaries,
  14.  *            1 is page summaries plus line pointer summaries,
  15.  *            and 2 is 1 plus tuples.
  16.  *
  17.  *    -h and -d0 are the defaults.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <sys/file.h>
  22.  
  23. static char *RcsId = "$Header: /private/postgres/src/support/RCS/pagedoc.c,v 1.1 1992/08/12 03:24:01 mao Exp $";
  24.  
  25. extern char    *optarg;
  26. extern int    optind, opterr;
  27.  
  28. typedef struct ItemIdData {
  29.     unsigned        lp_off:13,        /* offset to tuple */
  30.             lp_flags:6,        /* itemid flags */
  31.             lp_len:13;        /* length of tuple */
  32. } ItemIdData;
  33.  
  34. #define LP_USED        0x01    /* this line pointer is being used */
  35. #define LP_IVALID    0x02    /* this tuple is known to be insert valid */
  36. #define LP_DOCNT    0x04    /* this tuple continues on another page */
  37. #define LP_CTUP        0x08    /* this is a continuation tuple */
  38. #define LP_LOCK        0x10    /* this is a lock */
  39. #define LP_ISINDEX    0x20    /* this is an internal index tuple */
  40.  
  41. typedef struct ItemPointerData {
  42.     unsigned short    block[2];
  43.     unsigned short    offset;
  44. } ItemPointerData;
  45.  
  46. typedef struct HeapTupleData {
  47.     unsigned int    t_len;
  48.     ItemPointerData    t_ctid;
  49.     ItemPointerData    t_chain;
  50.     union {
  51.     ItemPointerData        l_ltid;
  52.     char            *l_lock;    /* actually a RuleLock */
  53.     } t_lock;
  54.     unsigned long    t_oid;
  55.     unsigned short    t_cmin;
  56.     unsigned short    t_cmax;
  57.     unsigned long    t_xmin;
  58.     unsigned long    t_xmax;
  59.     unsigned long    t_tmin;
  60.     unsigned long    t_tmax;
  61.     unsigned short    t_natts;
  62.     char        t_vtype;
  63.     char        t_infomask;
  64.     char        t_locktype;
  65.     char        t_bits[1];
  66. } HeapTupleData;
  67.  
  68. typedef struct IndexTupleData {
  69.     ItemPointerData        t_tid;
  70.  
  71. #define ITUP_HASNULLS    0x8000
  72. #define ITUP_HASVARLENA    0x4000
  73. #define ITUP_HASRULES    0x2000
  74. #define ITUP_LENMASK    0x1fff
  75.  
  76.     unsigned short        t_info;
  77. } IndexTupleData;
  78.  
  79. typedef struct BTItemData {
  80.     unsigned long    bti_oid;
  81.     IndexTupleData    bti_itup;
  82. } BTItemData;
  83.  
  84. typedef struct PageHeaderData {
  85.     unsigned short    pd_lower;
  86.     unsigned short    pd_upper;
  87.     unsigned short    pd_special;
  88.     unsigned short    pd_opaque;
  89.     ItemIdData        pd_linp[1];        /* line pointers start here */
  90. } PageHeaderData;
  91.  
  92. typedef struct BTPageOpaqueData {
  93.     unsigned short    btpo_prev;
  94.     unsigned short    btpo_next;
  95.     unsigned short    btpo_flags;
  96. } BTPageOpaqueData;
  97.  
  98. typedef struct BTMetaPageData {
  99.     unsigned long    btm_magic;
  100.     unsigned long    btm_version;
  101.     unsigned long    btm_root;
  102.     unsigned long    btm_freelist;
  103. } BTMetaPageData;
  104.  
  105. typedef struct RTreePageOpaqueData {
  106.     unsigned long    rtpo_flags;
  107.  
  108. #define RTF_LEAF    (1 << 0)
  109.  
  110. } RTreePageOpaqueData;
  111.  
  112. #define BTP_LEAF    (1 << 0)
  113. #define BTP_ROOT    (1 << 1)
  114. #define BTP_FREE    (1 << 2)
  115.  
  116. #define    HEAP    0
  117. #define BTREE    1
  118. #define RTREE    2
  119.  
  120. extern void        pagedoc();
  121. extern char        *readpage();
  122. extern void        heappage();
  123. extern void        btreepage();
  124. extern void        rtreepage();
  125. extern void        showlinp();
  126. extern void        showheaptup();
  127. extern void        showindextup();
  128. extern int        PageGetNEntries();
  129. extern unsigned long    ItemPointerGetBlockNumber();
  130.  
  131. main(argc, argv)
  132.     int argc;
  133.     char **argv;
  134. {
  135.     int reltype;
  136.     char *relname;
  137.     int level;
  138.     char c;
  139.     int errs;
  140.     int fd;
  141.  
  142.     errs = 0;
  143.     level = 0;
  144.     reltype = HEAP;
  145.  
  146.     while ((c = getopt(argc, argv, "hbrd:")) != EOF) {
  147.     switch (c) {
  148.         case 'h':
  149.         reltype = HEAP;
  150.         break;
  151.         case 'b':
  152.         reltype = BTREE;
  153.         break;
  154.         case 'r':
  155.         reltype = RTREE;
  156.         break;
  157.         case 'd':
  158.         level = atoi(optarg);
  159.         if  (level < 0)
  160.             errs++;
  161.         break;
  162.         default:
  163.         errs++;
  164.         break;
  165.     }
  166.     }
  167.  
  168.     if (optind != argc - 1)
  169.     errs++;
  170.  
  171.     if (errs) {
  172.     fprintf(stderr, "usage: %s [-hbr] [-d level] file\n", argv[0]);
  173.     fflush(stderr);
  174.     exit (1);
  175.     }
  176.  
  177.     relname = argv[optind];
  178.     if ((fd = open(relname, O_RDONLY, 0600)) < 0) {
  179.     perror(relname);
  180.     fflush(stderr);
  181.     exit (1);
  182.     }
  183.  
  184.     pagedoc(fd, level, reltype);
  185.  
  186.     if (close(fd) < 0) {
  187.     fprintf(stderr, "close: ");
  188.     perror(relname);
  189.     fflush(stderr);
  190.     exit (1);
  191.     }
  192.  
  193.     exit (0);
  194. }
  195.  
  196. void
  197. pagedoc(fd, level, reltype)
  198.     int fd;
  199.     int level;
  200.     int reltype;
  201. {
  202.     int i;
  203.     char *buf;
  204.  
  205.     i = 0;
  206.     while ((buf = readpage(fd)) != (char *) NULL) {
  207.     switch (reltype) {
  208.         case HEAP:
  209.         heappage(i, buf, level);
  210.         break;
  211.         case BTREE:
  212.         btreepage(i, buf, level);
  213.         break;
  214.         case RTREE:
  215.         rtreepage(i, buf, level);
  216.         break;
  217.         default:
  218.         /* should never happen */
  219.         fprintf(stderr, "invalid reltype %d\n", reltype);
  220.         fflush(stderr);
  221.         return;
  222.     }
  223.     i++;
  224.     }
  225. }
  226.  
  227. char pagebuf[8192];
  228.  
  229. char *
  230. readpage(fd)
  231.     int fd;
  232. {
  233.     int nbytes;
  234.  
  235.     nbytes = read(fd, pagebuf, 8192);
  236.     if (nbytes == 0)
  237.     return ((char *) NULL);
  238.     if (nbytes < 0) {
  239.     perror("read");
  240.     fflush(stderr);
  241.     exit (1);
  242.     }
  243.     if (nbytes != 8192) {
  244.     fprintf(stderr, "read: expected 8192 bytes, got %d (partial page?)\n",
  245.             nbytes);
  246.     fflush(stderr);
  247.     exit (1);
  248.     }
  249.  
  250.     return (pagebuf);
  251. }
  252.  
  253. void
  254. heappage(pgno, buf, level)
  255.     int pgno;
  256.     char *buf;
  257.     int level;
  258. {
  259.     PageHeaderData *phdr;
  260.     ItemIdData *linp;
  261.     int nlinps;
  262.     int i;
  263.     HeapTupleData *htup;
  264.  
  265.     phdr = (PageHeaderData *) buf;
  266.     nlinps = PageGetNEntries(phdr);
  267.     printf("[%03d]\tlower: %d upper: %d special: %d opaque 0x%hx (%d items)\n",
  268.         pgno, phdr->pd_lower, phdr->pd_upper, phdr->pd_special,
  269.         phdr->pd_opaque, nlinps);
  270.     if (phdr->pd_lower < 8)
  271.     printf("    **** lower too low!\n");
  272.     if (phdr->pd_lower > 8192)
  273.     printf("    **** lower too high!\n");
  274.     if (phdr->pd_upper < 12)
  275.     printf("    **** upper too low!\n");
  276.     if (phdr->pd_upper > 8192)
  277.     printf("    **** upper too high!\n");
  278.     if (phdr->pd_special > 8192)
  279.     printf("    **** special too high!\n");
  280.  
  281.     /* level 0 is page headers only */
  282.     if (level == 0)
  283.     return;
  284.  
  285.     for (i = 0, linp = &(phdr->pd_linp[0]); i < nlinps; linp++, i++) {
  286.     showlinp(i, linp);
  287.     /* level > 1 means show everything */
  288.     if (level > 1) {
  289.         htup = (HeapTupleData *) &(buf[linp->lp_off]);
  290.         showheaptup(htup);
  291.     }
  292.     }
  293. }
  294.  
  295. void
  296. btreepage(pgno, buf, level)
  297.     int pgno;
  298.     char *buf;
  299.     int level;
  300. {
  301.     PageHeaderData *phdr;
  302.     ItemIdData *linp;
  303.     int nlinps;
  304.     int i;
  305.     BTItemData *bti;
  306.     BTPageOpaqueData *btpo;
  307.     BTMetaPageData *meta;
  308.  
  309.     /* if this is the btree metadata page, handle it specially */
  310.     if (pgno == 0) {
  311.     meta = (BTMetaPageData *) buf;
  312.     printf("[meta]\tmagic 0x%06lx version %ld root %ld freelist %ld\n",
  313.         meta->btm_magic, meta->btm_version, meta->btm_root,
  314.         meta->btm_freelist);
  315.     if (meta->btm_magic != 0x053162)
  316.         printf("    **** magic number is bogus!\n");
  317.     return;
  318.     }
  319.  
  320.     phdr = (PageHeaderData *) buf;
  321.     nlinps = PageGetNEntries(phdr);
  322.     printf("[%03d]\tlower: %d upper: %d special: %d opaque 0x%hx (%d items)\n",
  323.         pgno, phdr->pd_lower, phdr->pd_upper, phdr->pd_special,
  324.         phdr->pd_opaque, nlinps);
  325.     btpo = (BTPageOpaqueData *) &(buf[phdr->pd_special]);
  326.     printf("\tprev %d next %d", btpo->btpo_prev, btpo->btpo_next);
  327.     if (btpo->btpo_flags & BTP_LEAF)
  328.     printf(" <leaf>");
  329.     if (btpo->btpo_flags & BTP_ROOT)
  330.     printf(" <root>");
  331.     if (!(btpo->btpo_flags & (BTP_LEAF|BTP_ROOT)))
  332.     printf(" <internal>");
  333.     if (btpo->btpo_flags & BTP_FREE)
  334.     printf(" <free>");
  335.     if (btpo->btpo_next != 0)
  336.     printf(" (item 001 is high key on page)");
  337.     else
  338.     printf(" (no high key)");
  339.     printf("\n");
  340.     if (phdr->pd_lower < 8)
  341.     printf("    **** lower too low!\n");
  342.     if (phdr->pd_lower > 8192)
  343.     printf("    **** lower too high!\n");
  344.     if (phdr->pd_upper < 12)
  345.     printf("    **** upper too low!\n");
  346.     if (phdr->pd_upper > 8192)
  347.     printf("    **** upper too high!\n");
  348.     if (phdr->pd_special > 8192)
  349.     printf("    **** special too high!\n");
  350.  
  351.     /* level 0 is page headers only */
  352.     if (level == 0)
  353.     return;
  354.  
  355.     for (i = 0, linp = &(phdr->pd_linp[0]); i < nlinps; linp++, i++) {
  356.     showlinp(i, linp);
  357.     /* level > 1 means show everything */
  358.     if (level > 1) {
  359.         bti = (BTItemData *) &(buf[linp->lp_off]);
  360.         printf("\t\toid %ld ", bti->bti_oid);
  361.         showindextup(&bti->bti_itup);
  362.     }
  363.     }
  364. }
  365.  
  366. void
  367. rtreepage(pgno, buf, level)
  368.     int pgno;
  369.     char *buf;
  370.     int level;
  371. {
  372.     PageHeaderData *phdr;
  373.     ItemIdData *linp;
  374.     int nlinps;
  375.     int i;
  376.     RTreePageOpaqueData *rtpo;
  377.     IndexTupleData *itup;
  378.  
  379.     phdr = (PageHeaderData *) buf;
  380.     rtpo = (RTreePageOpaqueData *) &(buf[phdr->pd_special]);
  381.     nlinps = PageGetNEntries(phdr);
  382.     printf("[%03d]\tlower: %d upper: %d special: %d opaque 0x%hx %s (%d items)\n",
  383.         pgno, phdr->pd_lower, phdr->pd_upper, phdr->pd_special,
  384.         phdr->pd_opaque,
  385.         ((rtpo->rtpo_flags & RTF_LEAF) ? "<leaf>":"internal"), nlinps);
  386.     if (phdr->pd_lower < 8)
  387.     printf("    **** lower too low!\n");
  388.     if (phdr->pd_lower > 8192)
  389.     printf("    **** lower too high!\n");
  390.     if (phdr->pd_upper < 12)
  391.     printf("    **** upper too low!\n");
  392.     if (phdr->pd_upper > 8192)
  393.     printf("    **** upper too high!\n");
  394.     if (phdr->pd_special > 8192)
  395.     printf("    **** special too high!\n");
  396.  
  397.     /* level 0 is page headers only */
  398.     if (level == 0)
  399.     return;
  400.  
  401.     for (i = 0, linp = &(phdr->pd_linp[0]); i < nlinps; linp++, i++) {
  402.     showlinp(i, linp);
  403.     /* level > 1 means show everything */
  404.     if (level > 1) {
  405.         itup = (IndexTupleData *) &(buf[linp->lp_off]);
  406.         showindextup(itup);
  407.     }
  408.     }
  409. }
  410.  
  411. void
  412. showlinp(itemno, linp)
  413.     int itemno;
  414.     ItemIdData *linp;
  415. {
  416.     int off;
  417.  
  418.     printf("\t{%03d}\t off %d length %d flags [",
  419.        itemno + 1, linp->lp_off, linp->lp_len);
  420.     if (linp->lp_flags & LP_USED)
  421.     printf(" LP_USED");
  422.     if (linp->lp_flags & LP_IVALID)
  423.     printf(" LP_IVALID");
  424.     if (linp->lp_flags & LP_DOCNT)
  425.     printf(" LP_DOCNT");
  426.     if (linp->lp_flags & LP_CTUP)
  427.     printf(" LP_CTUP");
  428.     if (linp->lp_flags & LP_LOCK)
  429.     printf(" LP_LOCK");
  430.     if (linp->lp_flags & LP_ISINDEX)
  431.     printf(" LP_ISINDEX");
  432.     printf(" ]\n");
  433.     if ((off = linp->lp_off) > 8192)
  434.     printf("\t    **** off too high!\n");
  435.     if (off & 0x3)
  436.     printf("\t    **** off is bogus -- unaligned tuple pointer!");
  437.     if (linp->lp_len > 8192)
  438.     printf("\t    **** len too high!\n");
  439.     if (!(linp->lp_flags & LP_USED))
  440.     printf("\t    **** item not used!\n");
  441. }
  442.  
  443. void
  444. showheaptup(htup)
  445.     HeapTupleData *htup;
  446. {
  447.     printf("\t\tlen %d ctid <%d,0,%d> chain <%d,0,%d> oid %ld\n",
  448.        htup->t_len, ItemPointerGetBlockNumber(htup->t_ctid.block),
  449.        htup->t_ctid.offset, ItemPointerGetBlockNumber(htup->t_chain.block),
  450.        htup->t_chain.offset, htup->t_oid);
  451.     printf("\t\tcmin/max %d/%d xmin/max %ld/%ld tmin/max %ld/%ld\n",
  452.        htup->t_cmin, htup->t_cmax, htup->t_xmin, htup->t_xmax,
  453.        htup->t_tmin, htup->t_tmax);
  454.     printf("\t\tnatts %d vtype %c infomask 0x%x locktype %c\n",
  455.        htup->t_natts, htup->t_vtype, htup->t_infomask, htup->t_locktype);
  456. }
  457.  
  458. void
  459. showindextup(itup)
  460.     IndexTupleData *itup;
  461. {
  462.     printf("heap tid <%d,0,%d> info [",
  463.        ItemPointerGetBlockNumber(itup->t_tid.block), itup->t_tid.offset);
  464.     if (itup->t_info & ITUP_HASNULLS)
  465.     printf(" HASNULLS");
  466.     if (itup->t_info & ITUP_HASVARLENA)
  467.     printf(" HASVARLENA");
  468.     if (itup->t_info & ITUP_HASRULES)
  469.     printf(" HASRULES");
  470.     printf(" ] length %d\n", itup->t_info & ITUP_LENMASK);
  471. }
  472.  
  473. int
  474. PageGetNEntries(phdr)
  475.     PageHeaderData *phdr;
  476. {
  477.     int n;
  478.  
  479.     n = (phdr->pd_lower - (2 * sizeof(unsigned long))) / sizeof(ItemIdData);
  480.  
  481.     return (n);
  482. }
  483.  
  484. unsigned long
  485. ItemPointerGetBlockNumber(iptr)
  486.     ItemPointerData *iptr;
  487. {
  488.     unsigned long b;
  489.  
  490.     b = (unsigned long) ((iptr->block[0] << 16) + iptr->block[1]);
  491.  
  492.     return (b);
  493. }
  494.