/* File:  plsync.c    Wed Jul  6 16:49:47 PDT 1988    w.klas  	    */
/* 	$Header: plsync.c,v 1.2 89/02/02 16:21:39 aoki Exp $*/
/* TabWidth 4 */

#include "pladt.h"
#include "plsync.h"
#include "ipci.h"
#include "plparam.h"

#include "ipc.h"

#include "log.h"

void
LtSynchInit(key)
    IPCKey  key;
{
    int	    status;
    
    /* get a semaphore if non-existent */

    Note("LtSynchInit: Initializing the lock table semaphore", LDEBUG);

    LockSemId = IpcSemaphoreCreate(key, 1, IPCProtection, LT_LockStartValue,
    	&status);

    if (0) {	/* XXX use validity function and check status */
    	elog(FATAL, "LtSynchInit: %m");
    	}
}

void
LtSynchKill(key)
    IPCKey  key;
{
    /* kill semaphore if existent */

    Note("LtSynchKill: Killing the lock table semaphore", LDEBUG);
    
    IpcSemaphoreKill(key);
}

/*
 * XXX LtReadLock, LtWriteLock, etc. should call generic functions in ipc/ipc.c.
 */
void
LtReadLock()
{
    int	    status;
    struct sembuf   sops;

    sops.sem_op = LT_SharedLock;
    sops.sem_flg = 0;
    sops.sem_num = 0;

    status = semop(LockSemId, (struct sembuf **)&sops, 1);
    if (status == -1) {
    	perror("semop");
    	exit(255);
    }
}

void
LtWriteLock(xid)
TransactionId	xid;
{
    int	    status;
    struct sembuf   sops;

    sops.sem_op = LT_ExclusiveLock;
    sops.sem_flg = 0;
    sops.sem_num = 0;
    
    Note("LtWriteLock: WriteLock request    ", LOCK, xid);
    status = semop(LockSemId, (struct sembuf **)&sops, 1);
    Note("LtWriteLock: WriteLock request got", LOCK, xid);
    if (status == -1) {
    	perror("semop");
    	exit(255);
    }
}

void
LtReadUnlock()
{
    int	    status;
    struct sembuf   sops;

    sops.sem_op = -LT_SharedLock;
    sops.sem_flg = 0;
    sops.sem_num = 0;

    status = semop(LockSemId, (struct sembuf **)&sops, 1);
    if (status == -1) {
    	perror("semop");
    	exit(255);
    }
}

void
LtWriteUnlock(xid)
TransactionId	xid;
{
    int	    status;
    struct sembuf   sops;

    sops.sem_op = -LT_ExclusiveLock;
    sops.sem_flg = 0;
    sops.sem_num = 0;

    Note("LtWriteUnlock: WriteUnlock request    ", LOCK, xid);
    status = semop(LockSemId, (struct sembuf **)&sops, 1);
    Note("LtWriteUnlock: WriteUnlock request got", LOCK, xid);
    if (status == -1) {
    	perror("semop");
    	exit(255);
    }
}



void
LtSyncInteractOn()
{   SynchInteraction = 1;
    return;
}


void
LtSyncInteractOff()
{   SynchInteraction = 0;
    return;
}


int
LtSyncInteractIsOn()
{
    return(SynchInteraction);
}

void
LtSyncWait()
{
    int	    	c;
    int	    	*ptr;
    
    if (LtSyncInteractIsOn()) {
    	ptr = (int *) malloc(sizeof(int));
    	Note("LtSyncWait: waiting: <CONTINUE>", LDEBUG);
    	fprintf(stdout, "Waiting: <CONTINUE>: \n");
    	c = fread(ptr, 1, 1, stdin);
    	Note("LtSyncWait: continue execution", LDEBUG);
    }
    return;
}


void
LtTransactionSemaphoreInit(key)
    IPCKey  key;
{
    int	status;

    /* get a set of semaphores if non-existent	*/
    	Note("LtTransactionSemaphoreInit: Initializing the set of semaphores for transactions", LDEBUG);

    	TransactionSemId = IpcSemaphoreCreate(key, NMAXSEM, IPCProtection,
    	PLT_LockStartValue, &status);

    if (0) {	/* XXX use validity function and check status */
    	elog(FATAL, "LtTransactionSemaphoreInit: %m");
    	}
}


void
LtTransactionSemaphoreKill(key)
    IPCKey  key;
{
    /* kill semaphore if existent */

    Note("LtTransactionSemaphoreKill: Killing the set of semaphores", LDEBUG);
    
    IpcSemaphoreKill(key);
}








int
LtSemaphoreManipulate(semNum, type, mode)
SemId	    	    semNum;
LockType    	type;
SemManipulationMode mode;
{
    int	    status;
    struct sembuf   sops;

    switch (type) {
    case PageLockRequest_Share:
    	    	if (mode == PLT_SemLock) {
    	    	    sops.sem_op = PLT_SharedLock;
    	    	} else {
    	    	    sops.sem_op = -PLT_SharedLock;
    	    	}
    	    	break;
    case PageLockRequest_Exclusive: 
    	    	if (mode == PLT_SemLock) {
    	    	    sops.sem_op = PLT_ExclusiveLock;
    	    	} else {
    	    	    sops.sem_op = -PLT_ExclusiveLock;
    	    	}
    	    	break;
    case MultiLevelLockRequest_ReadRelation:
    case MultiLevelLockRequest_IntentReadRelation:
    case MultiLevelLockRequest_ReadPage:
    case MultiLevelLockRequest_IntentReadPage:
    case MultiLevelLockRequest_ReadLine:
    case MultiLevelLockRequest_IntentReadLine:
               if (mode == PLT_SemLock) {
    	    	    sops.sem_op = PLT_SharedLock;
    	    	} else {
    	    	    sops.sem_op = -PLT_SharedLock;
    	    	}
    	    	break;
    case MultiLevelLockRequest_WriteRelation:
    case MultiLevelLockRequest_IntentWriteRelation:
    case MultiLevelLockRequest_WritePage:
    case MultiLevelLockRequest_IntentWritePage:
    case MultiLevelLockRequest_WriteLine:
    case MultiLevelLockRequest_IntentWriteLine:
               if (mode == PLT_SemLock) {
    	    	    sops.sem_op = PLT_ExclusiveLock;
    	    	} else {
    	    	    sops.sem_op = -PLT_ExclusiveLock;
    	    	}
    	    	break;
    default: Note("LtSemaphoreManipulate: Don't know how to manipulate the semaphore", DEBERR);
    }
    sops.sem_flg = 0;
    sops.sem_num = semNum;
    status = semop(TransactionSemId, (struct sembuf **)&sops, 1);
    if (status == -1) {
    	perror("semop");
    	exit(255);
    }	
}
