Пример #1
0
/*
 * TransactionLogFetch --- fetch commit status of specified transaction id
 */
static XidStatus
TransactionLogFetch(TransactionId transactionId)
{
	XidStatus	xidstatus;

	/*
	 * Before going to the commit log manager, check our single item cache to
	 * see if we didn't just check the transaction status a moment ago.
	 */
	if (TransactionIdEquals(transactionId, cachedFetchXid))
		return cachedFetchXidStatus;

	/*
	 * Also, check to see if the transaction ID is a permanent one.
	 */
	if (!TransactionIdIsNormal(transactionId))
	{
		if (TransactionIdEquals(transactionId, BootstrapTransactionId))
			return TRANSACTION_STATUS_COMMITTED;
		if (TransactionIdEquals(transactionId, FrozenTransactionId))
			return TRANSACTION_STATUS_COMMITTED;
		return TRANSACTION_STATUS_ABORTED;
	}

	/*
	 * Get the transaction status.
	 */
	xidstatus = TransactionIdGetStatus(transactionId);

	/*
	 * Cache it, but DO NOT cache status for unfinished or sub-committed
	 * transactions!  We only cache status that is guaranteed not to change.
	 */
	if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
		xidstatus != TRANSACTION_STATUS_SUB_COMMITTED)
	{
		TransactionIdStore(transactionId, &cachedFetchXid);
		cachedFetchXidStatus = xidstatus;
	}

	return xidstatus;
}
Пример #2
0
/*
 * ProcSleep -- put a process to sleep
 *
 * P() on the semaphore should put us to sleep.  The process
 * semaphore is cleared by default, so the first time we try
 * to acquire it, we sleep.
 *
 * ASSUME: that no one will fiddle with the queue until after
 * 	we release the spin lock.
 *
 * NOTES: The process queue is now a priority queue for locking.
 */
int
ProcSleep(PROC_QUEUE *queue,
	  SPINLOCK spinlock,
	  int token,
	  int prio,
	  LOCK *lock)
{
    int 	i;
    PROC	*proc;
#ifndef WIN32 /* figure this out later */
    struct itimerval timeval, dummy;
#endif /* WIN32 */
    
    proc = (PROC *) MAKE_PTR(queue->links.prev);
    for (i=0;i<queue->size;i++)
	{
	    if (proc->prio < prio)
		proc = (PROC *) MAKE_PTR(proc->links.prev);
	    else
		break;
	}
    
    MyProc->token = token;
    MyProc->waitLock = lock;
    
    /* -------------------
     * currently, we only need this for the ProcWakeup routines
     * -------------------
     */
    TransactionIdStore((TransactionId) GetCurrentTransactionId(), &MyProc->xid);
    
    /* -------------------
     * assume that these two operations are atomic (because
     * of the spinlock).
     * -------------------
     */
    SHMQueueInsertTL(&(proc->links),&(MyProc->links));
    queue->size++;
    
    SpinRelease(spinlock);
    
    /* --------------
     * Postgres does not have any deadlock detection code and for this 
     * reason we must set a timer to wake up the process in the event of
     * a deadlock.  For now the timer is set for 1 minute and we assume that
     * any process which sleeps for this amount of time is deadlocked and will 
     * receive a SIGALRM signal.  The handler should release the processes
     * semaphore and abort the current transaction.
     *
     * Need to zero out struct to set the interval and the micro seconds fields
     * to 0.
     * --------------
     */
#ifndef WIN32
    memset(&timeval, 0, sizeof(struct itimerval));
    timeval.it_value.tv_sec = DEADLOCK_TIMEOUT;
    
    if (setitimer(ITIMER_REAL, &timeval, &dummy))
	elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
#endif /* WIN32 */
    
    /* --------------
     * if someone wakes us between SpinRelease and IpcSemaphoreLock,
     * IpcSemaphoreLock will not block.  The wakeup is "saved" by
     * the semaphore implementation.
     * --------------
     */
    IpcSemaphoreLock(MyProc->sem.semId, MyProc->sem.semNum, IpcExclusiveLock);
    
    /* ---------------
     * We were awoken before a timeout - now disable the timer
     * ---------------
     */
#ifndef WIN32
    timeval.it_value.tv_sec = 0;
    
    
    if (setitimer(ITIMER_REAL, &timeval, &dummy))
	elog(FATAL, "ProcSleep: Unable to diable timer for process wakeup");
#endif /* WIN32 */
    
    /* ----------------
     * We were assumed to be in a critical section when we went
     * to sleep.
     * ----------------
     */
    SpinAcquire(spinlock);
    
    return(MyProc->errType);
}