📄 transsup.c
字号:
/*------------------------------------------------------------------------- * * transsup.c * postgres transaction access method support code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/access/transam/transsup.c,v 1.21.2.2 1999/08/02 05:56:46 scrappy Exp $ * * NOTES * This file contains support functions for the high * level access method interface routines found in transam.c * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/xact.h"#include "utils/bit.h"static XidStatus TransBlockGetXidStatus(Block tblock, TransactionId transactionId);static void TransBlockSetXidStatus(Block tblock, TransactionId transactionId, XidStatus xstatus);/* ---------------------------------------------------------------- * general support routines * ---------------------------------------------------------------- *//* -------------------------------- * AmiTransactionOverride * * This function is used to manipulate the bootstrap flag. * -------------------------------- */voidAmiTransactionOverride(bool flag){ AMI_OVERRIDE = flag;}/* -------------------------------- * TransComputeBlockNumber * -------------------------------- */voidTransComputeBlockNumber(Relation relation, /* relation to test */ TransactionId transactionId, /* transaction id to * test */ BlockNumber *blockNumberOutP){ long itemsPerBlock = 0; /* ---------------- * we calculate the block number of our transaction * by dividing the transaction id by the number of * transaction things per block. * ---------------- */ if (relation == LogRelation) itemsPerBlock = TP_NumXidStatusPerBlock; else elog(ERROR, "TransComputeBlockNumber: unknown relation"); /* ---------------- * warning! if the transaction id's get too large * then a BlockNumber may not be large enough to hold the results * of our division. * * XXX this will all vanish soon when we implement an improved * transaction id schema -cim 3/23/90 * * This has vanished now that xid's are 4 bytes (no longer 5). * -mer 5/24/92 * ---------------- */ (*blockNumberOutP) = transactionId / itemsPerBlock;}/* ---------------------------------------------------------------- * trans block support routines * ---------------------------------------------------------------- *//* -------------------------------- * TransBlockGetLastTransactionIdStatus * * This returns the status and transaction id of the last * transaction information recorded on the given TransBlock. * -------------------------------- */#ifdef NOT_USEDstatic XidStatusTransBlockGetLastTransactionIdStatus(Block tblock, TransactionId baseXid, TransactionId *returnXidP){ Index index; Index maxIndex; bits8 bit1; bits8 bit2; BitIndex offset; XidStatus xstatus; /* ---------------- * sanity check * ---------------- */ Assert((tblock != NULL)); /* ---------------- * search downward from the top of the block data, looking * for the first Non-in progress transaction status. Since we * are scanning backward, this will be last recorded transaction * status on the block. * ---------------- */ maxIndex = TP_NumXidStatusPerBlock; for (index = maxIndex; index > 0; index--) { offset = BitIndexOf(index - 1); bit1 = ((bits8) BitArrayBitIsSet((BitArray) tblock, offset++)) << 1; bit2 = (bits8) BitArrayBitIsSet((BitArray) tblock, offset); xstatus = (bit1 | bit2); /* ---------------- * here we have the status of some transaction, so test * if the status is recorded as "in progress". If so, then * we save the transaction id in the place specified by the caller. * ---------------- */ if (xstatus != XID_INPROGRESS) { if (returnXidP != NULL) { TransactionIdStore(baseXid, returnXidP); TransactionIdAdd(returnXidP, index - 1); } break; } } /* ---------------- * if we get here and index is 0 it means we couldn't find * a non-inprogress transaction on the block. For now we just * return this info to the user. They can check if the return * status is "in progress" to know this condition has arisen. * ---------------- */ if (index == 0) { if (returnXidP != NULL) TransactionIdStore(baseXid, returnXidP); } /* ---------------- * return the status to the user * ---------------- */ return xstatus;}#endif/* -------------------------------- * TransBlockGetXidStatus * * This returns the status of the desired transaction * -------------------------------- */static XidStatusTransBlockGetXidStatus(Block tblock, TransactionId transactionId){ Index index; bits8 bit1; bits8 bit2; BitIndex offset; /* ---------------- * calculate the index into the transaction data where * our transaction status is located * * XXX this will be replaced soon when we move to the * new transaction id scheme -cim 3/23/90 * * The old system has now been replaced. -mer 5/24/92 * ---------------- */ index = transactionId % TP_NumXidStatusPerBlock; /* ---------------- * get the data at the specified index * ---------------- */ offset = BitIndexOf(index); bit1 = ((bits8) BitArrayBitIsSet((BitArray) tblock, offset++)) << 1; bit2 = (bits8) BitArrayBitIsSet((BitArray) tblock, offset); /* ---------------- * return the transaction status to the caller * ---------------- */ return (XidStatus) (bit1 | bit2);}/* -------------------------------- * TransBlockSetXidStatus * * This sets the status of the desired transaction * -------------------------------- */static voidTransBlockSetXidStatus(Block tblock, TransactionId transactionId, XidStatus xstatus){ Index index; BitIndex offset; /* ---------------- * calculate the index into the transaction data where * we sould store our transaction status. * * XXX this will be replaced soon when we move to the * new transaction id scheme -cim 3/23/90 * * The new scheme is here -mer 5/24/92 * ---------------- */ index = transactionId % TP_NumXidStatusPerBlock; offset = BitIndexOf(index); /* ---------------- * store the transaction value at the specified offset * ---------------- */ switch (xstatus) { case XID_COMMIT: /* set 10 */ BitArraySetBit((BitArray) tblock, offset); BitArrayClearBit((BitArray) tblock, offset + 1); break; case XID_ABORT: /* set 01 */ BitArrayClearBit((BitArray) tblock, offset); BitArraySetBit((BitArray) tblock, offset + 1); break; case XID_INPROGRESS: /* set 00 */ BitArrayClearBit((BitArray) tblock, offset); BitArrayClearBit((BitArray) tblock, offset + 1); break; default: elog(NOTICE, "TransBlockSetXidStatus: invalid status: %d (ignored)", xstatus); break; }}/* ---------------------------------------------------------------- * transam i/o support routines * ---------------------------------------------------------------- *//* -------------------------------- * TransBlockNumberGetXidStatus * -------------------------------- */XidStatusTransBlockNumberGetXidStatus(Relation relation, BlockNumber blockNumber, TransactionId xid, bool *failP){ Buffer buffer; /* buffer associated with block */ Block block; /* block containing xstatus */ XidStatus xstatus; /* recorded status of xid */ bool localfail; /* bool used if failP = NULL */ /* ---------------- * get the page containing the transaction information * ---------------- */ buffer = ReadBuffer(relation, blockNumber); LockBuffer(buffer, BUFFER_LOCK_SHARE); block = BufferGetBlock(buffer); /* ---------------- * get the status from the block. note, for now we always * return false in failP. * ---------------- */ if (failP == NULL) failP = &localfail; (*failP) = false; xstatus = TransBlockGetXidStatus(block, xid); /* ---------------- * release the buffer and return the status * ---------------- */ LockBuffer(buffer, BUFFER_LOCK_UNLOCK); ReleaseBuffer(buffer); return xstatus;}/* -------------------------------- * TransBlockNumberSetXidStatus * -------------------------------- */voidTransBlockNumberSetXidStatus(Relation relation, BlockNumber blockNumber, TransactionId xid, XidStatus xstatus, bool *failP){ Buffer buffer; /* buffer associated with block */ Block block; /* block containing xstatus */ bool localfail; /* bool used if failP = NULL */ /* ---------------- * get the block containing the transaction status * ---------------- */ buffer = ReadBuffer(relation, blockNumber); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); block = BufferGetBlock(buffer); /* ---------------- * attempt to update the status of the transaction on the block. * if we are successful, write the block. otherwise release the buffer. * note, for now we always return false in failP. * ---------------- */ if (failP == NULL) failP = &localfail; (*failP) = false; TransBlockSetXidStatus(block, xid, xstatus); LockBuffer(buffer, BUFFER_LOCK_UNLOCK); if ((*failP) == false) WriteBuffer(buffer); else ReleaseBuffer(buffer);}/* -------------------------------- * TransGetLastRecordedTransaction * -------------------------------- */#ifdef NOT_USEDvoidTransGetLastRecordedTransaction(Relation relation, TransactionId xid, /* return: transaction * id */ bool *failP){ BlockNumber blockNumber; /* block number */ Buffer buffer; /* buffer associated with block */ Block block; /* block containing xid status */ BlockNumber n; /* number of blocks in the relation */ TransactionId baseXid; (*failP) = false; /* ---------------- * SOMEDAY gain exclusive access to the log relation * * That someday is today 5 Aug. 1991 -mer * It looks to me like we only need to set a read lock here, despite * the above comment about exclusive access. The block is never * actually written into, we only check status bits. * ---------------- */ RelationSetLockForRead(relation); /* ---------------- * we assume the last block of the log contains the last * recorded transaction. If the relation is empty we return * failure to the user. * ---------------- */ n = RelationGetNumberOfBlocks(relation); if (n == 0) { (*failP) = true; return; } /* ---------------- * get the block containing the transaction information * ---------------- */ blockNumber = n - 1; buffer = ReadBuffer(relation, blockNumber); block = BufferGetBlock(buffer); /* ---------------- * get the last xid on the block * ---------------- */ baseXid = blockNumber * TP_NumXidStatusPerBlock;/* XXX ???? xid won't get returned! - AY '94 */ TransBlockGetLastTransactionIdStatus(block, baseXid, &xid); ReleaseBuffer(buffer); /* ---------------- * SOMEDAY release our lock on the log relation * ---------------- */ RelationUnsetLockForRead(relation);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -