home *** CD-ROM | disk | FTP | other *** search
- /*
- * mm.c -- main memory storage manager
- *
- * This code manages relations that reside in (presumably stable)
- * main memory.
- */
-
- #include "tmp/c.h"
- #include "tmp/postgres.h"
-
- #ifdef MAIN_MEMORY
-
- #include <math.h>
- #include "machine.h"
- #include "storage/ipc.h"
- #include "storage/ipci.h"
- #include "storage/smgr.h"
- #include "storage/block.h"
- #include "storage/shmem.h"
- #include "storage/spin.h"
-
- #include "utils/hsearch.h"
- #include "utils/rel.h"
- #include "utils/log.h"
-
- RcsId("$Header: /private/postgres/src/storage/smgr/RCS/mm.c,v 1.8 1992/02/24 13:30:22 mao Exp $");
-
- /*
- * MMCacheTag -- Unique triplet for blocks stored by the main memory
- * storage manager.
- */
-
- typedef struct MMCacheTag {
- ObjectId mmct_dbid;
- ObjectId mmct_relid;
- BlockNumber mmct_blkno;
- } MMCacheTag;
-
- /*
- * Shared-memory hash table for main memory relations contains
- * entries of this form.
- */
-
- typedef struct MMHashEntry {
- MMCacheTag mmhe_tag;
- int mmhe_bufno;
- } MMHashEntry;
-
- /*
- * MMRelTag -- Unique identifier for each relation that is stored in the
- * main-memory storage manager.
- */
-
- typedef struct MMRelTag {
- ObjectId mmrt_dbid;
- ObjectId mmrt_relid;
- } MMRelTag;
-
- /*
- * Shared-memory hash table for # blocks in main memory relations contains
- * entries of this form.
- */
-
- typedef struct MMRelHashEntry {
- MMRelTag mmrhe_tag;
- int mmrhe_nblocks;
- } MMRelHashEntry;
-
- #define MMNBUFFERS 10
- #define MMNRELATIONS 2
-
- SPINLOCK MMCacheLock;
- extern bool IsPostmaster;
- extern ObjectId MyDatabaseId;
-
- static int *MMCurTop;
- static int *MMCurRelno;
- static MMCacheTag *MMBlockTags;
- static char *MMBlockCache;
- static HTAB *MMCacheHT;
- static HTAB *MMRelCacheHT;
-
- int
- mminit()
- {
- char *mmcacheblk;
- int mmsize;
- bool found;
- HASHCTL info;
-
- SpinAcquire(MMCacheLock);
-
- mmsize = (BLCKSZ * MMNBUFFERS) + sizeof(*MMCurTop) + sizeof(*MMCurRelno);
- mmsize += (MMNBUFFERS * sizeof(MMCacheTag));
- mmcacheblk = (char *) ShmemInitStruct("Main memory smgr", mmsize, &found);
-
- if (mmcacheblk == (char *) NULL) {
- SpinRelease(MMCacheLock);
- return (SM_FAIL);
- }
-
- info.keysize = sizeof(MMCacheTag);
- info.datasize = sizeof(int);
- info.hash = tag_hash;
-
- MMCacheHT = (HTAB *) ShmemInitHash("Main memory store HT",
- MMNBUFFERS, MMNBUFFERS,
- &info, (HASH_ELEM|HASH_FUNCTION));
-
- if (MMCacheHT == (HTAB *) NULL) {
- SpinRelease(MMCacheLock);
- return (SM_FAIL);
- }
-
- info.keysize = sizeof(MMRelTag);
- info.datasize = sizeof(int);
- info.hash = tag_hash;
-
- MMRelCacheHT = (HTAB *) ShmemInitHash("Main memory rel HT",
- MMNRELATIONS, MMNRELATIONS,
- &info, (HASH_ELEM|HASH_FUNCTION));
-
- if (MMRelCacheHT == (HTAB *) NULL) {
- SpinRelease(MMCacheLock);
- return (SM_FAIL);
- }
-
- if (IsPostmaster) {
- bzero(mmcacheblk, mmsize);
- SpinRelease(MMCacheLock);
- return (SM_SUCCESS);
- }
-
- SpinRelease(MMCacheLock);
-
- MMCurTop = (int *) mmcacheblk;
- mmcacheblk += sizeof(int);
- MMCurRelno = (int *) mmcacheblk;
- mmcacheblk += sizeof(int);
- MMBlockTags = (MMCacheTag *) mmcacheblk;
- mmcacheblk += (MMNBUFFERS * sizeof(MMCacheTag));
- MMBlockCache = mmcacheblk;
-
- return (SM_SUCCESS);
- }
-
- int
- mmshutdown()
- {
- return (SM_SUCCESS);
- }
-
- int
- mmcreate(reln)
- Relation reln;
- {
- MMRelHashEntry *entry;
- bool found;
- MMRelTag tag;
-
- SpinAcquire(MMCacheLock);
-
- if (*MMCurRelno == MMNRELATIONS) {
- SpinRelease(MMCacheLock);
- return (SM_FAIL);
- }
-
- (*MMCurRelno)++;
-
- tag.mmrt_relid = reln->rd_id;
- if (reln->rd_rel->relisshared)
- tag.mmrt_dbid = (ObjectId) 0;
- else
- tag.mmrt_dbid = MyDatabaseId;
-
- entry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
- (char *) &tag, HASH_ENTER, &found);
-
- if (entry == (MMRelHashEntry *) NULL) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "main memory storage mgr rel cache hash table corrupt");
- }
-
- if (found) {
- /* already exists */
- SpinRelease(MMCacheLock);
- return (SM_FAIL);
- }
-
- entry->mmrhe_nblocks = 0;
-
- SpinRelease(MMCacheLock);
-
- return (SM_SUCCESS);
- }
-
- /*
- * mmunlink() -- Unlink a relation.
- */
-
- int
- mmunlink(reln)
- Relation reln;
- {
- int i;
- ObjectId reldbid;
- MMHashEntry *entry;
- MMRelHashEntry *rentry;
- bool found;
- MMRelTag rtag;
-
- if (reln->rd_rel->relisshared)
- reldbid = (ObjectId) 0;
- else
- reldbid = MyDatabaseId;
-
- SpinAcquire(MMCacheLock);
-
- for (i = 0; i < MMNBUFFERS; i++) {
- if (MMBlockTags[i].mmct_dbid == reldbid
- && MMBlockTags[i].mmct_relid == reln->rd_id) {
- entry = (MMHashEntry *) hash_search(MMCacheHT,
- (char *) &MMBlockTags[i],
- HASH_REMOVE, &found);
- if (entry == (MMHashEntry *) NULL || !found) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmunlink: cache hash table corrupted");
- }
- MMBlockTags[i].mmct_dbid = (ObjectId) 0;
- MMBlockTags[i].mmct_relid = (ObjectId) 0;
- MMBlockTags[i].mmct_blkno = (BlockNumber) 0;
- }
- }
- rtag.mmrt_dbid = reldbid;
- rtag.mmrt_relid = reln->rd_id;
-
- rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
- HASH_REMOVE, &found);
-
- if (rentry == (MMRelHashEntry *) NULL || !found) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmunlink: rel cache hash table corrupted");
- }
-
- (*MMCurRelno)--;
-
- SpinRelease(MMCacheLock);
- }
-
- /*
- * mmextend() -- Add a block to the specified relation.
- *
- * This routine returns SM_FAIL or SM_SUCCESS, with errno set as
- * appropriate.
- */
-
- int
- mmextend(reln, buffer)
- Relation reln;
- char *buffer;
- {
- MMRelHashEntry *rentry;
- MMHashEntry *entry;
- int i;
- ObjectId reldbid;
- int offset;
- bool found;
- MMRelTag rtag;
- MMCacheTag tag;
-
- if (reln->rd_rel->relisshared)
- reldbid = (ObjectId) 0;
- else
- reldbid = MyDatabaseId;
-
- tag.mmct_dbid = rtag.mmrt_dbid = reldbid;
- tag.mmct_relid = rtag.mmrt_relid = reln->rd_id;
-
- SpinAcquire(MMCacheLock);
-
- if (*MMCurTop == MMNBUFFERS) {
- for (i = 0; i < MMNBUFFERS; i++) {
- if (MMBlockTags[i].mmct_dbid == 0 && MMBlockTags[i].mmct_relid == 0)
- break;
- }
- if (i == MMNBUFFERS) {
- SpinRelease(MMCacheLock);
- return (SM_FAIL);
- }
- } else {
- i = *MMCurTop;
- (*MMCurTop)++;
- }
-
- rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
- HASH_FIND, &found);
- if (rentry == (MMRelHashEntry *) NULL || !found) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmextend: rel cache hash table corrupt");
- }
-
- tag.mmct_blkno = rentry->mmrhe_nblocks;
-
- entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
- HASH_ENTER, &found);
- if (entry == (MMHashEntry *) NULL || found) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmextend: cache hash table corrupt");
- }
-
- entry->mmhe_bufno = i;
- MMBlockTags[i].mmct_dbid = reldbid;
- MMBlockTags[i].mmct_relid = reln->rd_id;
- MMBlockTags[i].mmct_blkno = rentry->mmrhe_nblocks;
-
- /* page numbers are zero-based, so we increment this at the end */
- (rentry->mmrhe_nblocks)++;
-
- /* write the extended page */
- offset = (i * BLCKSZ);
- bcopy(buffer, &(MMBlockCache[offset]), BLCKSZ);
-
- SpinRelease(MMCacheLock);
-
- return (SM_SUCCESS);
- }
-
- /*
- * mmopen() -- Open the specified relation.
- */
-
- int
- mmopen(reln)
- Relation reln;
- {
- /* automatically successful */
- return (0);
- }
-
- /*
- * mmclose() -- Close the specified relation.
- *
- * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
- */
-
- int
- mmclose(reln)
- Relation reln;
- {
- /* automatically successful */
- return (SM_SUCCESS);
- }
-
- /*
- * mmread() -- Read the specified block from a relation.
- *
- * Returns SM_SUCCESS or SM_FAIL.
- */
-
- int
- mmread(reln, blocknum, buffer)
- Relation reln;
- BlockNumber blocknum;
- char *buffer;
- {
- MMHashEntry *entry;
- bool found;
- int offset;
- MMCacheTag tag;
-
- if (reln->rd_rel->relisshared)
- tag.mmct_dbid = (ObjectId) 0;
- else
- tag.mmct_dbid = MyDatabaseId;
-
- tag.mmct_relid = reln->rd_id;
- tag.mmct_blkno = blocknum;
-
- SpinAcquire(MMCacheLock);
- entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
- HASH_FIND, &found);
-
- if (entry == (MMHashEntry *) NULL) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmread: hash table corrupt");
- }
-
- if (!found) {
- /* reading nonexistent pages is defined to fill them with zeroes */
- SpinRelease(MMCacheLock);
- bzero(buffer, BLCKSZ);
- return (SM_SUCCESS);
- }
-
- offset = (entry->mmhe_bufno * BLCKSZ);
- bcopy(&MMBlockCache[offset], buffer, BLCKSZ);
-
- SpinRelease(MMCacheLock);
-
- return (SM_SUCCESS);
- }
-
- /*
- * mmwrite() -- Write the supplied block at the appropriate location.
- *
- * Returns SM_SUCCESS or SM_FAIL.
- */
-
- int
- mmwrite(reln, blocknum, buffer)
- Relation reln;
- BlockNumber blocknum;
- char *buffer;
- {
- MMHashEntry *entry;
- bool found;
- int offset;
- MMCacheTag tag;
-
- if (reln->rd_rel->relisshared)
- tag.mmct_dbid = (ObjectId) 0;
- else
- tag.mmct_dbid = MyDatabaseId;
-
- tag.mmct_relid = reln->rd_id;
- tag.mmct_blkno = blocknum;
-
- SpinAcquire(MMCacheLock);
- entry = (MMHashEntry *) hash_search(MMCacheHT, (char *) &tag,
- HASH_FIND, &found);
-
- if (entry == (MMHashEntry *) NULL) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmread: hash table corrupt");
- }
-
- if (!found) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmwrite: hash table missing requested page");
- }
-
- offset = (entry->mmhe_bufno * BLCKSZ);
- bcopy(buffer, &MMBlockCache[offset], BLCKSZ);
-
- SpinRelease(MMCacheLock);
-
- return (SM_SUCCESS);
- }
-
- /*
- * mmflush() -- Synchronously write a block to stable storage.
- *
- * For main-memory relations, this is exactly equivalent to mmwrite().
- */
-
- int
- mmflush(reln, blocknum, buffer)
- Relation reln;
- BlockNumber blocknum;
- char *buffer;
- {
- return (mmwrite(reln, blocknum, buffer));
- }
-
- /*
- * mmblindwrt() -- Write a block to stable storage blind.
- *
- * We have to be able to do this using only the name and OID of
- * the database and relation in which the block belongs.
- */
-
- int
- mmblindwrt(dbstr, relstr, dbid, relid, blkno, buffer)
- char *dbstr;
- char *relstr;
- OID dbid;
- OID relid;
- BlockNumber blkno;
- char *buffer;
- {
- return (SM_FAIL);
- }
-
- /*
- * mmnblocks() -- Get the number of blocks stored in a relation.
- *
- * Returns # of blocks or -1 on error.
- */
-
- int
- mmnblocks(reln)
- Relation reln;
- {
- MMRelTag rtag;
- MMRelHashEntry *rentry;
- bool found;
- int nblocks;
-
- if (reln->rd_rel->relisshared)
- rtag.mmrt_dbid = (ObjectId) 0;
- else
- rtag.mmrt_dbid = MyDatabaseId;
-
- rtag.mmrt_relid = reln->rd_id;
-
- SpinAcquire(MMCacheLock);
-
- rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT, (char *) &rtag,
- HASH_FIND, &found);
-
- if (rentry == (MMRelHashEntry *) NULL) {
- SpinRelease(MMCacheLock);
- elog(FATAL, "mmnblocks: rel cache hash table corrupt");
- }
-
- if (found)
- nblocks = rentry->mmrhe_nblocks;
- else
- nblocks = -1;
-
- SpinRelease(MMCacheLock);
-
- return (nblocks);
- }
-
- /*
- * mmcommit() -- Commit a transaction.
- *
- * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
- */
-
- int
- mmcommit()
- {
- return (SM_SUCCESS);
- }
-
- /*
- * mmabort() -- Abort a transaction.
- */
-
- int
- mmabort()
- {
- return (SM_SUCCESS);
- }
-
- /*
- * MMShmemSize() -- Declare amount of shared memory we require.
- *
- * The shared memory initialization code creates a block of shared
- * memory exactly big enough to hold all the structures it needs to.
- * This routine declares how much space the main memory storage
- * manager will use.
- */
-
- int
- MMShmemSize()
- {
- int size;
- int nbuckets;
- int nsegs;
- int tmp;
-
- /*
- * first compute space occupied by the (dbid,relid,blkno) hash table
- */
-
- nbuckets = 1 << (int)my_log2((MMNBUFFERS - 1) / DEF_FFACTOR + 1);
- nsegs = 1 << (int)my_log2((nbuckets - 1) / DEF_SEGSIZE + 1);
-
- size = my_log2(MMNBUFFERS) + sizeof(HHDR);
- size += nsegs * DEF_SEGSIZE * sizeof(SEGMENT);
- tmp = (int)ceil((double)MMNBUFFERS/BUCKET_ALLOC_INCR);
- size += tmp * BUCKET_ALLOC_INCR *
- (sizeof(BUCKET_INDEX) + sizeof(MMHashEntry));
-
- /*
- * now do the same for the rel hash table
- */
-
- size += my_log2(MMNRELATIONS) + sizeof(HHDR);
- size += nsegs * DEF_SEGSIZE * sizeof(SEGMENT);
- tmp = (int)ceil((double)MMNRELATIONS/BUCKET_ALLOC_INCR);
- size += tmp * BUCKET_ALLOC_INCR *
- (sizeof(BUCKET_INDEX) + sizeof(MMRelHashEntry));
-
- /*
- * finally, add in the memory block we use directly
- */
-
- size += (BLCKSZ * MMNBUFFERS) + sizeof(*MMCurTop) + sizeof(*MMCurRelno);
- size += (MMNBUFFERS * sizeof(MMCacheTag));
-
- return (size);
- }
-
- #endif /* MAIN_MEMORY */
-