home *** CD-ROM | disk | FTP | other *** search
- /*
- * shmemdoc.c -- Shared memory doctor for POSTGRES.
- *
- * This program lets you view the state of shared memory and
- * semaphores after an abnormal termination. It assumes that
- * state is static -- that is, no other process should be changing
- * shared memory while this one is running. In order to use this,
- * you should start the postmaster with the -n option (noreinit)
- * in order to avoid reinitializing shared structures after a backend
- * terminates abnormally.
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <sys/sem.h>
-
- #include "tmp/c.h"
- #include "support/shmemipc.h"
- #include "support/shmemipci.h"
- #include "utils/memutils.h"
-
- RcsId("$Header: /private/postgres/src/support/RCS/shmemdoc.c,v 1.3 1992/08/18 17:58:37 mao Exp $");
-
- /* default port for ipc connections (used to generate ipc key) */
- #define DEF_PORT 4321
- #define DEF_NBUFS 64
- #define LBUFSIZ 512
- #define MAXARGS 10
-
- extern int optind, opterr;
- extern char *optarg;
- extern int errno;
-
- typedef struct _Cmd {
- char *cmd_name;
- int cmd_nargs;
- int (*cmd_func)();
- } Cmd;
-
- extern int getsize();
- extern void cmdloop();
- extern void shmemsplit();
- extern int semstat();
- extern int semset();
- extern int quit();
- extern int help();
- extern int setbase();
- extern int whatis();
- extern int shmemstat();
- extern int bufdesc();
- extern int bufdescs();
- extern int buffer();
- extern int linp();
- extern int tuple();
-
- Cmd CmdList[] = {
- "bufdesc", 1, bufdesc,
- "bufdescs", 0, bufdescs,
- "buffer", 3, buffer,
- "help", 0, help,
- "linp", 2, linp,
- "quit", 0, quit,
- "semset", 2, semset,
- "semstat", 0, semstat,
- "setbase", 1, setbase,
- "shmemstat", 0, shmemstat,
- "tuple", 3, tuple,
- "whatis", 1, whatis,
- (char *) NULL, 0, NULL
- };
-
- char *SemNames[] = {
- "shared memory lock",
- "binding lock",
- "buffer manager lock",
- "lock manager lock",
- "shared inval cache lock",
- #ifdef SONY_JUKEBOX
- "sony jukebox cache lock",
- "jukebox spinlock",
- #endif
- #ifdef MAIN_MEMORY
- "main memory cache lock",
- #endif
- "proc struct lock",
- "oid generation lock",
- (char *) NULL
- };
-
- typedef struct LRelId {
- unsigned long relId;
- unsigned long dbId;
- } LRelId;
-
- typedef struct BufferTag {
- LRelId relId;
- unsigned long blockNum;
- } BufferTag;
-
- typedef struct BufferDesc {
- int freeNext;
- int freePrev;
- unsigned int data;
- BufferTag tag;
- int id;
- unsigned short flags;
- short bufsmgr;
- unsigned refcount;
- char sb_dbname[16];
- char sb_relname[16];
- #ifdef HAS_TEST_AND_SET
- slock_t io_in_progress_lock;
- #endif /* HAS_TEST_AND_SET */
- } BufferDesc;
-
- char *Base;
- char *SharedRegion;
- int SemaphoreId;
- int NBuffers;
- char *BindingTable;
- BufferDesc *BufferDescriptors;
- char *BufferBlocks;
- #ifndef HAS_TEST_AND_SET
- int *NWaitIOBackend;
- #endif /* ndef HAS_TEST_AND_SET */
- char *BufHashTable;
- char *LockTableCtl;
- char *LockTableLockHash;
- char *LockTableXIDHash;
- char *SharedRegionEnd;
- char *LastKnownSMAddr;
-
- typedef struct ItemIdData {
- unsigned lp_off:13, /* offset to tuple */
- lp_flags:6, /* itemid flags */
- lp_len:13; /* length of tuple */
- } ItemIdData;
-
- #define LP_USED 0x01 /* this line pointer is being used */
- #define LP_IVALID 0x02 /* this tuple is known to be insert valid */
- #define LP_DOCNT 0x04 /* this tuple continues on another page */
- #define LP_CTUP 0x08 /* this is a continuation tuple */
- #define LP_LOCK 0x10 /* this is a lock */
- #define LP_ISINDEX 0x20 /* this is an internal index tuple */
-
- typedef struct ItemPointerData {
- unsigned short block[2];
- unsigned short offset;
- } ItemPointerData;
-
- typedef struct HeapTupleData {
- unsigned int t_len;
- ItemPointerData t_ctid;
- ItemPointerData t_chain;
- union {
- ItemPointerData l_ltid;
- char *l_lock; /* actually a RuleLock */
- } t_lock;
- unsigned long t_oid;
- unsigned short t_cmin;
- unsigned short t_cmax;
- unsigned long t_xmin;
- unsigned long t_xmax;
- unsigned long t_tmin;
- unsigned long t_tmax;
- unsigned short t_natts;
- char t_vtype;
- char t_infomask;
- char t_locktype;
- char t_bits[1];
- } HeapTupleData;
-
- typedef struct IndexTupleData {
- ItemPointerData t_tid;
-
- #define ITUP_HASNULLS 0x8000
- #define ITUP_HASVARLENA 0x4000
- #define ITUP_HASRULES 0x2000
- #define ITUP_LENMASK 0x1fff
-
- unsigned short t_info;
- } IndexTupleData;
-
- typedef struct BTItemData {
- unsigned long bti_oid;
- IndexTupleData bti_itup;
- } BTItemData;
-
- typedef struct PageHeaderData {
- unsigned short pd_lower;
- unsigned short pd_upper;
- unsigned short pd_special;
- unsigned short pd_opaque;
- ItemIdData pd_linp[1]; /* line pointers start here */
- } PageHeaderData;
-
- typedef struct BTPageOpaqueData {
- unsigned short btpo_prev;
- unsigned short btpo_next;
- unsigned short btpo_flags;
- } BTPageOpaqueData;
-
- typedef struct BTMetaPageData {
- unsigned long btm_magic;
- unsigned long btm_version;
- unsigned long btm_root;
- unsigned long btm_freelist;
- } BTMetaPageData;
-
- typedef struct RTreePageOpaqueData {
- unsigned long rtpo_flags;
-
- #define RTF_LEAF (1 << 0)
-
- } RTreePageOpaqueData;
-
- #define BTP_LEAF (1 << 0)
- #define BTP_ROOT (1 << 1)
- #define BTP_FREE (1 << 2)
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int c;
- int errs;
- int key, spinkey, memkey, shmid;
- char *region;
- int portno;
- int size;
-
- errs = 0;
- portno = DEF_PORT;
- NBuffers = DEF_NBUFS;
- while ((c = getopt(argc, argv, "B:p:")) != EOF) {
- switch (c) {
- case 'B':
- NBuffers = atoi(optarg);
- break;
- case 'p':
- portno = atoi(optarg);
- break;
- default:
- fprintf(stderr, "unknown argument %c\n", c);
- errs++;
- break;
- }
- }
-
- if (errs) {
- fprintf(stderr, "usage: %s [-p port]\n", *argv);
- fflush(stderr);
- exit (1);
- }
-
- /* this has got to be a hirohamaism */
- key = SystemPortAddressGetIPCKey(portno);
- spinkey = IPCKeyGetSpinLockSemaphoreKey(key);
-
- SemaphoreId = semget(spinkey, 0, 0);
- if (SemaphoreId < 0) {
- fprintf(stderr, "%s: cannot attach semaphores (port %d)\n",
- *argv, portno);
- perror("semget");
- fflush(stderr);
- exit (1);
- }
-
- size = getsize();
- memkey = IPCKeyGetBufferMemoryKey(key);
- shmid = shmget(memkey, size, 0);
-
- if (shmid < 0) {
- fprintf(stderr, "%s: cannot identify shared memory by name\n", *argv);
- perror("shmget");
- fflush(stderr);
- exit (1);
- }
-
- Base = SharedRegion = region = (char *) shmat(shmid, 0, 0);
- if (region == (char *) -1) {
- fprintf(stderr, "%s: cannot attach shared memory\n", *argv);
- perror("shmat");
- fflush(stderr);
- exit (1);
- }
- SharedRegionEnd = region + size;
-
- shmemsplit(region);
-
- cmdloop();
-
- exit (0);
- }
-
- int
- getsize()
- {
- /* XXX compute this, someday */
- return(833820);
- }
-
- void
- cmdloop()
- {
- char *l;
- char lbuf[LBUFSIZ];
- char *cmd, *arg[MAXARGS];
- int nargs;
- int cmdno;
- int status;
-
- printf("> ");
- fflush(stdout);
-
- while ((l = fgets(lbuf, LBUFSIZ, stdin)) != (char *) NULL) {
- lbuf[strlen(l) - 1] = '\0';
- while (*l != '\0' && isspace(*l))
- l++;
- cmd = l;
-
- if (*cmd == '\0')
- goto nextcmd;
-
- /* skip command and white space following it */
- while (*l != '\0' && !isspace(*l))
- l++;
- if (*l != '\0') {
- *l++ = '\0';
- while (*l != '\0' && isspace(*l))
- l++;
- }
-
- /* consume one argument */
- for (nargs = 0; nargs < MAXARGS && *l != '\0'; nargs++) {
- arg[nargs] = l;
- while (*l != '\0' && !isspace(*l))
- l++;
- if (*l != '\0') {
- do
- *l++ = '\0';
- while (*l != '\0' && isspace(*l));
- }
- }
-
- for (cmdno = 0; CmdList[cmdno].cmd_name != (char *) NULL; cmdno++)
- if (strcmp(CmdList[cmdno].cmd_name, cmd) == 0)
- break;
-
- if (CmdList[cmdno].cmd_name == (char *) NULL) {
- printf("%s unknown, 'help' for help\n", cmd);
- } else if (CmdList[cmdno].cmd_nargs != nargs) {
- printf("arg count mismatch: expected %d\n",
- CmdList[cmdno].cmd_nargs);
- } else {
- switch (nargs) {
- case 0:
- status = (*(CmdList[cmdno].cmd_func))();
- break;
- case 1:
- status = (*(CmdList[cmdno].cmd_func))(arg[0]);
- break;
- case 2:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1]);
- break;
- case 3:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2]);
- break;
- case 4:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2],
- arg[3]);
- break;
- case 5:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2],
- arg[3],
- arg[4]);
- break;
- case 6:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2],
- arg[3],
- arg[4],
- arg[5]);
- break;
- case 7:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2],
- arg[3],
- arg[4],
- arg[5],
- arg[6]);
- break;
- case 8:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2],
- arg[3],
- arg[4],
- arg[5],
- arg[6],
- arg[7]);
- break;
- case 9:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2],
- arg[3],
- arg[4],
- arg[5],
- arg[6],
- arg[7],
- arg[8]);
- break;
- case 10:
- status = (*(CmdList[cmdno].cmd_func))(arg[0],
- arg[1],
- arg[2],
- arg[3],
- arg[4],
- arg[5],
- arg[6],
- arg[7],
- arg[8],
- arg[9]);
- break;
- default:
- fprintf(stderr, "illegal arg count %d\n", nargs);
- fflush(stderr);
- exit (1);
- }
-
- if (status < 0) {
- return;
- } else if (status > 0) {
- fprintf(stderr, "%s returns %d\n", CmdList[cmdno].cmd_name,
- status);
- fflush(stderr);
- }
- }
-
- nextcmd:
- printf("> ");
- fflush(stdout);
- }
- }
-
- int
- semstat()
- {
- int i;
- int semval, sempid, semncnt, semzcnt;
- union semun ignore;
- ignore.val = 0;
-
- for (i = 0; SemNames[i] != (char *) NULL; i++) {
- if ((semval = semctl(SemaphoreId, i, GETVAL, ignore)) < 0) {
- perror(SemNames[i]);
- return(-errno);
- }
- if ((sempid = semctl(SemaphoreId, i, GETPID, ignore)) < 0) {
- perror(SemNames[i]);
- return(-errno);
- }
- if ((semncnt = semctl(SemaphoreId, i, GETNCNT, ignore)) < 0) {
- perror(SemNames[i]);
- return(-errno);
- }
- if ((semzcnt = semctl(SemaphoreId, i, GETZCNT, ignore)) < 0) {
- perror(SemNames[i]);
- return(-errno);
- }
- printf("%s%*sval %3d, last pid %d, ncnt %d, zcnt %d\n",
- SemNames[i],
- 30 - strlen(SemNames[i]), "",
- semval, sempid, semncnt, semzcnt);
- }
- }
-
- int
- quit()
- {
- return (-1);
- }
-
- int
- help()
- {
- printf("semstat\t\t\tshow status of system semaphores\n");
- printf("semset n val\t\tset semaphore n to val\n");
- printf("\n");
- printf("bufdesc n\t\tprint buffer descriptor n\n");
- printf("bufdescs\t\tprint all buffer descriptors\n");
- printf("buffer n type level\tshow contents of buffer n, which is a page from a\n");
- printf("\t\t\ttype (h,b,r) relation, with level (0,1,2) detail\n");
- printf("linp n which\t\tprint line pointer which of buffer n\n");
- printf("tuple n type which\tprint tuple which of buffer n, which is a page from\n");
- printf("\t\t\ta type (h,b,r) relation\n");
- printf("\n");
- printf("setbase val\t\tuse val as the logical shmem base address\n");
- printf("shmemstat\t\tprint shared memory layout and stats\n");
- printf("whatis ptr\t\twhat shared memory object is ptr?\n");
- printf("\n");
- printf("help\t\t\tprint this command summary\n");
- printf("quit\t\t\texit\n");
-
- return (0);
- }
-
- int
- semset(n, val)
- char *n;
- char *val;
- {
- int semno;
- union semun semval;
-
- semno = atoi(n);
- if (semno < 0 || semno > MAX_SPINS) {
- fprintf(stderr, "sem number out of range: shd be between 0 and %d\n",
- MAX_SPINS);
- return (1);
- }
-
- semval.val = atoi(val);
-
- if (semctl(SemaphoreId, semno, SETVAL, semval) < 0) {
- perror("semset");
- return (1);
- }
-
- return (0);
- }
-
- /* XXX yikes */
- void
- shmemsplit(region)
- char *region;
- {
- BindingTable = region;
- region += (60 + 1024 + 2040);
- region += 16; /* XXX this 16 is mysterious to me */
- BufferDescriptors = (BufferDesc *) region;
- region += 4420;
- BufferBlocks = region;
- region += 524288;
- #ifndef HAS_TEST_AND_SET
- NWaitIOBackend = (int *) region;
- region += 4;
- #endif /* ndef HAS_TEST_AND_SET */
- BufHashTable = region;
- region += (68 + 1024);
- LockTableCtl = region;
- region += 60;
- LockTableLockHash = region;
- region += (72 + 1024);
- LockTableXIDHash = region;
- region += (72 + 1024);
- LastKnownSMAddr = region;
- }
-
- int
- setbase(addr)
- char *addr;
- {
- Base = (char *) strtol(addr, (char *) NULL, 0);
- return (0);
- }
-
- int
- whatis(addr)
- char *addr;
- {
- char *locn;
- char *base;
- int off;
-
- locn = (char *) strtol(addr, (char *) NULL, 0);
- locn = (locn - Base) + SharedRegion;
-
- if (locn >= BindingTable && locn < (char *) BufferDescriptors) {
- if (locn > BindingTable)
- printf("pointer into ");
- printf("binding table\n");
- } else if (locn >= (char *) BufferDescriptors && locn < BufferBlocks) {
- base = (char *) BufferDescriptors;
- off = (locn - base) / sizeof(BufferDesc);
- if ((locn - base) % sizeof(BufferDesc) != 0)
- printf("pointer into ");
- printf("buffer desc %d\n", off);
- } else if (locn >= BufferBlocks
- #ifndef HAS_TEST_AND_SET
- && locn < (char *) NWaitIOBackend) {
- #else
- && locn < BufHashTable) {
- #endif
- base = BufferBlocks;
- off = (locn - base) / 8192;
- if ((locn - base) % 8192 != 0)
- printf("byte %d of ", (locn - base) % 8192);
- printf("buffer %d\n", off);
- #ifndef HAS_TEST_AND_SET
- } else if (locn >= (char *) NWaitIOBackend
- && locn < BufHashTable) {
- if (locn != (char *) NWaitIOBackend)
- printf("pointer into ");
- printf("number of backends waiting for i/o to complete\n");
- #endif
- } else if (locn >= BufHashTable && locn < LockTableCtl) {
- if (locn > BufHashTable)
- printf("pointer into ");
- printf("buffer hash table\n");
- } else if (locn >= LockTableCtl && locn < LockTableLockHash) {
- if (locn > LockTableCtl)
- printf("pointer into ");
- printf("lock table control\n");
- } else if (locn >= LockTableLockHash && locn < LockTableXIDHash) {
- if (locn > LockTableLockHash)
- printf("pointer into ");
- printf("lock table (lock hash)\n");
- } else if (locn >= LockTableXIDHash && locn < LastKnownSMAddr) {
- if (locn > LockTableXIDHash)
- printf("pointer into ");
- printf("lock table (xid hash)\n");
- } else if (locn >= LastKnownSMAddr && locn < SharedRegionEnd) {
- printf("unknown shared memory pointer\n");
- } else
- printf("not a shared memory pointer\n");
-
- return (0);
- }
-
- #define XLATE(p) ((((char *) p) - SharedRegion) + Base)
-
- int
- shmemstat()
- {
- printf("shared region 0x%lx - 0x%lx\n",
- XLATE(SharedRegion), XLATE(SharedRegionEnd));
- printf("binding table 0x%lx\n", XLATE(BindingTable));
- printf("buffer descriptors 0x%lx\n", XLATE(BufferDescriptors));
- printf("buffer blocks 0x%lx\n", XLATE(BufferBlocks));
- #ifndef HAS_TEST_AND_SET
- printf("# backends waiting on i/o 0x%lx\n", XLATE(NWaitIOBackend));
- #endif /* ndef HAS_TEST_AND_SET */
- printf("buffer hash table 0x%lx\n", XLATE(BufHashTable));
- printf("lock table control 0x%lx\n", XLATE(LockTableCtl));
- printf("lock table (lock hash) 0x%lx\n", XLATE(LockTableLockHash));
- printf("lock table (xid hash) 0x%lx\n", XLATE(LockTableXIDHash));
- printf("last known shared mem addr 0x%lx\n", XLATE(LastKnownSMAddr));
-
- return (0);
- }
-
- int
- showbufd(i)
- int i;
- {
- BufferDesc *d;
-
- d = &BufferDescriptors[i];
- printf("[%02d]\tnext %d, prev %d, data 0x%lx, relid %d, dbid %d, blkno %d\n",
- i, d->freeNext, d->freePrev, XLATE(d->data), d->tag.relId.relId,
- d->tag.relId.dbId, d->tag.blockNum);
- printf("\tid %d, flags 0x%x, smgr %d, refcnt %d, db '%.16s', rel '%.16s'\n",
- d->id, d->flags, d->bufsmgr, d->refcount,
- &(d->sb_dbname[0]), &(d->sb_relname[0]));
- #ifdef HAS_TEST_AND_SET
- printf("\tiolock 0xlx\n", d->io_in_progress_lock);
- #endif
- }
-
- bufdescs()
- {
- BufferDesc *d;
- int i;
-
- for (i = 0; i < NBuffers; i++)
- showbufd(i);
-
- return (0);
- }
-
- int
- bufdesc(bno)
- char *bno;
- {
- int i;
-
- i = atoi(bno);
-
- if (i < 0 || i >= NBuffers) {
- fprintf(stderr, "buffer number %d out of range (0 to %d)\n",
- i, NBuffers);
- return (1);
- }
-
- showbufd(i);
-
- return (0);
- }
-
- extern int buffer();
- extern void heappage();
- extern void btreepage();
- extern void rtreepage();
- extern void showlinp();
- extern void showheaptup();
- extern void showindextup();
- extern int PageGetNEntries();
- extern unsigned long ItemPointerGetBlockNumber();
-
- int
- buffer(pgno, type, level)
- char *pgno;
- char *type;
- char *level;
- {
- int p, l;
- int off;
-
- p = atoi(pgno);
- if (p < 0 || p >= NBuffers) {
- fprintf(stderr, "buffer number %d out of range (0 - %d)\n",
- p, NBuffers);
- return (1);
- }
- off = p * 8192;
-
- l = atoi(level);
- if (l < 0) {
- fprintf(stderr, "level %d out of range -- must be non-negative\n", l);
- return (1);
- }
-
- switch (*type) {
- case 'h':
- heappage(BufferDescriptors[p].tag.blockNum,
- &(BufferBlocks[off]), l);
- break;
- case 'b':
- btreepage(BufferDescriptors[p].tag.blockNum,
- &(BufferBlocks[off]), l);
- break;
- case 'r':
- rtreepage(BufferDescriptors[p].tag.blockNum,
- &(BufferBlocks[off]), l);
- break;
- default:
- /* should never happen */
- fprintf(stderr, "type '%s' should be h, r, or b\n", type);
- return (1);
- }
-
- return (0);
- }
-
- void
- heappage(pgno, buf, level)
- int pgno;
- char *buf;
- int level;
- {
- PageHeaderData *phdr;
- ItemIdData *lp;
- int nlinps;
- int i;
- HeapTupleData *htup;
-
- phdr = (PageHeaderData *) buf;
- nlinps = PageGetNEntries(phdr);
- printf("lower: %d upper: %d special: %d opaque 0x%hx (%d items)\n",
- phdr->pd_lower, phdr->pd_upper, phdr->pd_special,
- phdr->pd_opaque, nlinps);
- if (phdr->pd_lower < 8)
- printf(" **** lower too low!\n");
- if (phdr->pd_lower > 8192)
- printf(" **** lower too high!\n");
- if (phdr->pd_upper < 12)
- printf(" **** upper too low!\n");
- if (phdr->pd_upper > 8192)
- printf(" **** upper too high!\n");
- if (phdr->pd_special > 8192)
- printf(" **** special too high!\n");
-
- /* level 0 is page headers only */
- if (level == 0)
- return;
-
- for (i = 0, lp = &(phdr->pd_linp[0]); i < nlinps; lp++, i++) {
- showlinp(i, lp);
- /* level > 1 means show everything */
- if (level > 1) {
- htup = (HeapTupleData *) &(buf[lp->lp_off]);
- showheaptup(htup);
- }
- }
- }
-
- void
- btreepage(pgno, buf, level)
- char *buf;
- int level;
- {
- PageHeaderData *phdr;
- ItemIdData *lp;
- int nlinps;
- int i;
- BTItemData *bti;
- BTPageOpaqueData *btpo;
- BTMetaPageData *meta;
-
- /* if this is the btree metadata page, handle it specially */
- if (pgno == 0) {
- meta = (BTMetaPageData *) buf;
- printf("metapage: magic 0x%06lx version %ld root %ld freelist %ld\n",
- meta->btm_magic, meta->btm_version, meta->btm_root,
- meta->btm_freelist);
- if (meta->btm_magic != 0x053162)
- printf(" **** magic number is bogus!\n");
-
- return;
- }
-
- phdr = (PageHeaderData *) buf;
- nlinps = PageGetNEntries(phdr);
- printf("lower: %d upper: %d special: %d opaque 0x%hx (%d items)\n",
- phdr->pd_lower, phdr->pd_upper, phdr->pd_special,
- phdr->pd_opaque, nlinps);
- btpo = (BTPageOpaqueData *) &(buf[phdr->pd_special]);
- printf("\tprev %d next %d", btpo->btpo_prev, btpo->btpo_next);
- if (btpo->btpo_flags & BTP_LEAF)
- printf(" <leaf>");
- if (btpo->btpo_flags & BTP_ROOT)
- printf(" <root>");
- if (!(btpo->btpo_flags & (BTP_LEAF|BTP_ROOT)))
- printf(" <internal>");
- if (btpo->btpo_flags & BTP_FREE)
- printf(" <free>");
- if (btpo->btpo_next != 0)
- printf(" (item 001 is high key on page)");
- else
- printf(" (no high key)");
- printf("\n");
- if (phdr->pd_lower < 8)
- printf(" **** lower too low!\n");
- if (phdr->pd_lower > 8192)
- printf(" **** lower too high!\n");
- if (phdr->pd_upper < 12)
- printf(" **** upper too low!\n");
- if (phdr->pd_upper > 8192)
- printf(" **** upper too high!\n");
- if (phdr->pd_special > 8192)
- printf(" **** special too high!\n");
-
- /* level 0 is page headers only */
- if (level == 0)
- return;
-
- for (i = 0, lp = &(phdr->pd_linp[0]); i < nlinps; lp++, i++) {
- showlinp(i, lp);
- /* level > 1 means show everything */
- if (level > 1) {
- bti = (BTItemData *) &(buf[lp->lp_off]);
- printf("\t\toid %ld ", bti->bti_oid);
- showindextup(&bti->bti_itup);
- }
- }
- }
-
- void
- rtreepage(pgno, buf, level)
- int pgno;
- char *buf;
- int level;
- {
- PageHeaderData *phdr;
- ItemIdData *lp;
- int nlinps;
- int i;
- RTreePageOpaqueData *rtpo;
- IndexTupleData *itup;
-
- phdr = (PageHeaderData *) buf;
- rtpo = (RTreePageOpaqueData *) &(buf[phdr->pd_special]);
- nlinps = PageGetNEntries(phdr);
- printf("lower: %d upper: %d special: %d opaque 0x%hx %s (%d items)\n",
- phdr->pd_lower, phdr->pd_upper, phdr->pd_special,
- phdr->pd_opaque,
- ((rtpo->rtpo_flags & RTF_LEAF) ? "<leaf>":"internal"), nlinps);
- if (phdr->pd_lower < 8)
- printf(" **** lower too low!\n");
- if (phdr->pd_lower > 8192)
- printf(" **** lower too high!\n");
- if (phdr->pd_upper < 12)
- printf(" **** upper too low!\n");
- if (phdr->pd_upper > 8192)
- printf(" **** upper too high!\n");
- if (phdr->pd_special > 8192)
- printf(" **** special too high!\n");
-
- /* level 0 is page headers only */
- if (level == 0)
- return;
-
- for (i = 0, lp = &(phdr->pd_linp[0]); i < nlinps; lp++, i++) {
- showlinp(i, lp);
- /* level > 1 means show everything */
- if (level > 1) {
- itup = (IndexTupleData *) &(buf[lp->lp_off]);
- showindextup(itup);
- }
- }
- }
-
- void
- showlinp(itemno, lp)
- int itemno;
- ItemIdData *lp;
- {
- int off;
-
- printf(" {%03d} off %d length %d flags [",
- itemno + 1, lp->lp_off, lp->lp_len);
- if (lp->lp_flags & LP_USED)
- printf(" LP_USED");
- if (lp->lp_flags & LP_IVALID)
- printf(" LP_IVALID");
- if (lp->lp_flags & LP_DOCNT)
- printf(" LP_DOCNT");
- if (lp->lp_flags & LP_CTUP)
- printf(" LP_CTUP");
- if (lp->lp_flags & LP_LOCK)
- printf(" LP_LOCK");
- if (lp->lp_flags & LP_ISINDEX)
- printf(" LP_ISINDEX");
- printf(" ]\n");
- if ((off = lp->lp_off) > 8192)
- printf(" **** off too high!\n");
- if (off & 0x3)
- printf(" **** off is bogus -- unaligned tuple pointer!");
- if (lp->lp_len > 8192)
- printf(" **** len too high!\n");
- if (!(lp->lp_flags & LP_USED))
- printf(" **** item not used!\n");
- }
-
- void
- showheaptup(htup)
- HeapTupleData *htup;
- {
- printf("\tlen %d ctid <%d,0,%d> chain <%d,0,%d> oid %ld cmin/max %d/%d\n",
- htup->t_len, ItemPointerGetBlockNumber(htup->t_ctid.block),
- htup->t_ctid.offset, ItemPointerGetBlockNumber(htup->t_chain.block),
- htup->t_chain.offset, htup->t_oid, htup->t_cmin, htup->t_cmax);
- printf("\txmin/max %ld/%ld tmin/max %ld/%ld natts %d\n",
- htup->t_xmin, htup->t_xmax, htup->t_tmin, htup->t_tmax,
- htup->t_natts);
- printf("\tvtype '\\%03o' infomask 0x%x locktype '%c'\n",
- htup->t_vtype, htup->t_infomask, htup->t_locktype);
- }
-
- void
- showindextup(itup)
- IndexTupleData *itup;
- {
- printf("heap tid <%d,0,%d> info [",
- ItemPointerGetBlockNumber(itup->t_tid.block), itup->t_tid.offset);
- if (itup->t_info & ITUP_HASNULLS)
- printf(" HASNULLS");
- if (itup->t_info & ITUP_HASVARLENA)
- printf(" HASVARLENA");
- if (itup->t_info & ITUP_HASRULES)
- printf(" HASRULES");
- printf(" ] length %d\n", itup->t_info & ITUP_LENMASK);
- }
-
- int
- PageGetNEntries(phdr)
- PageHeaderData *phdr;
- {
- int n;
-
- n = (phdr->pd_lower - (2 * sizeof(unsigned long))) / sizeof(ItemIdData);
-
- return (n);
- }
-
- unsigned long
- ItemPointerGetBlockNumber(iptr)
- ItemPointerData *iptr;
- {
- unsigned long b;
-
- b = (unsigned long) ((iptr->block[0] << 16) + iptr->block[1]);
-
- return (b);
- }
-
- int
- linp(pgno, which)
- char *pgno;
- char *which;
- {
- int p, n;
- int off;
- PageHeaderData *phdr;
-
- p = atoi(pgno);
- if (p < 0 || p >= NBuffers) {
- fprintf(stderr, "buffer number %d out of range (0 - %d)\n",
- p, NBuffers);
- return (1);
- }
-
- n = atoi(which);
- if (n < 0) {
- fprintf(stderr, "linp %d out of range -- must be non-negative\n", n);
- return (1);
- }
-
- off = p * 8192;
- phdr = (PageHeaderData *) &(BufferBlocks[off]);
-
- showlinp(n, &(phdr->pd_linp[n]));
-
- return (0);
- }
-
- int
- tuple(pgno, type, which)
- char *pgno;
- char *type;
- char *which;
- {
- int p, n;
- int off;
- PageHeaderData *phdr;
- ItemIdData *lp;
- BTItemData *bti;
- char *buf;
-
- p = atoi(pgno);
- if (p < 0 || p >= NBuffers) {
- fprintf(stderr, "buffer number %d out of range (0 - %d)\n",
- p, NBuffers);
- return (1);
- }
-
- n = atoi(which);
- if (n < 0) {
- fprintf(stderr, "linp %d out of range -- must be non-negative\n", n);
- return (1);
- }
-
- off = p * 8192;
- phdr = (PageHeaderData *) &(BufferBlocks[off]);
- buf = (char *) phdr;
- lp = &(phdr->pd_linp[n]);
-
- switch (*type) {
- case 'r':
- showindextup((IndexTupleData *) &(buf[lp->lp_off]));
- break;
-
- case 'b':
- bti = (BTItemData *) &(buf[lp->lp_off]);
- showindextup(&bti->bti_itup);
- break;
-
- case 'h':
- showheaptup((HeapTupleData *) &(buf[lp->lp_off]));
- break;
-
- default:
- fprintf(stderr, "type %s unknown -- try h, r, or b\n", type);
- fflush(stderr);
- return (1);
- }
-
- return (0);
- }
-