/* * SIMPLE Buffer Tester * */ #include "postgres.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" int NBuffers = 4; #undef INIT_BUFFERTAG #define INIT_BUFFERTAG(a,r,b) \ ( \ (a).rnode.spcNode = (a).rnode.dbNode = 0, \ (a).rnode.relNode = (r), \ (a).blockNum = (b) \ ) void printBuffers() { int i; BufferDesc *buf; char *block; buf = BufferDescriptors; for (i=0; irefcount == 0) printf("[%1s]",((char *) MAKE_PTR(buf->data))); else printf("(%1s)",((char *) MAKE_PTR(buf->data))); } printf("\n"); } BufferDesc* findPage(BufferTag *btag, int *cdb_found_index) { BufferDesc *buf; buf = StrategyBufferLookup(btag, false, cdb_found_index); return buf; } void writePage(char pg, BufferDesc *buf) { *((char *) MAKE_PTR(buf->data)) = pg; } BufferDesc * getPage(Oid rel, int bno) { BufferTag btag; BufferDesc *buf; int cdb_replace_index; int cdb_found_index; INIT_BUFFERTAG(btag, rel, bno); // Find page if in memory buf = findPage(&btag, &cdb_found_index); if (buf == NULL) { // Get a free page buf = StrategyGetBuffer(&cdb_replace_index); if (buf == NULL) { printf("Out of buffers!\n"); exit(0); } else if (buf->refcount > 0) { printf("Pinned buffer!\n"); exit(0); } buf->refcount = 1; PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 1; } else { buf->refcount++; PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1]++; return buf; } StrategyReplaceBuffer(buf, &btag, cdb_found_index, cdb_replace_index); buf->tag = btag; return buf; } void unpinPage(Oid rel, int bno) { BufferTag btag; int cdb_found_index; BufferDesc *buf; INIT_BUFFERTAG(btag, rel, bno); buf = findPage(&btag, &cdb_found_index); if (buf == NULL) printf("Page not in memory!\n"); else { buf->refcount--; if (buf->refcount == 0) buf->reference = true; PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1]--; } } #define GET_WRITE(r, b, v) GET_WRITE_PIN(r, b, v, false) #define GET_WRITE_PIN(r, b, v, p) \ do { \ BufferDesc *bdesc; \ bdesc = getPage((r), (b)); \ writePage((v), bdesc); \ if (!(p)) unpinPage((r), (b)); \ } while (0) void usage() { printf("BUFTEST++: USAGE\n"); printf("buftest \n\n"); printf("===== COMMAND FILE FORMAT =====\n"); printf("cmd, arg1 [, arg2 [, arg3]]\n"); printf("cmd IN {w : write, r : read and compare, i : invalidate}\n"); printf("WRITE => w, page, value\n"); printf("READ and COMPARE => r, buffer_frame, compare_value\n"); printf("INVALIDATE => i, buffer_frame\n"); exit(0); } int main(int argc, char *argv[]) { FILE *pattern = NULL; char cbuf[21]; int page, frm; char cmd, val; if (argc != 2) usage(); printf("Initializing buffer pool with %d pages\n", NBuffers); InitBufferPool(); printf("Beginning tests in file %s...\n", argv[1]); pattern = fopen(argv[1], "r"); while (fgets(cbuf, 20, pattern) != NULL) { BufferDesc *buf = NULL; switch(cbuf[0]) { case 'w': sscanf(cbuf, "%c, %d, %c\n", &cmd, &page, &val); GET_WRITE(0, page, val); printBuffers(); break; case 'r': { sscanf(cbuf, "%c, %d, %c\n", &cmd, &frm, &val); buf = &BufferDescriptors[frm]; if (*((char*) MAKE_PTR(buf->data)) != val) { printf("PAGE MISMATCH! %c != ", val); printf("[%1s]\n",((char *) MAKE_PTR(buf->data))); } break; } case 'i': { sscanf(cbuf, "%c, %d\n", &cmd, &frm); buf = &BufferDescriptors[frm]; StrategyInvalidateBuffer(buf); break; } } } printf("Finished.\n"); return 0; }